Exemplo n.º 1
0
 /**
  * @covers \Kisma\Core\Utility\Inflector::pluralize
  */
 public function testPluralize()
 {
     $_words = array('mouse' => 'mice', 'dizzy' => 'dizzies', 'history' => 'histories', 'child' => 'children', 'quiz' => 'quizzes', 'person' => 'people', 'wart' => 'warts', 'ox' => 'oxen', 'louse' => 'lice', 'matrix' => 'matrices', 'vertex' => 'vertices', 'hive' => 'hives', 'thief' => 'thieves', 'tomato' => 'tomatoes', 'glass' => 'glasses', 'cows' => 'cows', 'geese' => 'geese', 'deer' => 'deer');
     foreach ($_words as $_word => $_expected) {
         $this->assertEquals($_expected, Inflector::pluralize($_word));
     }
 }
Exemplo n.º 2
0
 /**
  * @param int             $code
  * @param string|null     $message
  * @param \Exception|null $previous
  * @param mixed|null      $context
  *
  * @throws \InvalidArgumentException
  */
 public function __construct($code, $message = null, $previous = null, $context = null)
 {
     if (!\Kisma\Core\Enums\HttpResponse::contains($code)) {
         throw new \InvalidArgumentException('The code "' . $code . '" is not a valid HTTP response code.');
     }
     if (null === $message) {
         $message = \Kisma\Core\Utility\Inflector::untag(\Kisma\Core\Enums\HttpResponse::nameOf($code));
     }
     parent::__construct($message, $code, $previous, $context);
 }
Exemplo n.º 3
0
 /**
  * Dynamically generates the object from the declared properties of the given object or array
  *
  * @param array|object $object
  *
  * @return \stdClass
  */
 public static function toObject($object)
 {
     //	If we can't iterate over the thing, we bail
     if (!is_object($object) && !is_array($object) && !$object instanceof \Traversable) {
         return null;
     }
     if (is_array($object)) {
         //	Convert to an object
         $_properties = new \stdClass();
         foreach ($object as $_key => $_value) {
             $_properties->{$_key} = $_value;
         }
     } else {
         $_me = new \ReflectionObject($object);
         $_properties = $_me->getProperties();
     }
     //	We'll return this
     $_obj = new \stdClass();
     if (!empty($_properties)) {
         if (is_object($object)) {
             $_myClass = get_class($object);
         } else {
             $_myClass = '_array_';
         }
         foreach ($_properties as $_property) {
             //	Only want properties of $object hierarchy...
             if (isset($_property->class)) {
                 $_class = new \ReflectionClass($_property->class);
                 if (!empty($_class) && !$_class->isInstance($object) && !$_class->isSubclassOf($_myClass)) {
                     unset($_class);
                     continue;
                 }
                 unset($_class);
             }
             try {
                 $_realPropertyName = $_propertyName = ltrim($_property->name, '_ ');
                 if (false !== strpos($_propertyName, '_')) {
                     $_propertyName = Inflector::tag($_propertyName);
                 }
                 $_getter = 'get' . $_propertyName;
                 if (method_exists($object, $_getter)) {
                     $_propertyValue = $object->{$_getter}();
                     if (!is_scalar($_propertyValue)) {
                         $_propertyValue = self::toObject($_propertyValue);
                     }
                     $_obj->{$_realPropertyName} = $_propertyValue;
                 }
             } catch (\Exception $_ex) {
                 //	Just ignore, not a valid property if we can't read it with a getter
             }
         }
     }
     return $_obj;
 }
Exemplo n.º 4
0
 /**
  * Given a string, return it to neutral format (lowercase, period and underscores)
  *
  * @param string $item  The string to neutralize
  * @param string $strip If provided, it's value is removed from item before it's neutralized.
  *                      Example: "REQUEST_URI" would be "URI" with $strip = "REQUEST_"
  *
  * @return string
  */
 public static function neutralize($item, $strip = null)
 {
     if (is_numeric($item)) {
         return $item;
     }
     if (null !== $strip) {
         $item = str_ireplace($strip, null, $item);
     }
     //	Split by forward slash, backslash, period, or space...
     $_parts = preg_split("/[. \\/\\\\]+/", $item);
     array_walk($_parts, function (&$part) {
         //      Clean
         $part = Inflector::decamelize($part);
     });
     return implode('.', $_parts);
 }
