├── .readthedocs.yaml ├── Controller ├── Component │ ├── DataTable │ │ └── DataTableConfig.php │ └── DataTableComponent.php └── DataTableAppController.php ├── Lib └── DataTableRequestHandlerTrait.php ├── Model └── DataTableAppModel.php ├── README.md ├── Test └── Case │ ├── AllTestsTest.php │ └── Controller │ └── Component │ └── DataTableComponentTest.php ├── View ├── DataTableResponseView.php └── Helper │ └── DataTableHelper.php └── composer.json /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the OS, Python version and other tools you might need 9 | build: 10 | os: ubuntu-22.04 11 | tools: 12 | python: "3.12" 13 | # You can also specify other tool versions: 14 | # nodejs: "19" 15 | # rust: "1.64" 16 | # golang: "1.19" 17 | 18 | # Build documentation in the "docs/" directory with Sphinx 19 | sphinx: 20 | configuration: docs/conf.py 21 | 22 | # Optionally build your docs in additional formats such as PDF and ePub 23 | # formats: 24 | # - pdf 25 | # - epub 26 | 27 | # Optional but recommended, declare the Python requirements required 28 | # to build your documentation 29 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html 30 | # python: 31 | # install: 32 | # - requirements: docs/requirements.txt 33 | -------------------------------------------------------------------------------- /Controller/Component/DataTable/DataTableConfig.php: -------------------------------------------------------------------------------- 1 | true, 20 | 'autoRender' => true, 21 | 'columns' => array(), 22 | 'conditions' => array(), 23 | 'maxLimit' => 100, 24 | 'viewVar' => 'dtResults', 25 | 'order' => array(), 26 | ); 27 | 28 | /** 29 | * @var string 30 | */ 31 | protected $_name; 32 | 33 | /** 34 | * @var array 35 | */ 36 | protected $_config; 37 | 38 | /** 39 | * 40 | * @param string $name Name of the config to parse 41 | * @param array $config List of configs 42 | */ 43 | public function __construct($name, $config) { 44 | if (!isset($config[$name])) { 45 | throw new Exception(sprintf('%s: Missing config %s', __CLASS__, $name)); 46 | } 47 | 48 | $this->_name = $name; 49 | $this->_config = array_merge($this->defaults, $config, $config[$name]); 50 | $this->_parse(); 51 | } 52 | 53 | /** 54 | * Returns reference to config values 55 | * 56 | * @return mixed 57 | */ 58 | public function &__get($name) { 59 | return $this->_config[$name]; 60 | } 61 | 62 | /** 63 | * Sets config values 64 | * 65 | * @param string $name 66 | * @param mixed $value 67 | */ 68 | public function __set($name, $value) { 69 | $this->_config[$name] = $value; 70 | } 71 | 72 | /** 73 | * Gets query array 74 | * 75 | * @return array 76 | */ 77 | public function getQuery() { 78 | return array_diff_key($this->_config, array_flip([ 79 | 'columns', 'viewVar', $this->_name 80 | ])); 81 | } 82 | 83 | /** 84 | * Gets count query array 85 | * 86 | * @return array 87 | */ 88 | public function getCountQuery() { 89 | return array_diff_key($this->_config, array_flip([ 90 | 'columns', 'viewVar', 'fields', 'limit', 'offset', $this->_name 91 | ])); 92 | } 93 | 94 | /** 95 | * Converts field to Model.field 96 | * 97 | * @param string $object 98 | * @param string $field 99 | * @return string 100 | */ 101 | protected function _toColumn($alias, $field) { 102 | return (strpos($field, '.') !== false) ? $field : $alias . '.' . $field; 103 | } 104 | 105 | /** 106 | * Parse the config specified 107 | * 108 | * @return void 109 | */ 110 | protected function _parse() { 111 | if (!$this->model) { 112 | $this->model = $this->_name; 113 | } 114 | 115 | if (!$this->view) { 116 | $this->view = $this->_name; 117 | } 118 | 119 | if ($this->scope) { 120 | $this->conditions[] = $this->scope; 121 | } 122 | 123 | $columns = array(); 124 | foreach ($this->columns as $field => $options) { 125 | $useField = !is_null($options); 126 | $enabled = $useField && (!isset($options['useField']) || $options['useField']); 127 | if (is_numeric($field)) { 128 | $field = $options; 129 | $options = array(); 130 | } 131 | if (is_bool($options)) { 132 | $enabled = $options; 133 | $options = array(); 134 | } 135 | $label = Inflector::humanize($field); 136 | if (is_string($options)) { 137 | $label = $options; 138 | $options = array(); 139 | } 140 | $defaults = array( 141 | 'useField' => $useField, 142 | 'label' => $label, 143 | 'bSortable' => $enabled, 144 | 'bSearchable' => $enabled, 145 | ); 146 | $options = array_merge($defaults, (array) $options); 147 | $column = ($options['useField']) ? $this->_toColumn($this->model, $field) : $field; 148 | $columns[$column] = $options; 149 | if ($options['useField']) { 150 | $this->fields[] = $column; 151 | } 152 | } 153 | $this->columns = $columns; 154 | } 155 | } -------------------------------------------------------------------------------- /Controller/Component/DataTableComponent.php: -------------------------------------------------------------------------------- 1 | Controller = $controller; 36 | } 37 | 38 | /** 39 | * Main processing logic for DataTable 40 | * 41 | * @param mixed $object 42 | * @param mixed $scope 43 | * @return DataTableConfig 44 | */ 45 | public function paginate($name = null, $scope = array()) { 46 | if ($name === null) { 47 | $name = $this->Controller->request->params['action']; 48 | } 49 | 50 | $config = new DataTableConfig($name, $this->settings); 51 | $config->conditions = array_merge($config->conditions, $scope); 52 | 53 | $Model = $this->_getModel($config->model); 54 | $iTotalRecords = $Model->find('count', $config->getCountQuery()); 55 | 56 | $this->_sort($config); 57 | $this->_search($config, $Model); 58 | $this->_paginate($config); 59 | 60 | $iTotalDisplayRecords = $Model->find('count', $config->getCountQuery()); 61 | $results = $Model->find('all', $config->getQuery()); 62 | 63 | $aaData = array(); 64 | if ($config->autoData) { 65 | foreach ($results as $result) { 66 | $row = []; 67 | foreach ($config->columns as $column => $options) { 68 | if (!$options['useField']) { 69 | $row[] = null; 70 | } else { 71 | $value = Hash::extract($result, $column); 72 | $row[] = $value ? $value[0] : null; 73 | } 74 | } 75 | $aaData[] = $row; 76 | } 77 | } 78 | 79 | $dataTableData = array( 80 | 'iTotalRecords' => $iTotalRecords, 81 | 'iTotalDisplayRecords' => $iTotalDisplayRecords, 82 | 'sEcho' => (int) Hash::get($this->_getParams(), 'sEcho'), 83 | 'aaData' => $aaData, 84 | ); 85 | 86 | if ($config->autoData && $config->autoRender) { 87 | $this->Controller->viewClass = 'Json'; 88 | $this->Controller->set(compact('dataTableData')); 89 | $this->Controller->set('_serialize', 'dataTableData'); 90 | } else { 91 | $this->Controller->viewClass = 'DataTable.DataTableResponse'; 92 | $this->Controller->view = $config->view; 93 | $this->Controller->set($config->viewVar, $results); 94 | $this->Controller->set(compact('dataTableData')); 95 | } 96 | 97 | return $config; 98 | } 99 | 100 | /** 101 | * Sets view vars needed for the helper 102 | * 103 | * @param array|string $names 104 | * @return void 105 | */ 106 | public function setViewVar($names) { 107 | $dtColumns = array(); 108 | foreach ((array) $names as $name) { 109 | $dtColumns[$name] = (new DataTableConfig($name, $this->settings))->columns; 110 | } 111 | $this->Controller->set(compact('dtColumns')); 112 | } 113 | 114 | /** 115 | * Sets pagination limit and page 116 | * 117 | * @param DataTableConfig $config 118 | * @return void 119 | */ 120 | protected function _paginate(DataTableConfig $config) { 121 | $params = $this->_getParams(); 122 | if (!isset($params['iDisplayLength'], $params['iDisplayStart'])) { 123 | return; 124 | } 125 | 126 | $config->limit = min($params['iDisplayLength'], $config->maxLimit); 127 | $config->offset = $params['iDisplayStart']; 128 | } 129 | 130 | /** 131 | * Adds conditions to filter results 132 | * 133 | * @param DataTableConfig $config 134 | * @param Model $Model 135 | * @return void 136 | */ 137 | protected function _search(DataTableConfig $config, Model $Model) { 138 | $i = 0; 139 | $conditions = array(); 140 | $params = $this->_getParams(); 141 | $searchTerm = Hash::get($params, 'sSearch'); 142 | foreach ($config->columns as $column => $options) { 143 | if ($options['useField']) { 144 | $searchable = $options['bSearchable']; 145 | if ($searchable === false) { 146 | continue; 147 | } 148 | $searchKey = "sSearch_$i"; 149 | $columnSearchTerm = Hash::get($params, $searchKey); 150 | 151 | if ($searchTerm && ($searchable === true || $searchable === DataTableConfig::SEARCH_GLOBAL)) { 152 | $conditions['OR'][] = array("$column LIKE" => '%' . $searchTerm . '%'); 153 | } 154 | if ($columnSearchTerm && ($searchable === true || $searchable === DataTableConfig::SEARCH_COLUMN)) { 155 | $conditions[] = array("$column LIKE" => '%' . $columnSearchTerm . '%'); 156 | } 157 | if (is_callable(array($Model, $searchable))) { 158 | $Model->$searchable($column, $searchTerm, $columnSearchTerm, $config); 159 | } 160 | } 161 | $i++; 162 | } 163 | if (!empty($conditions)) { 164 | $config->conditions['AND'] = Hash::merge((array) Hash::get($config->conditions, 'AND'), $conditions); 165 | } 166 | } 167 | 168 | /** 169 | * Sets sort field and direction 170 | * 171 | * @param DataTableConfig $config 172 | * @return void 173 | */ 174 | protected function _sort(DataTableConfig $config) { 175 | $params = $this->_getParams(); 176 | for ($i = 0; $i < count($config->columns); $i++) { 177 | $sortColKey = "iSortCol_$i"; 178 | if (!isset($params[$sortColKey])) { 179 | continue; 180 | } 181 | 182 | $column = Hash::get(array_keys($config->columns), $params[$sortColKey]); 183 | if (!$column || !$config->columns[$column]['bSortable']) { 184 | continue; 185 | } 186 | 187 | $direction = Hash::get($params, "sSortDir_$i") ?: 'asc'; 188 | $config->order[$column] = in_array(strtolower($direction), array('asc', 'desc')) ? $direction : 'asc'; 189 | } 190 | } 191 | 192 | /** 193 | * Gets the model to be paginated 194 | * 195 | * @param string $model Name of the model to load 196 | * @return Model 197 | */ 198 | protected function _getModel($model) { 199 | $this->Controller->loadModel($model); 200 | return $this->Controller->$model; 201 | } 202 | 203 | /** 204 | * Gets datatable request params 205 | * 206 | * @return array 207 | */ 208 | protected function _getParams() { 209 | $property = $this->Controller->request->is('get') ? 'query' : 'data'; 210 | return $this->Controller->request->$property; 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /Controller/DataTableAppController.php: -------------------------------------------------------------------------------- 1 | request->query('config'); 6 | if (method_exists($this, $config)) { 7 | $this->setAction($config); 8 | return; 9 | } 10 | $this->DataTable->paginate($config); 11 | } 12 | } -------------------------------------------------------------------------------- /Model/DataTableAppModel.php: -------------------------------------------------------------------------------- 1 | = 2.2 6 | * PHP >= 5.4 7 | 8 | # Documentation 9 | Documentation is available on [wiki page](https://github.com/tigrang/cakephp-datatable/wiki) 10 | 11 | Update 02/05/2015 12 | * v2.0.0 released which is not backwards compatible with v1.0.0 13 | * The old master was tagged as v1.0.0 -------------------------------------------------------------------------------- /Test/Case/AllTestsTest.php: -------------------------------------------------------------------------------- 1 | addTestDirectoryRecursive(CakePlugin::path('DataTable') . 'Test' . DS); 12 | return $suite; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Test/Case/Controller/Component/DataTableComponentTest.php: -------------------------------------------------------------------------------- 1 | array( 32 | 'columns' => array( 33 | 'id' => false, 34 | 'title' => 'Post Title', 35 | 'body' => true, 36 | 'created' => array( 37 | 'bSearchable' => false, 38 | ), 39 | 'Action' => null, 40 | ), 41 | ), 42 | ); 43 | 44 | $this->request = new CakeRequest(); 45 | $this->request->query = array( 46 | 'sEcho' => 1, 47 | 'iColumns' => 4, 48 | 'sColumns' => '', 49 | 'iDisplayStart' => 0, 50 | 'iDisplayLength' => 10, 51 | 'mDataProp_0' => 0, 52 | 'mDataProp_1' => 1, 53 | 'mDataProp_2' => 2, 54 | 'mDataProp_3' => 3, 55 | 'sSearch' => '', 56 | 'bRegex' => false, 57 | 'sSearch_0' => '', 58 | 'bRegex_0' => false, 59 | 'bSearchable_0' => true, 60 | 'sSearch_1' => '', 61 | 'bRegex_1' => false, 62 | 'bSearchable_1' => true, 63 | 'sSearch_2' => '', 64 | 'bRegex_2' => false, 65 | 'bSearchable_2' => true, 66 | 'sSearch_3' => '', 67 | 'bRegex_3' => false, 68 | 'bSearchable_3' => true, 69 | 'iSortCol_0' => 0, 70 | 'sSortDir_0' => 'desc', 71 | 'iSortingCols' => 1, 72 | 'bSortable_0' => true, 73 | 'bSortable_1' => true, 74 | 'bSortable_2' => true, 75 | 'bSortable_3' => true, 76 | ); 77 | 78 | $Controller = new Controller($this->request, new CakeResponse()); 79 | $Collection = new ComponentCollection(); 80 | 81 | $this->DataTable = new DataTableComponent($Collection, $settings); 82 | $this->DataTable->initialize($Controller); 83 | } 84 | 85 | /** 86 | * tearDown 87 | * 88 | * @return void 89 | */ 90 | public function tearDown() { 91 | parent::tearDown(); 92 | unset($this->request); 93 | unset($this->DataTable); 94 | } 95 | 96 | /** 97 | * testConfig 98 | * 99 | * @return void 100 | */ 101 | public function testConfig() { 102 | $config = $this->DataTable->paginate('Post'); 103 | 104 | $fields = array( 105 | 'Post.id', 106 | 'Post.title', 107 | 'Post.body', 108 | 'Post.created', 109 | ); 110 | $this->assertEqual($fields, $config->fields); 111 | 112 | $parsedColumnConfig = array( 113 | 'Post.id' => array( 114 | 'useField' => true, 115 | 'label' => 'Id', 116 | 'bSortable' => false, 117 | 'bSearchable' => false 118 | ), 119 | 'Post.title' => array( 120 | 'useField' => true, 121 | 'label' => 'Post Title', 122 | 'bSortable' => true, 123 | 'bSearchable' => true 124 | ), 125 | 'Post.body' => array( 126 | 'useField' => true, 127 | 'label' => 'Body', 128 | 'bSortable' => true, 129 | 'bSearchable' => true 130 | ), 131 | 'Post.created' => array( 132 | 'useField' => true, 133 | 'label' => 'Created', 134 | 'bSortable' => true, 135 | 'bSearchable' => false 136 | ), 137 | 'Action' => array( 138 | 'useField' => false, 139 | 'label' => 'Action', 140 | 'bSortable' => false, 141 | 'bSearchable' => false 142 | ), 143 | ); 144 | 145 | $this->assertEqual($parsedColumnConfig, $config->columns); 146 | } 147 | 148 | /** 149 | * testUnsortableColumn 150 | * 151 | * @return void 152 | */ 153 | public function testUnsortableColumn() { 154 | $this->request->query['iSortCol_0'] = 0; 155 | $config = $this->DataTable->paginate('Post'); 156 | $this->assertEmpty($config->order); 157 | } 158 | 159 | /** 160 | * testSortableColumn 161 | * 162 | * @return void 163 | */ 164 | public function testSortableColumn() { 165 | $this->request->query['iSortCol_0'] = 3; 166 | $this->request->query['iSortDir_0'] = 'desc'; 167 | $config = $this->DataTable->paginate('Post'); 168 | $this->assertEqual(array('Post.created' => 'desc'), $config->order); 169 | } 170 | 171 | /** 172 | * testSearch 173 | * 174 | * @return void 175 | */ 176 | public function testSearch() { 177 | $this->request->query['sSearch_1'] = 'test'; 178 | $config = $this->DataTable->paginate('Post'); 179 | 180 | $conditions = array( 181 | 'OR' => array( 182 | array('Post.body LIKE' => '%test%'), 183 | ), 184 | ); 185 | $this->assertEqual($conditions, $config->conditions); 186 | } 187 | 188 | /** 189 | * testPaginate 190 | * 191 | * @return void 192 | */ 193 | public function testPaginate() { 194 | $config = $this->DataTable->paginate('Post'); 195 | $this->assertEqual(10, $config->limit); 196 | $this->assertEqual(0, $config->offset); 197 | 198 | $this->request->query['iDisplayStart'] = 10; 199 | $config = $this->DataTable->paginate('Post'); 200 | $this->assertEqual(10, $config->limit); 201 | $this->assertEqual(10, $config->offset); 202 | } 203 | } -------------------------------------------------------------------------------- /View/DataTableResponseView.php: -------------------------------------------------------------------------------- 1 | dtResponse = $this->viewVars['dataTableData']; 35 | } 36 | 37 | /** 38 | * Renders file and returns json-encoded response 39 | * 40 | * @param null $view 41 | * @param null $layout 42 | * @return string 43 | */ 44 | public function render($view = null, $layout = null) { 45 | parent::render($view, $layout); 46 | $options = 0; 47 | if (version_compare(PHP_VERSION, '5.4.0', '>=') && Configure::read('debug')) { 48 | $options = JSON_PRETTY_PRINT; 49 | } 50 | return json_encode($this->dtResponse, $options); 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /View/Helper/DataTableHelper.php: -------------------------------------------------------------------------------- 1 | array( 25 | 'class' => 'dataTable', 26 | 'trOptions' => array(), 27 | 'thOptions' => array(), 28 | 'theadOptions' => array(), 29 | 'tbody' => '', 30 | 'tbodyOptions' => array(), 31 | 'tfoot' => '', 32 | 'tfootOptions' => array(), 33 | ), 34 | 'scriptBlock' => 'script', 35 | 'js' => array( 36 | 'aoColumns' => true, 37 | 'sAjaxSource' => array('action' => 'processDataTableRequest'), 38 | 'bServerSide' => true, 39 | ), 40 | ); 41 | 42 | /** 43 | * Table header labels 44 | * 45 | * @var array 46 | */ 47 | protected $_labels = array(); 48 | 49 | /** 50 | * Column data passed from controller 51 | * 52 | * @var array 53 | */ 54 | protected $_dtColumns; 55 | 56 | /** 57 | * Javascript settings for all pagination configs 58 | * 59 | * @var 60 | */ 61 | protected $_dtSettings = array(); 62 | 63 | /** 64 | * Constructor 65 | * 66 | * @param View $View The View this helper is being attached to. 67 | * @param array $settings Configuration settings for the helper. 68 | */ 69 | public function __construct(View $View, $settings = array()) { 70 | parent::__construct($View, $settings); 71 | if (isset($this->_View->viewVars['dtColumns'])) { 72 | foreach ($this->_View->viewVars['dtColumns'] as $config => $columns) { 73 | $this->_parseSettings($config, $columns); 74 | } 75 | } 76 | } 77 | 78 | /** 79 | * Output dataTable settings to script block 80 | * 81 | * @param string $viewFile 82 | */ 83 | public function afterRender($viewFile) { 84 | $jsVar = sprintf('var dataTableSettings = %s;', json_encode($this->_dtSettings)); 85 | $this->scriptBlock($jsVar, array('block' => 'dataTableSettings')); 86 | if ($this->settings['scriptBlock'] !== false) { 87 | $initScript = <<< INIT_SCRIPT 88 | $(document).ready(function() { 89 | $('.dataTable').each(function() { 90 | var table = $(this); 91 | var settings = dataTableSettings[table.attr('data-config')]; 92 | table.dataTable(settings); 93 | }); 94 | }); 95 | INIT_SCRIPT; 96 | $this->scriptBlock($initScript, array('block' => $this->settings['scriptBlock'])); 97 | } 98 | } 99 | 100 | /** 101 | * Renders a DataTable 102 | * 103 | * Options take on the following values: 104 | * - `class` For table. Default: `dataTable` 105 | * - `trOptions` Array of options for tr 106 | * - `thOptions` Array of options for th 107 | * - `theadOptions` Array of options for thead 108 | * - `tbody` Content for tbody 109 | * - `tbodyOptions` Array of options for tbody 110 | * 111 | * The rest of the keys wil be passed as options for the table 112 | * 113 | * @param string $config Config to render 114 | * @param array $options Options for table 115 | * @param array $js Options for js var 116 | * @return string 117 | */ 118 | public function render($config = null, $options = array(), $js = array()) { 119 | if ($config === null) { 120 | $config = current(array_keys($this->request->params['models'])); 121 | } 122 | 123 | $options = array_merge($this->settings['table'], $options); 124 | 125 | $trOptions = $options['trOptions']; 126 | $thOptions = $options['thOptions']; 127 | unset($options['trOptions'], $options['thOptions']); 128 | 129 | $theadOptions = $options['theadOptions']; 130 | $tbodyOptions = $options['tbodyOptions']; 131 | $tfootOptions = $options['tfootOptions']; 132 | unset($options['theadOptions'], $options['tbodyOptions'], $options['tfootOptions']); 133 | 134 | $tbody = $options['tbody']; 135 | $tfoot = $options['tfoot']; 136 | unset($options['tbody'], $options['tfoot']); 137 | 138 | $tableHeaders = $this->tableHeaders($this->_labels[$config], $trOptions, $thOptions); 139 | $tableHead = $this->tag('thead', $tableHeaders, $theadOptions); 140 | $tableBody = $this->tag('tbody', $tbody, $tbodyOptions); 141 | $tableFooter = $this->tag('tfoot', $tfoot, $tfootOptions); 142 | $options['data-config'] = $config; 143 | $table = $this->tag('table', $tableHead . $tableBody . $tableFooter, $options); 144 | $this->jsSettings($config, $js); 145 | 146 | return $table; 147 | } 148 | 149 | /** 150 | * Renders table headers with column-specific attribute support 151 | * 152 | * @param $names 153 | * @param null $trOptions 154 | * @param null $thOptions 155 | * @return string 156 | */ 157 | public function tableHeaders($names, $trOptions = null, $thOptions = null) { 158 | $out = array(); 159 | foreach ($names as $name) { 160 | $arg = $name; 161 | $options = array(); 162 | if (is_array($name)) { 163 | list($arg, $options) = $name; 164 | } 165 | $options = array_merge((array)$thOptions, $options); 166 | $out[] = sprintf($this->_tags['tableheader'], $this->_parseAttributes($options), $arg); 167 | } 168 | return sprintf($this->_tags['tablerow'], $this->_parseAttributes($trOptions), join(' ', $out)); 169 | } 170 | 171 | /** 172 | * Sets label at the given index. 173 | * 174 | * @param string $config 175 | * @param int $index of column to change 176 | * @param string $label new label to be set. `__LABEL__` string will be replaced by the original label 177 | */ 178 | public function setLabel($config, $index, $label) { 179 | $oldLabel = $this->_labels[$config][$index]; 180 | $oldOptions = $options = array(); 181 | if (is_array($oldLabel)) { 182 | list($oldLabel, $oldOptions) = $oldLabel; 183 | } 184 | if (is_array($label)) { 185 | list($label, $options) = $label; 186 | } 187 | $this->_labels[$config][$index] = array( 188 | $this->_parseLabel($label, $oldLabel), 189 | array_merge($oldOptions, $options), 190 | ); 191 | } 192 | 193 | /** 194 | * Returns js settings either as an array or json-encoded string 195 | * 196 | * @param array $settings 197 | * @param bool $encode 198 | * @return array|string 199 | */ 200 | public function jsSettings($config, $settings = array(), $encode = false) { 201 | $settings = array_merge($this->settings['js'], (array)$settings); 202 | if (!empty($settings['bServerSide'])) { 203 | if (!isset($settings['sAjaxSource']) || $settings['sAjaxSource'] === true) { 204 | $settings['sAjaxSource'] = $this->request->here(); 205 | } 206 | if (!is_string($settings['sAjaxSource'])) { 207 | $settings['sAjaxSource']['?']['config'] = $config; 208 | $settings['sAjaxSource'] = Router::url($settings['sAjaxSource']); 209 | } 210 | } 211 | if (isset($settings['aoColumns']) && $settings['aoColumns'] === true) { 212 | $settings['aoColumns'] = $this->_dtColumns[$config]; 213 | } 214 | $this->_dtSettings[$config] = $settings; 215 | return ($encode) ? json_encode($settings) : $settings; 216 | } 217 | 218 | /** 219 | * Parse a label with its options 220 | * 221 | * @param $label 222 | * @param string $oldLabel 223 | * @return string 224 | */ 225 | protected function _parseLabel($label, $oldLabel = '') { 226 | $replacements = array( 227 | '__CHECKBOX__' => '', 228 | '__LABEL__' => $oldLabel, 229 | ); 230 | foreach ($replacements as $search => $replace) { 231 | $label = str_replace($search, $replace, $label); 232 | } 233 | return $label; 234 | } 235 | 236 | /** 237 | * Parse settings 238 | * 239 | * @param string $config 240 | * @param array $columns 241 | * @return array 242 | */ 243 | protected function _parseSettings($config, $columns) { 244 | foreach ($columns as $field => $options) { 245 | if ($options === null) { 246 | $label = $field; 247 | $options = array( 248 | 'bSearchable' => false, 249 | 'bSortable' => false, 250 | ); 251 | } else { 252 | $label = $options['label']; 253 | unset($options['label']); 254 | if (isset($options['bSearchable'])) { 255 | $options['bSearchable'] = (boolean)$options['bSearchable']; 256 | } 257 | } 258 | $this->_labels[$config][] = $this->_parseLabel($label); 259 | $this->_dtColumns[$config][] = $options; 260 | } 261 | return $this->_dtColumns[$config]; 262 | } 263 | } -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tigrang/cakephp-datatable", 3 | "description": "CakePHP DataTable Plugin", 4 | "type": "cakephp-plugin", 5 | "keywords": ["cakephp", "datatable", "table"], 6 | "homepage": "https://github.com/tigrang/cakephp-datatable", 7 | "license": "MIT", 8 | "authors": [ 9 | { 10 | "name": "Tigran Gabrielyan", 11 | "homepage": "https://github.com/tigrang", 12 | "role": "developer" 13 | } 14 | ], 15 | "support": { 16 | "issues": "https://github.com/tigrang/cakephp-datatable/issues", 17 | "source": "https://github.com/tigrang/cakephp-datatable" 18 | }, 19 | "require": { 20 | "php": ">=5.4.0", 21 | "composer/installers": "*" 22 | }, 23 | "extra": { 24 | "installer-name": "DataTable" 25 | }, 26 | "suggest": { 27 | "datatables/datatables": "jQuery Plugin for Displaying Tabular Data" 28 | } 29 | } --------------------------------------------------------------------------------