Exemplo n.º 5
0
 /**
  * @param array $schema
  * @param bool  $returnHtml If true, HTML is returned, otherwise an array of fields
  *
  * @return string
  */
 protected static function _buildFormFields($schema, $returnHtml = true)
 {
     $_form = null;
     $_fields = array();
     foreach ($schema as $_field => $_settings) {
         //	No private fields are ever rendered
         if (false !== Option::get($_settings, 'private', false)) {
             continue;
         }
         $_value = Option::get($_settings, 'value', Option::get($_settings, 'default'));
         $_label = Option::get($_settings, 'label', Inflector::display($_field));
         $_labelAttributes = Option::get($_settings, 'label_attributes', array('for' => $_field));
         $_attributes = array_merge(array('name' => $_field, 'id' => $_field), Option::get($_settings, 'attributes', array()));
         if (false !== ($_required = Option::get($_settings, 'required', false))) {
             $_attributes['class'] = HtmlMarkup::addValue(Option::get($_attributes, 'class'), 'required');
         }
         $_form .= HtmlMarkup::label($_labelAttributes, $_label);
         $_fields[$_field]['label'] = array('value' => $_label, 'attributes' => $_labelAttributes);
         switch ($_settings['type']) {
             case 'text':
                 $_form .= HtmlMarkup::tag('textarea', $_attributes, $_value) . PHP_EOL;
                 $_fields[$_field] = array_merge($_fields[$_field], array('type' => 'textarea', 'contents' => $_value), $_attributes);
                 break;
             case 'select':
                 $_attributes['size'] = Option::get($_settings, 'size', 1);
                 $_attributes['value'] = $_value;
                 $_fields[$_field] = array_merge($_fields[$_field], array('type' => 'select', 'data' => Option::get($_settings, 'options', array())), $_attributes);
                 $_form .= HtmlMarkup::select($_fields[$_field]['data'], $_attributes) . PHP_EOL;
                 break;
             default:
                 $_attributes['maxlength'] = Option::get($_settings, 'length');
                 $_attributes['value'] = $_value;
                 $_attributes['type'] = 'text';
                 $_fields[$_field] = array_merge($_fields[$_field], array('type' => 'input', 'value' => $_value), $_attributes);
                 $_form .= HtmlMarkup::tag('input', $_attributes, null, true, true) . PHP_EOL;
                 break;
         }
     }
     return $returnHtml ? $_form : $_fields;
 }
Exemplo n.º 6
0
 public function testServiceRequestEvents()
 {
     //	A post test
     Platform::on('user.list', 'http://dsp.local/web/eventReceiver', static::API_KEY);
     //	An inline test
     Platform::on('user.list', function ($event, $eventName, $dispatcher) {
         $this->assertEquals('user.list', $eventName);
         $this->_actionEventFired = 1;
         echo 'event "user.list" has been fired.';
     }, static::API_KEY);
     $this->_preProcessFired = $this->_postProcessFired = 0;
     $_config = (require dirname(dirname(__DIR__)) . '/config/web.php');
     /** @var \RestController $_controller */
     list($_controller, $_actionId) = Pii::app()->createController('rest/user');
     try {
         $_controller->setService('user');
         $_service = ServiceHandler::getService($_controller->getService());
         $_service->on(PlatformServiceEvents::PRE_PROCESS, function ($event, $eventName, $dispatcher) {
             $this->assertEquals('user.get.pre_process', $eventName);
             $this->_preProcessFired = 1;
         });
         $_service->on(PlatformServiceEvents::POST_PROCESS, function ($event, $eventName, $dispatcher) {
             $this->assertEquals('user.get.post_process', $eventName);
             $this->_postProcessFired = 1;
         });
         //	Test GET
         $_request = Pii::app()->getRequestObject();
         $_request->query->set('app_name', Inflector::neutralize(__CLASS__));
         $_request->overrideGlobals();
         $_response = $_service->processRequest(null, HttpMethod::GET, false);
         $this->assertTrue(is_array($_response) && isset($_response['resource']));
         $this->assertTrue(1 == $this->_preProcessFired && 1 == $this->_postProcessFired && 1 == $this->_actionEventFired);
     } catch (\Exception $ex) {
         RestResponse::sendErrors($ex);
     }
 }
Exemplo n.º 7
0
 /**
  * Merges settings to pre-constructed provider config
  *
  * @param array|ProviderConfigLike $settings
  *
  * @return $this
  */
 public function mergeSettings($settings = array())
 {
     foreach ($settings as $_key => $_value) {
         if (property_exists($this, $_key)) {
             try {
                 Option::set($this, $_key, $_value);
                 unset($settings, $_key);
                 continue;
             } catch (\Exception $_ex) {
                 //	Ignore...
             }
         }
         $_setter = Inflector::tag('set_' . $_key);
         if (method_exists($this, $_setter)) {
             call_user_func(array($this, $_setter), $_value);
             unset($settings, $_key, $_setter);
         }
     }
     return $this;
 }
Exemplo n.º 8
0
 /**
  * @return array
  * @throws DreamFactory\Platform\Exceptions\BadRequestException
  */
 protected function _parseRequest()
 {
     $_resourceId = strtolower(trim(FilterInput::request('resource', null, FILTER_SANITIZE_STRING)));
     $_id = FilterInput::request('id', null, FILTER_SANITIZE_STRING);
     if (empty($_resourceId) || empty($_resourceId) && empty($_id)) {
         throw new BadRequestException(404, 'Not found.');
     }
     //	Handle a plural request
     if (false !== ($_tempId = Inflector::isPlural($_resourceId, true))) {
         $_resourceId = $_tempId;
     }
     $this->setModelClass('DreamFactory\\Platform\\Yii\\Models\\' . Inflector::deneutralize($_resourceId));
     return array($_resourceId, $_id);
 }
Exemplo n.º 9
0
 /**
  * Makes a list of available templates
  *
  * @param string $pattern
  *
  * @return void
  */
 protected static function _loadTemplates($pattern = self::DEFAULT_TEMPLATE_PATTERN)
 {
     if (array() !== (static::$_templateCache = Oasys::getStore()->get('oasys.template_cache', array()))) {
         //	Loaded from cache...
         return;
     }
     $_list = array();
     foreach (static::$_providerPaths as $_path) {
         $_templates = glob($_path . '/Templates/' . $pattern);
         foreach ($_templates as $_template) {
             $_templateName = str_ireplace('.template.php', null, basename($_template));
             $_templateId = Inflector::neutralize($_templateName);
             //	Skip base classes in these directories...
             if ('base_' == substr($_templateId, 0, 4)) {
                 continue;
             }
             $_list[$_templateId] = $_path . '/Templates/' . $_template;
             unset($_template, $_templateId, $_templateName);
         }
         unset($_path, $_templates);
     }
     //	Merge in the found templates
     Oasys::getStore()->set('oasys.template_cache', static::$_templateCache = array_merge(static::$_templateCache, $_list));
     Log::debug('Cached templates: ' . implode(', ', array_keys(static::$_templateCache)));
 }
Exemplo n.º 10
0
 /**
  * @return array
  */
 public function toArray()
 {
     $_properties = array();
     $_mirror = new \ReflectionClass(get_class($this));
     foreach ($_mirror->getMethods() as $_method) {
         $_methodName = $_method->getShortName();
         if ($_method->isPublic() && 'get' == strtolower(substr($_methodName, 0, 3))) {
             $_key = Inflector::neutralize(substr($_methodName, 3));
             $_properties[$_key] = $this->{$_methodName}();
         }
     }
     return $_properties;
 }
Exemplo n.º 11
0
<?php

/**
 * @var WebController           $this
 * @var array                   $schema
 * @var BasePlatformSystemModel $model
 * @var array                   $_formOptions Provided by includer
 * @var array                   $errors       Errors if any
 * @var string                  $resourceName The name of this resource (i.e. App, AppGroup, etc.) Essentially the model name
 * @var string                  $displayName
 * @var array                   $_data_
 */
use DreamFactory\Yii\Utility\BootstrapForm;
use Kisma\Core\Utility\Inflector;
$update = false;
$_form = new BootstrapForm();
$_options = array('breadcrumbs' => array('Admin Dashboard' => '/admin', Inflector::display($resourceName) . 's' => '/admin', $displayName => false));
$_formOptions = $_form->pageHeader($_options);
//	Render the form
$this->renderPartial('_' . $resourceName . '_form', $_data_);
Exemplo n.º 12
0
 /**
  * Creates a generic, consistent event for scripting and notifications
  *
  * The returned array is as follows:
  *
  * array(
  *  //    Basics
  *  'id'                => 'A unique ID assigned to this event',
  *  'name'              => 'event.name',
  *  'trigger'           => '{api_name}/{resource}',
  *  'stop_propagation'  => [true|false],
  *  'dispatcher'        => array(
  *      'id'            => 'A unique ID assigned to the dispatcher of this event',
  *      'type'          => 'The class name of the dispatcher',
  *  ),
  *  //  Information about the triggering request
  *  'request'           => array(
  *      'timestamp'     => 'timestamp of the initial request',
  *      'path'          => '/full/path/that/triggered/event',
  *      'api_name'      =>'The api_name of the called service',
  *      'resource'      => 'The name of the resource requested',
  *      'body'          => 'The body posted as part of the request (possibly normalized by the service)',
  *  ),
  *  //  Information about the outgoing response.
  *  'response' => 'The response body returned to the calling service and eventually to the requesting client.',
  *  //    Access to the platform api
  *  'platform'      => array(
  *      'api'       => [wormhole to inline-REST API],
  *      'config'    => [standard DSP configuration update],
  *      'session'   => [the current session],
  *  ),
  *  'extra' => [Extra information passed by caller],
  * )
  *
  * Note that this structure is not passed to the script verbatim. Portions are extracted and exposed by the
  * Script resource as it sees fit.
  *
  * Please note that the format of the request and response bodies may differ slightly from the format passed in or
  * sent back to the client. Some service handlers normalize the data for convenience, i.e. see
  * BaseDbSvc::_determineRequestMembers().
  *
  * Therefore the data exposed by the event system has been "normalized" to provide a reliable and consistent manner
  * in which to process said data. There should be no need for wasting time trying to determine if your data is
  * "maybe here, or maybe there, or maybe over there even" when received by your event handlers.
  *
  *
  * @param string          $eventName        The event name
  * @param PlatformEvent   $event            The event
  * @param EventDispatcher $dispatcher       The dispatcher of the event
  * @param array           $extra            Any additional data to put into the event structure
  * @param bool            $includeDspConfig If true, the current DSP config is added to container
  * @param bool            $returnJson       If true, the event will be returned as a JSON string, otherwise an
  *                                          array.
  *
  * @return array|string
  */
 public static function normalizeEvent($eventName, PlatformEvent $event, $dispatcher, array $extra = [], $includeDspConfig = true, $returnJson = false)
 {
     static $config = null;
     if (!$config) {
         $config = $includeDspConfig ? \Cache::get(Config::LAST_RESPONSE_CACHE_KEY, false) : false;
     }
     //	Clean up the event extras, remove data portion
     $eventExtras = $event->getData();
     $path = $dispatcher->getPathInfo(true);
     //	Clean up the trigger
     $trigger = false !== strpos($path, 'rest', 0) || false !== strpos($path, '/rest', 0) ? str_replace(['/rest', 'rest'], null, $path) : $path;
     $request = static::buildRequestArray($event);
     $response = $event->getResponseData();
     //	Build the array
     $event = ['id' => $event->getEventId(), 'name' => $eventName, 'timestamp' => date('c', Option::server('REQUEST_TIME_FLOAT', Option::server('REQUEST_TIME', microtime(true)))), 'trigger' => $trigger, 'request_path' => $path, 'stop_propagation' => ArrayUtils::get($eventExtras, 'stop_propagation', false, true), 'dispatcher_id' => spl_object_hash($dispatcher), 'dispatcher_type' => Inflector::neutralize(get_class($dispatcher)), 'extra' => $extra, 'platform' => ['config' => $config, 'session' => static::getCleanedSession()], 'request' => $request, 'response' => $response];
     return $returnJson ? json_encode($event, JSON_UNESCAPED_SLASHES) : $event;
 }
Exemplo n.º 13
0
        $_apps .= HtmlMarkup::tag('option', $_attributes, $_model->name);
        unset($_model);
    }
    unset($_models);
}
$_models = ResourceStore::model('provider')->findAll(array('select' => 'id, provider_name, api_name', 'order' => 'provider_name'));
if (!empty($_models)) {
    $_first = true;
    /** @var Provider[] $_models */
    foreach ($_models as $_model) {
        $_attributes = array('name' => $_model->api_name, 'value' => $_model->api_name, 'data-provider-id' => $_model->id, 'data-provider-tag' => Inflector::neutralize($_model->provider_name) . ':' . $_model->api_name, 'data-profile-resource' => strtolower($_model->provider_name) == 'facebook' ? '/me' : '/user');
        if ($_first) {
            $_attributes['selected'] = 'selected';
            $_first = false;
        }
        $_providers .= HtmlMarkup::tag('option', $_attributes, $_model->api_name . ' (' . Inflector::display($_model->provider_name) . ')');
        $_providerCache->{$_model->api_name} = $_model->getAttributes();
        unset($_model, $_config, $_attributes, $_profileResource);
    }
    unset($_models);
}
//	Default url
$_defaultUrl = '/rest/system/user';
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <title>DreamFactory Portal Sandbox</title>
    <meta charset="utf-8" />
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
Exemplo n.º 14
0
 /**
  * Returns the constant name as a string
  *
  * @param string $constant
  * @param bool   $flipped If false, the $constantValue should contain the constant name and the value will be returned
  * @param bool   $pretty  If true, returned value is prettified (acme.before_event becomes "Acme Before Event")
  *
  * @throws \InvalidArgumentException
  * @return string
  */
 public static function nameOf($constant, $flipped = true, $pretty = true)
 {
     if (in_array($constant, array_keys($_constants = static::getDefinedConstants($flipped)))) {
         return $pretty ? Inflector::display(Inflector::neutralize($_constants[$constant])) : $_constants[$constant];
     }
     throw new \InvalidArgumentException('A constant with the value of "' . $constant . '" does not exist.');
 }
Exemplo n.º 15
0
 /**
  * Load up with presents
  */
 protected function _loadRequest()
 {
     $_goodies = array();
     //	Fill up the bag
     if (isset($_SERVER) && !empty($_SERVER)) {
         foreach ($_SERVER as $_key => $_value) {
             if (false !== stripos($_key, 'HTTP_', 0)) {
                 if (!isset($_goodies['server.headers']) || !is_array($_goodies['server.headers'])) {
                     $_goodies['server.headers'] = array();
                 }
                 $_tag = Inflector::tag($_key, true, 'HTTP_');
                 $_goodies['server.headers'][$_tag] = $_value;
             } else {
                 $_tag = 'server.' . Inflector::tag($_key, true);
                 $_goodies[$_tag] = $_value;
             }
         }
     }
     if (isset($_REQUEST) && !empty($_REQUEST)) {
         foreach ($_REQUEST as $_key => $_value) {
             $_tag = 'request.' . Inflector::tag($_key, true, 'REQUEST_');
             $_goodies[$_tag] = $_value;
         }
     }
     $this->merge($_goodies);
     return true;
 }
Exemplo n.º 16
0
 /**
  * @param string $name Cleans up a user-supplied option key
  *
  * @return string
  */
 protected static function _getKeyTag($name)
 {
     //	If this is an array, apply to all keys
     if (is_array($name)) {
         $_items = array();
         foreach ($name as $_key => $_value) {
             $_items[$_key] = $_value;
         }
         return $_items;
     }
     if (is_string($name)) {
         $_tag = Inflector::neutralize($name);
         if (false === strpos($_tag, CoreSettings::OPTION_KEY_PREFIX, 0)) {
             $_tag = CoreSettings::OPTION_KEY_PREFIX . ltrim($_tag, '.');
         }
         return $_tag;
     }
     //	Dunno, have it back the same I guess...
     return $name;
 }
Exemplo n.º 17
0
 /**
  * Builds a hash of events and handlers that are present in this object based on the event handler signature.
  * This merely builds the hash, nothing is done with it.
  *
  * @param \Kisma\Core\Interfaces\SubscriberLike|string $object     The object or class to scan
  * @param string                                       $pattern    The method listener pattern to scan for
  * @param bool                                         $rediscover By default, the discoverer will not wire up the same object's events more than once.
  *                                                                 Setting $rediscover to TRUE will force the rediscovery of the listeners, if any.
  *                                                                 The default is false.
  *
  * @return array|bool The listeners discovered. True if already discovered, False on error
  */
 public static function _discoverObjectListeners($object, $pattern = self::LISTENER_DISCOVERY_PATTERN, $rediscover = false)
 {
     static $_discovered = array();
     $_listeners = array();
     $_objectId = spl_object_hash(is_string($object) ? '_class.' . $object : $object);
     if (false === $rediscover && isset($_discovered[$_objectId])) {
         return true;
     }
     try {
         $_mirror = new \ReflectionClass($object);
         $_methods = $_mirror->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED);
         //	Check each method for the event handler signature
         foreach ($_methods as $_method) {
             //	Event handler?
             if (0 == preg_match($pattern, $_method->name, $_matches) || empty($_matches[1])) {
                 continue;
             }
             //	Neutralize the name
             $_eventName = Inflector::neutralize($_matches[1]);
             if (!isset($_listeners[$_eventName])) {
                 $_listeners[$_eventName] = array();
             }
             //	Save off a callable
             $_listeners[$_eventName][] = array($object, $_method->name);
             //	Clean up
             unset($_matches, $_method);
         }
         unset($_methods, $_mirror);
         $_discovered[$_objectId] = true;
     } catch (\Exception $_ex) {
         return false;
     }
     //	Return the current map
     return $_listeners;
 }
Exemplo n.º 18
0
Arquivo: Seed.php Projeto: kisma/kisma
 /**
  * When unserializing an object, this will re-attach any event handlers...
  */
 public function __wakeup()
 {
     //	This is my hash. There are many like it, but this one is mine.
     $this->_id = hash('sha256', spl_object_hash($this) . getmypid() . microtime(true));
     //	Auto-set tag and name if empty
     $this->_tag = $this->_tag ?: Inflector::neutralize(get_called_class());
     $this->_name = $this->_name ?: $this->_tag;
     if ($this instanceof SubscriberLike) {
         EventManager::discoverListeners($this);
     }
     //	Publish after_construct event
     if ($this->_enableLifeEvents) {
         $this->trigger(LifeEvents::AFTER_CONSTRUCT);
     }
 }
Exemplo n.º 19
0
 /**
  * @param array $data
  *
  * @return $this
  */
 public function fromArray($data = array())
 {
     foreach ($data as $_key => $_value) {
         //  Event ID cannot be changed
         if ('event_id' != $_key) {
             if (method_exists($this, 'set' . ($_key = Inflector::deneutralize($_key)))) {
                 $this->{'set' . $_key}($_value);
             }
         }
     }
     //  Special propagation stopper
     if (isset($data['stop_propagation']) && false !== $data['stop_propagation']) {
         $this->stopPropagation();
     }
     return $this;
 }
Exemplo n.º 20
0
use DreamFactory\Common\Enums\PageLocation;
use DreamFactory\Platform\Enums\ResponseFormats;
use DreamFactory\Yii\Utility\Pii;
use Kisma\Core\Utility\Inflector;
use Kisma\Core\Utility\Option;
$_state = $_content = $_tabs = null;
Pii::scriptFile('/js/df.datatables.js', PageLocation::End);
//if ( null !== ( $_state = Pii::getState( 'admin.state' ) ) )
$_state = array();
$_class = ' class="active"';
foreach ($resourceColumns as $_resource => $_config) {
    $_html = '<h3>Coming Soon!</h3>';
    $_buttons = $_labels = null;
    $_active = $_resource == 'app' ? ' active' : null;
    //	Get/create a menu name
    $_menuName = Option::get($_config, 'menu_name', Option::get($_config, 'header', Inflector::pluralize($_config['resource'])));
    if (isset($_config['labels']) && !empty($_config['labels'])) {
        $_id = 'tab-' . $_resource;
        $_count = 0;
        foreach ($_config['labels'] as $_label) {
            $_labels .= '<th>' . $_label . '</th>';
            $_count++;
        }
        if (null !== ($_displayName = Option::get($_config, 'display_name'))) {
            $_buttons = '<button class="btn btn-success" id="create-' . $_resource . '">Add ' . $_displayName . '</button>';
        }
        $_html = <<<HTML
<h3>{$_config['header']}<div id="admin-toolbar" class=" pull-right">{$_buttons}</div></h3>
<table class="table table-striped table-hover table-bordered table-resource" id="{$_resource}-table">
<thead>
\t<tr>{$_labels}</tr>