1 | <?php |
||
2 | |||
3 | /* For licensing terms, see /license.txt */ |
||
4 | |||
5 | use ChamiloSession as Session; |
||
6 | |||
7 | /** |
||
8 | * This class allows you to display a sortable data-table. It is possible to |
||
9 | * split the data in several pages. |
||
10 | * Using this class you can: |
||
11 | * - automatically create checkboxes of the first table column |
||
12 | * - a "select all" and "deselect all" link is added |
||
13 | * - only if you provide a list of actions for the selected items |
||
14 | * - click on the table header to sort the data |
||
15 | * - choose how many items you see per page |
||
16 | * - navigate through all data-pages. |
||
17 | */ |
||
18 | class SortableTable extends HTML_Table |
||
19 | { |
||
20 | /** |
||
21 | * A name for this table. |
||
22 | */ |
||
23 | public $table_name; |
||
24 | /** |
||
25 | * The page to display. |
||
26 | */ |
||
27 | public $page_nr; |
||
28 | /** |
||
29 | * The column to sort the data. |
||
30 | */ |
||
31 | public $column; |
||
32 | /** |
||
33 | * The sorting direction (ASC or DESC). |
||
34 | */ |
||
35 | public $direction; |
||
36 | /** |
||
37 | * Number of items to display per page. |
||
38 | */ |
||
39 | public $per_page; |
||
40 | /** |
||
41 | * The default number of items to display per page. |
||
42 | */ |
||
43 | public $default_items_per_page; |
||
44 | /** |
||
45 | * A prefix for the URL-parameters, can be used on pages with multiple |
||
46 | * SortableTables. |
||
47 | */ |
||
48 | public $param_prefix; |
||
49 | /** |
||
50 | * The pager object to split the data in several pages. |
||
51 | */ |
||
52 | public $pager; |
||
53 | /** |
||
54 | * The total number of items in the table. |
||
55 | */ |
||
56 | public $total_number_of_items; |
||
57 | /** |
||
58 | * The function to get the total number of items. |
||
59 | */ |
||
60 | public $get_total_number_function; |
||
61 | /** |
||
62 | * The function to the the data to display. |
||
63 | */ |
||
64 | public $get_data_function; |
||
65 | /** |
||
66 | * An array with defined column-filters. |
||
67 | */ |
||
68 | public $column_filters; |
||
69 | /** |
||
70 | * A list of actions which will be available through a select list. |
||
71 | */ |
||
72 | public $form_actions; |
||
73 | /** |
||
74 | * Additional parameters to pass in the URL. |
||
75 | */ |
||
76 | public $additional_parameters; |
||
77 | /** |
||
78 | * Additional attributes for the th-tags. |
||
79 | */ |
||
80 | public $th_attributes; |
||
81 | /** |
||
82 | * Additional attributes for the td-tags. |
||
83 | */ |
||
84 | public $td_attributes; |
||
85 | /** |
||
86 | * Array with names of the other tables defined on the same page of this |
||
87 | * table. |
||
88 | */ |
||
89 | public $other_tables; |
||
90 | /** |
||
91 | * Activates the odd even rows. |
||
92 | * */ |
||
93 | public $odd_even_rows_enabled = true; |
||
94 | public $use_jqgrid = false; |
||
95 | public $table_id = null; |
||
96 | public $headers = []; |
||
97 | public $actionButtons = []; |
||
98 | /** |
||
99 | * The array containing all data for this table. |
||
100 | */ |
||
101 | public $table_data; |
||
102 | public $hideItemSelector; |
||
103 | // Hide table navigation, better to be use when exporting table to PDF. |
||
104 | public $hideNavigation = false; |
||
105 | |||
106 | /** |
||
107 | * @var array Columns to hide |
||
108 | */ |
||
109 | private $columnsToHide = []; |
||
110 | private $dataFunctionParams; |
||
111 | private $defaultColumn; |
||
112 | private $defaultItemsPerPage; |
||
113 | |||
114 | /** |
||
115 | * Create a new SortableTable. |
||
116 | * |
||
117 | * @param string $table_name A name for the table (default = 'table') |
||
118 | * @param string $get_total_number_function A user defined function to get |
||
119 | * the total number of items in the table |
||
120 | * @param string $get_data_function A function to get the data to display on |
||
121 | * the current page |
||
122 | * @param int $default_column The default column on which the data should be |
||
123 | * sorted |
||
124 | * @param int $default_items_per_page The default number of items to show |
||
125 | * on one page |
||
126 | * @param string $default_order_direction The default order direction; |
||
127 | * either the constant 'ASC' or 'DESC' |
||
128 | * @param string $table_id |
||
129 | * @param array $attributes They are custom attributes of the table |
||
130 | */ |
||
131 | public function __construct( |
||
132 | $table_name = 'table', |
||
133 | $get_total_number_function = null, |
||
134 | $get_data_function = null, |
||
135 | $default_column = 1, |
||
136 | $default_items_per_page = 20, |
||
137 | $default_order_direction = 'ASC', |
||
138 | $table_id = null, |
||
139 | $attributes = [] |
||
140 | ) { |
||
141 | if (empty($table_id)) { |
||
142 | $table_id = $table_name.uniqid('table', true); |
||
143 | } |
||
144 | |||
145 | if (empty($attributes)) { |
||
146 | $attributes = []; |
||
147 | $attributes['class'] = 'table table-hover table-striped table-bordered data_table'; |
||
148 | $attributes['id'] = $table_id; |
||
149 | } |
||
150 | |||
151 | $this->table_id = $table_id; |
||
152 | parent::__construct($attributes); |
||
153 | $this->table_name = $table_name; |
||
154 | $this->additional_parameters = []; |
||
155 | $this->param_prefix = $table_name.'_'; |
||
156 | $this->defaultColumn = (int) $default_column; |
||
157 | $this->defaultItemsPerPage = $default_items_per_page; |
||
158 | $this->hideItemSelector = false; |
||
159 | |||
160 | $defaultRow = api_get_configuration_value('table_default_row'); |
||
161 | if (!empty($defaultRow)) { |
||
162 | $this->defaultItemsPerPage = $default_items_per_page = $defaultRow; |
||
163 | } |
||
164 | |||
165 | $cleanSessionData = Session::read('clean_sortable_table'); |
||
166 | if (true === $cleanSessionData) { |
||
167 | $this->cleanUrlSessionParams(); |
||
168 | } |
||
169 | |||
170 | // Allow to change paginate in multiples tabs |
||
171 | $this->per_page = Session::read($this->param_prefix.'per_page', $default_items_per_page); |
||
172 | |||
173 | // If per page changed, then reset the page to 1 |
||
174 | if (!empty($this->per_page) && isset($_GET[$this->param_prefix.'per_page']) && |
||
175 | $this->per_page != $_GET[$this->param_prefix.'per_page'] |
||
176 | ) { |
||
177 | Session::erase($this->param_prefix.'page_nr'); |
||
178 | $_GET[$this->param_prefix.'page_nr'] = 1; |
||
179 | } |
||
180 | |||
181 | $this->per_page = isset($_GET[$this->param_prefix.'per_page']) |
||
182 | ? (int) $_GET[$this->param_prefix.'per_page'] |
||
183 | : $this->per_page; |
||
184 | |||
185 | if (isset($_GET[$this->param_prefix.'per_page'])) { |
||
186 | Session::erase($this->param_prefix.'page_nr'); |
||
187 | } |
||
188 | |||
189 | $this->page_nr = Session::read($this->param_prefix.'page_nr', 1); |
||
190 | $this->page_nr = isset($_GET[$this->param_prefix.'page_nr']) |
||
191 | ? (int) $_GET[$this->param_prefix.'page_nr'] |
||
192 | : $this->page_nr; |
||
193 | |||
194 | $this->column = Session::read($this->param_prefix.'column', $default_column); |
||
195 | $this->column = isset($_GET[$this->param_prefix.'column']) |
||
196 | ? (int) $_GET[$this->param_prefix.'column'] |
||
197 | : $this->column; |
||
198 | |||
199 | // Default direction. |
||
200 | if (in_array(strtoupper($default_order_direction), ['ASC', 'DESC'])) { |
||
201 | $this->direction = $default_order_direction; |
||
202 | } |
||
203 | |||
204 | $my_session_direction = Session::read($this->param_prefix.'direction'); |
||
205 | if (!empty($my_session_direction)) { |
||
206 | if (!in_array($my_session_direction, ['ASC', 'DESC'])) { |
||
207 | $this->direction = 'ASC'; |
||
208 | } else { |
||
209 | if ('ASC' === $my_session_direction) { |
||
210 | $this->direction = 'ASC'; |
||
211 | } elseif ('DESC' === $my_session_direction) { |
||
212 | $this->direction = 'DESC'; |
||
213 | } |
||
214 | } |
||
215 | } |
||
216 | |||
217 | if (isset($_GET[$this->param_prefix.'direction'])) { |
||
218 | $my_get_direction = $_GET[$this->param_prefix.'direction']; |
||
219 | if (!in_array($my_get_direction, ['ASC', 'DESC'])) { |
||
220 | $this->direction = 'ASC'; |
||
221 | } else { |
||
222 | if ('ASC' === $my_get_direction) { |
||
223 | $this->direction = 'ASC'; |
||
224 | } elseif ('DESC' === $my_get_direction) { |
||
225 | $this->direction = 'DESC'; |
||
226 | } |
||
227 | } |
||
228 | } |
||
229 | |||
230 | Session::write($this->param_prefix.'per_page', $this->per_page); |
||
231 | Session::write($this->param_prefix.'direction', $this->direction); |
||
232 | Session::write($this->param_prefix.'page_nr', $this->page_nr); |
||
233 | Session::write($this->param_prefix.'column', $this->column); |
||
234 | |||
235 | $this->pager = null; |
||
236 | $this->default_items_per_page = $default_items_per_page; |
||
237 | $this->total_number_of_items = -1; |
||
238 | $this->get_total_number_function = $get_total_number_function; |
||
239 | $this->get_data_function = $get_data_function; |
||
240 | $this->column_filters = []; |
||
241 | $this->form_actions = []; |
||
242 | $this->checkbox_name = null; |
||
243 | $this->td_attributes = []; |
||
244 | $this->th_attributes = []; |
||
245 | $this->other_tables = []; |
||
246 | $this->dataFunctionParams = []; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Clean URL params when changing student view. |
||
251 | */ |
||
252 | public function cleanUrlSessionParams() |
||
253 | { |
||
254 | Session::erase('clean_sortable_table'); |
||
255 | |||
256 | $prefix = $this->param_prefix; |
||
257 | |||
258 | Session::erase($prefix.'page_nr'); |
||
259 | Session::erase($prefix.'column'); |
||
260 | Session::erase($prefix.'direction'); |
||
261 | Session::erase($prefix.'per_page'); |
||
262 | |||
263 | $_GET[$this->param_prefix.'per_page'] = $this->default_items_per_page; |
||
264 | $_GET[$this->param_prefix.'page_nr'] = 1; |
||
265 | $_GET[$this->param_prefix.'column'] = $this->defaultColumn; |
||
266 | $_GET[$this->param_prefix.'direction'] = $this->direction; |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * @return array |
||
271 | */ |
||
272 | public function getDataFunctionParams() |
||
273 | { |
||
274 | return $this->dataFunctionParams; |
||
275 | } |
||
276 | |||
277 | /** |
||
278 | * @param array $dataFunctionParams |
||
279 | * |
||
280 | * @return $this |
||
281 | */ |
||
282 | public function setDataFunctionParams($dataFunctionParams) |
||
283 | { |
||
284 | $this->dataFunctionParams = $dataFunctionParams; |
||
285 | |||
286 | return $this; |
||
287 | } |
||
288 | |||
289 | /** |
||
290 | * Get the Pager object to split the showed data in several pages. |
||
291 | * |
||
292 | * @return Pager_Sliding |
||
293 | */ |
||
294 | public function get_pager() |
||
295 | { |
||
296 | if (null === $this->pager) { |
||
297 | $params['mode'] = 'Sliding'; |
||
298 | $params['perPage'] = $this->per_page; |
||
299 | $params['totalItems'] = $this->get_total_number_of_items(); |
||
300 | $params['urlVar'] = $this->param_prefix.'page_nr'; |
||
301 | $params['currentPage'] = $this->page_nr; |
||
302 | $icon_attributes = ['style' => 'vertical-align: middle;']; |
||
303 | $params['prevImg'] = Display:: return_icon( |
||
304 | 'action_prev.png', |
||
305 | get_lang('PreviousPage'), |
||
306 | $icon_attributes |
||
307 | ); |
||
308 | $params['nextImg'] = Display:: return_icon( |
||
309 | 'action_next.png', |
||
310 | get_lang('NextPage'), |
||
311 | $icon_attributes |
||
312 | ); |
||
313 | $params['firstPageText'] = Display:: return_icon( |
||
314 | 'action_first.png', |
||
315 | get_lang('FirstPage'), |
||
316 | $icon_attributes |
||
317 | ); |
||
318 | $params['lastPageText'] = Display:: return_icon( |
||
319 | 'action_last.png', |
||
320 | get_lang('LastPage'), |
||
321 | $icon_attributes |
||
322 | ); |
||
323 | $params['firstPagePre'] = ''; |
||
324 | $params['lastPagePre'] = ''; |
||
325 | $params['firstPagePost'] = ''; |
||
326 | $params['lastPagePost'] = ''; |
||
327 | $params['spacesBeforeSeparator'] = ''; |
||
328 | $params['spacesAfterSeparator'] = ''; |
||
329 | $query_vars = array_keys($_GET); |
||
330 | $query_vars_needed = [ |
||
331 | $this->param_prefix.'column', |
||
332 | $this->param_prefix.'direction', |
||
333 | $this->param_prefix.'per_page', |
||
334 | ]; |
||
335 | if (!empty($this->additional_parameters) && count($this->additional_parameters) > 0) { |
||
336 | $query_vars_needed = array_merge( |
||
337 | $query_vars_needed, |
||
338 | array_keys($this->additional_parameters) |
||
339 | ); |
||
340 | } |
||
341 | $query_vars_exclude = array_diff($query_vars, $query_vars_needed); |
||
342 | |||
343 | $params['excludeVars'] = $query_vars_exclude; |
||
344 | $this->pager = &Pager::factory($params); |
||
345 | } |
||
346 | |||
347 | return $this->pager; |
||
348 | } |
||
349 | |||
350 | /** |
||
351 | * Display the table. |
||
352 | */ |
||
353 | public function display() |
||
354 | { |
||
355 | echo $this->return_table(); |
||
356 | } |
||
357 | |||
358 | public function toArray() |
||
359 | { |
||
360 | $headers = array_column($this->getHeaders(), 'label'); |
||
361 | |||
362 | return array_merge([$headers], $this->table_data); |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Displays the table, complete with navigation buttons to browse through |
||
367 | * the data-pages. |
||
368 | */ |
||
369 | public function return_table() |
||
370 | { |
||
371 | $empty_table = false; |
||
372 | $content = $this->get_table_html(); |
||
373 | if ($this->get_total_number_of_items() == 0) { |
||
374 | $cols = $this->getColCount(); |
||
375 | $this->setCellAttributes( |
||
376 | 1, |
||
377 | 0, |
||
378 | 'style="font-style: italic;text-align:center;" colspan='.$cols |
||
379 | ); |
||
380 | $message_empty = api_xml_http_response_encode(get_lang('TheListIsEmpty')); |
||
381 | $this->setCellContents(1, 0, $message_empty); |
||
382 | $empty_table = true; |
||
383 | } |
||
384 | |||
385 | if ($empty_table) { |
||
386 | return ''; |
||
387 | } |
||
388 | |||
389 | $params = $this->get_sortable_table_param_string().'&'.$this->get_additional_url_paramstring(); |
||
390 | $table_id = 'form_'.$this->table_name.'_id'; |
||
391 | $html = ''; |
||
392 | if (false === $this->hideNavigation) { |
||
393 | $form = $this->get_page_select_form(); |
||
394 | $nav = $this->get_navigation_html(); |
||
395 | |||
396 | $html .= '<div class="table-well">'; |
||
397 | $html .= '<table class="data_table_pagination">'; |
||
398 | $html .= '<tr>'; |
||
399 | $html .= '<td style="width:25%;">'; |
||
400 | $html .= $form; |
||
401 | $html .= '</td>'; |
||
402 | $html .= '<td style="text-align:center;">'; |
||
403 | $html .= $this->get_table_title(); |
||
404 | $html .= '</td>'; |
||
405 | $html .= '<td style="text-align:right;width:25%;">'; |
||
406 | $html .= $nav; |
||
407 | $html .= '</td>'; |
||
408 | $html .= '</tr>'; |
||
409 | $html .= '</table>'; |
||
410 | $html .= '</div>'; |
||
411 | } |
||
412 | |||
413 | if (count($this->form_actions) > 0) { |
||
414 | $html .= '<form |
||
415 | id ="'.$table_id.'" |
||
416 | name="form_'.$this->table_name.'" |
||
417 | class="form-search" |
||
418 | method="post" action="'.api_get_self().'?'.$params.'" >'; |
||
419 | } |
||
420 | |||
421 | $html .= '<div class="table-responsive">'.$content.'</div>'; |
||
422 | |||
423 | if (!empty($this->additional_parameters)) { |
||
424 | foreach ($this->additional_parameters as $key => $value) { |
||
425 | $html .= '<input type="hidden" name ="'.Security::remove_XSS($key).'" value ="' |
||
426 | .Security::remove_XSS($value).'" />'; |
||
427 | } |
||
428 | } |
||
429 | $html .= '<input type="hidden" name="action">'; |
||
430 | |||
431 | $showFooter = count($this->actionButtons) > 0 || |
||
432 | count($this->form_actions) > 0 || |
||
433 | $this->get_total_number_of_items() > $this->default_items_per_page; |
||
434 | |||
435 | if ($showFooter) { |
||
436 | $html .= '<div class="table-well">'; |
||
437 | $html .= '<table class="data_table_pagination">'; |
||
438 | $html .= '<tr>'; |
||
439 | $html .= '<td>'; |
||
440 | |||
441 | if (count($this->actionButtons) > 0) { |
||
442 | $html .= '<div class="btn-toolbar">'; |
||
443 | $html .= '<div class="btn-group">'; |
||
444 | |||
445 | foreach ($this->actionButtons as $action => $data) { |
||
446 | $label = $data['label']; |
||
447 | $icon = $data['icon']; |
||
448 | $html .= '<a class="btn btn-default" href="?'.$params.'&action_table='.$action.'" >'.$icon.' ' |
||
449 | .$label.'</a>'; |
||
450 | } |
||
451 | $html .= '</div>'; //btn-group |
||
452 | $html .= '</div>'; //toolbar |
||
453 | } |
||
454 | |||
455 | if (count($this->form_actions) > 0) { |
||
456 | $html .= '<div class="btn-toolbar">'; |
||
457 | $html .= '<div class="btn-group">'; |
||
458 | $html .= '<a class="btn btn-default" href="?'.$params.'&'.$this->param_prefix |
||
459 | .'selectall=1" onclick="javascript: setCheckbox(true, \''.$table_id.'\'); return false;">' |
||
460 | .get_lang('SelectAll').'</a>'; |
||
461 | $html .= '<a class="btn btn-default" href="?'.$params |
||
462 | .'" onclick="javascript: setCheckbox(false, \''.$table_id.'\'); return false;">' |
||
463 | .get_lang('UnSelectAll').'</a> '; |
||
464 | $html .= '</div>'; |
||
465 | $html .= '<div class="btn-group"> |
||
466 | <button class="btn btn-default" type="button">'.get_lang('Actions').'</button> |
||
467 | <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown"> |
||
468 | <span class="caret"></span> |
||
469 | </button>'; |
||
470 | $html .= '<ul class="dropdown-menu">'; |
||
471 | foreach ($this->form_actions as $action => &$label) { |
||
472 | $html .= '<li><a data-action ="'.$action |
||
473 | .'" href="#" onclick="javascript:action_click(this, \''.$table_id.'\');">'.$label.'</a></li>'; |
||
474 | } |
||
475 | $html .= '</ul>'; |
||
476 | $html .= '</div>'; //btn-group |
||
477 | $html .= '</div>'; //toolbar |
||
478 | } |
||
479 | |||
480 | $html .= '</td>'; |
||
481 | // Pagination |
||
482 | if ($this->get_total_number_of_items() > $this->default_items_per_page) { |
||
483 | $html .= '<td class="text-right">'; |
||
484 | $html .= $nav; |
||
485 | $html .= '</td>'; |
||
486 | } |
||
487 | |||
488 | $html .= '</tr>'; |
||
489 | $html .= '</table>'; |
||
490 | $html .= '</div>'; //toolbar |
||
491 | } |
||
492 | |||
493 | if (count($this->form_actions) > 0) { |
||
494 | $html .= '</form>'; |
||
495 | } |
||
496 | |||
497 | return $html; |
||
498 | } |
||
499 | |||
500 | /** |
||
501 | * This function shows the content of a table in a grid. |
||
502 | * Should not be use to edit information (edit/delete rows) only. |
||
503 | */ |
||
504 | public function display_grid() |
||
505 | { |
||
506 | $empty_table = false; |
||
507 | if ($this->get_total_number_of_items() == 0) { |
||
508 | $message_empty = api_xml_http_response_encode(get_lang('TheListIsEmpty')); |
||
509 | $this->setCellContents(1, 0, $message_empty); |
||
510 | $empty_table = true; |
||
511 | } |
||
512 | $html = ''; |
||
513 | if (!$empty_table) { |
||
514 | $form = $this->get_page_select_form(); |
||
515 | $nav = $this->get_navigation_html(); |
||
516 | |||
517 | // @todo This style css must be moved to default.css only for dev |
||
518 | echo '<style> |
||
519 | .main-grid { width:100%;} |
||
520 | .sub-header { width:100%; padding-top: 10px; padding-right: 10px; padding-left: 10px; height:30px;} |
||
521 | .grid_container { width:100%;} |
||
522 | .grid_item { height: 120px; width:98px; float:left; padding:5px; margin:8px;} |
||
523 | .grid_element_0 { width:100px; height: 100px; float:left; text-align:center; margin-bottom:5px;} |
||
524 | .grid_element_1 { width:100px; float:left; text-align:center;margin-bottom:5px;} |
||
525 | .grid_element_2 { width:150px; float:left;} |
||
526 | .grid_selectbox { width:30%; float:left;} |
||
527 | .grid_title { width:30%; float:left;} |
||
528 | .grid_nav { } |
||
529 | </style>'; |
||
530 | |||
531 | // @todo This also must be moved |
||
532 | // Show only navigations if there are more than 1 page |
||
533 | $my_pager = $this->get_pager(); |
||
534 | $html .= '<div class="main-grid">'; |
||
535 | if ($my_pager->numPages() > 1) { |
||
536 | $html .= '<div class="sub-header">'; |
||
537 | $html .= '<div class="grid_selectbox">'.$form.'</div>'; |
||
538 | $html .= '<div class="grid_title">'.$this->get_table_title().'</div>'; |
||
539 | $html .= '<div class="grid_nav">'.$nav.'</div>'; |
||
540 | $html .= '</div>'; |
||
541 | } |
||
542 | |||
543 | $html .= '<div class="clear"></div>'; |
||
544 | if (count($this->form_actions) > 0) { |
||
545 | $params = $this->get_sortable_table_param_string().'&'.$this->get_additional_url_paramstring(); |
||
546 | $html .= '<form method="post" action="'.api_get_self().'?'.$params |
||
547 | .'" name="form_'.$this->table_name.'">'; |
||
548 | } |
||
549 | } |
||
550 | // Getting the items of the table |
||
551 | $items = $this->get_clean_html(false); //no sort |
||
552 | |||
553 | // Generation of style classes must be improved. Maybe we need a a table name to create style on the fly: |
||
554 | // i.e: .whoisonline_table_grid_container instead of .grid_container |
||
555 | // where whoisonline is the table's name like drupal's template engine |
||
556 | $html .= '<div class="grid_container">'; |
||
557 | if (is_array($items) && count($items) > 0) { |
||
558 | foreach ($items as &$row) { |
||
559 | $html .= '<div class="grid_item">'; |
||
560 | $i = 0; |
||
561 | foreach ($row as &$element) { |
||
562 | $html .= '<div class="grid_element_'.$i.'">'.$element.'</div>'; |
||
563 | $i++; |
||
564 | } |
||
565 | $html .= '</div>'; |
||
566 | } |
||
567 | } |
||
568 | $html .= '</div>'; //close grid_container |
||
569 | $html .= '</div>'; //close main grid |
||
570 | $html .= '<div class="clear"></div>'; |
||
571 | |||
572 | echo $html; |
||
573 | } |
||
574 | |||
575 | /** |
||
576 | * This function returns the content of a table in a grid |
||
577 | * Should not be use to edit information (edit/delete rows) only. |
||
578 | * |
||
579 | * @param array options of visibility |
||
580 | * @param bool hide navigation optionally |
||
581 | * @param int content per page when show navigation (optional) |
||
582 | * @param bool sort data optionally |
||
583 | * |
||
584 | * @return string grid html |
||
585 | */ |
||
586 | public function display_simple_grid( |
||
587 | $visibility_options, |
||
588 | $hide_navigation = true, |
||
589 | $per_page = 20, |
||
590 | $sort_data = true, |
||
591 | $grid_class = [] |
||
592 | ) { |
||
593 | $empty_table = false; |
||
594 | if ($this->get_total_number_of_items() == 0) { |
||
595 | $message_empty = api_xml_http_response_encode(get_lang('TheListIsEmpty')); |
||
596 | $this->setCellContents(1, 0, $message_empty); |
||
597 | $empty_table = true; |
||
598 | } |
||
599 | $html = ''; |
||
600 | if (!$empty_table) { |
||
601 | // If we show the pagination |
||
602 | if (!$hide_navigation) { |
||
603 | $form = ' '; |
||
604 | |||
605 | if ($this->get_total_number_of_items() > $per_page) { |
||
606 | if ($per_page > 10) { |
||
607 | $form = $this->get_page_select_form(); |
||
608 | } |
||
609 | $nav = $this->get_navigation_html(); |
||
610 | // This also must be moved |
||
611 | $html = '<div class="sub-header">'; |
||
612 | $html .= '<div class="grid_selectbox">'.$form.'</div>'; |
||
613 | $html .= '<div class="grid_title">'.$this->get_table_title().'</div>'; |
||
614 | $html .= '<div class="grid_nav">'.$nav.'</div>'; |
||
615 | $html .= '</div>'; |
||
616 | } |
||
617 | } |
||
618 | |||
619 | $html .= '<div class="clear"></div>'; |
||
620 | if (count($this->form_actions) > 0) { |
||
621 | $params = $this->get_sortable_table_param_string().'&'.$this->get_additional_url_paramstring(); |
||
622 | $html .= '<form method="post" action="'.api_get_self().'?'.$params |
||
623 | .'" name="form_'.$this->table_name.'">'; |
||
624 | } |
||
625 | } |
||
626 | |||
627 | if ($hide_navigation) { |
||
628 | $items = $this->table_data; // This is a faster way to get what we want |
||
629 | } else { |
||
630 | // The normal way |
||
631 | $items = $this->get_clean_html($sort_data); // Getting the items of the table |
||
632 | } |
||
633 | |||
634 | // Generation of style classes must be improved. Maybe we need a a table name to create style on the fly: |
||
635 | // i.e: .whoisonline_table_grid_container instead of .grid_container |
||
636 | // where whoisonline is the table's name like drupal's template engine |
||
637 | |||
638 | if (is_array($visibility_options)) { |
||
639 | $filter = false; // The 2nd condition of the if will be loaded |
||
640 | } else { |
||
641 | $filter = $visibility_options !== false; |
||
642 | } |
||
643 | |||
644 | $item_css_class = $item_css_style = $grid_css_class = $grid_css_style = ''; |
||
645 | if (!empty($grid_class)) { |
||
646 | $grid_css_class = $grid_class['main']['class']; |
||
647 | $item_css_class = $grid_class['item']['class']; |
||
648 | |||
649 | $grid_css_style = isset($grid_class['main']['style']) ? $grid_class['main']['style'] : null; |
||
650 | $item_css_style = isset($grid_class['item']['style']) ? $grid_class['item']['style'] : null; |
||
651 | } |
||
652 | |||
653 | $div = ''; |
||
654 | if (is_array($items) && count($items) > 0) { |
||
655 | foreach ($items as &$row) { |
||
656 | $i = 0; |
||
657 | $rows = ''; |
||
658 | foreach ($row as &$element) { |
||
659 | if ($filter || isset($visibility_options[$i]) && $visibility_options[$i] |
||
660 | ) { |
||
661 | $rows .= '<div class="'.$this->table_name.'_grid_element_'.$i.'">'.$element.'</div>'; |
||
662 | } |
||
663 | $i++; |
||
664 | } |
||
665 | $div .= Display::div( |
||
666 | $rows, |
||
667 | [ |
||
668 | 'class' => $item_css_class.' '.$this->table_name.'_grid_item', |
||
669 | 'style' => $item_css_style, |
||
670 | ] |
||
671 | ); |
||
672 | } |
||
673 | } |
||
674 | |||
675 | $html .= Display::div( |
||
676 | $div, |
||
677 | [ |
||
678 | 'class' => $grid_css_class.' '.$this->table_name.'_grid_container', |
||
679 | 'style' => $grid_css_style, |
||
680 | ] |
||
681 | ); |
||
682 | $html .= '<div class="clear"></div>'; |
||
683 | |||
684 | return $html; |
||
685 | } |
||
686 | |||
687 | /** |
||
688 | * Get the HTML-code with the navigational buttons to browse through the |
||
689 | * data-pages. |
||
690 | */ |
||
691 | public function get_navigation_html() |
||
692 | { |
||
693 | $pager = $this->get_pager(); |
||
694 | $pager_links = $pager->getLinks(); |
||
695 | $nav = $pager_links['first'].' '.$pager_links['back']; |
||
696 | $nav .= ' '.$pager->getCurrentPageId().' / '.$pager->numPages().' '; |
||
697 | $nav .= $pager_links['next'].' '.$pager_links['last']; |
||
698 | |||
699 | return $nav; |
||
700 | } |
||
701 | |||
702 | /** |
||
703 | * Get the HTML-code with the data-table. |
||
704 | */ |
||
705 | public function get_table_html() |
||
706 | { |
||
707 | $pager = $this->get_pager(); |
||
708 | $offset = $pager->getOffsetByPageId(); |
||
709 | $from = $offset[0] - 1; |
||
710 | $table_data = $this->get_table_data($from, $this->per_page, $this->column); |
||
711 | $this->processHeaders(); |
||
712 | if (is_array($table_data)) { |
||
713 | $count = 1; |
||
714 | foreach ($table_data as &$row) { |
||
715 | $row = $this->filter_data($row); |
||
716 | |||
717 | $newRow = []; |
||
718 | if (!empty($this->columnsToHide)) { |
||
719 | $counter = 0; |
||
720 | foreach ($row as $index => $rowInfo) { |
||
721 | if (!isset($this->columnsToHide[$index])) { |
||
722 | $newRow[$counter] = $rowInfo; |
||
723 | $counter++; |
||
724 | } |
||
725 | } |
||
726 | $row = $newRow; |
||
727 | } |
||
728 | $this->addRow($row); |
||
729 | if (isset($row['child_of'])) { |
||
730 | $this->setRowAttributes( |
||
731 | $count, |
||
732 | ['class' => 'hidden hidden_'.$row['child_of']], |
||
733 | true |
||
734 | ); |
||
735 | } |
||
736 | $count++; |
||
737 | } |
||
738 | } |
||
739 | |||
740 | if (true == $this->odd_even_rows_enabled) { |
||
0 ignored issues
–
show
|
|||
741 | $this->altRowAttributes( |
||
742 | 0, |
||
743 | ['class' => 'row_odd'], |
||
744 | ['class' => 'row_even'], |
||
745 | true |
||
746 | ); |
||
747 | } |
||
748 | |||
749 | foreach ($this->th_attributes as $column => $attributes) { |
||
750 | $this->setCellAttributes(0, $column, $attributes); |
||
751 | } |
||
752 | foreach ($this->td_attributes as $column => $attributes) { |
||
753 | $this->setColAttributes($column, $attributes); |
||
754 | } |
||
755 | |||
756 | return $this->toHTML(); |
||
757 | } |
||
758 | |||
759 | /** |
||
760 | * This function return the items of the table. |
||
761 | * |
||
762 | * @param bool true for sorting table data or false otherwise |
||
763 | * |
||
764 | * @return array table row items |
||
765 | */ |
||
766 | public function get_clean_html($sort = true) |
||
767 | { |
||
768 | $pager = $this->get_pager(); |
||
769 | $offset = $pager->getOffsetByPageId(); |
||
770 | $from = $offset[0] - 1; |
||
771 | $table_data = $this->get_table_data($from, null, null, null, $sort); |
||
772 | $new_table_data = []; |
||
773 | if (is_array($table_data)) { |
||
774 | foreach ($table_data as $index => &$row) { |
||
775 | $row = $this->filter_data($row); |
||
776 | $new_table_data[] = $row; |
||
777 | } |
||
778 | } |
||
779 | |||
780 | return $new_table_data; |
||
781 | } |
||
782 | |||
783 | /** |
||
784 | * Get the HTML-code which represents a form to select how many items a page |
||
785 | * should contain. |
||
786 | */ |
||
787 | public function get_page_select_form() |
||
788 | { |
||
789 | $total_number_of_items = $this->get_total_number_of_items(); |
||
790 | if ($total_number_of_items <= $this->default_items_per_page) { |
||
791 | return ''; |
||
792 | } |
||
793 | |||
794 | if (true === $this->hideItemSelector) { |
||
795 | return ''; |
||
796 | } |
||
797 | |||
798 | $result[] = '<form method="GET" action="'.api_get_self().'" style="display:inline;">'; |
||
799 | $param[$this->param_prefix.'direction'] = $this->direction; |
||
800 | $param[$this->param_prefix.'page_nr'] = $this->page_nr; |
||
801 | $param[$this->param_prefix.'column'] = $this->column; |
||
802 | |||
803 | if (is_array($this->additional_parameters)) { |
||
804 | $param = array_merge($param, $this->additional_parameters); |
||
805 | } |
||
806 | |||
807 | foreach ($param as $key => &$value) { |
||
808 | $result[] = '<input type="hidden" name="'.$key.'" value="'.$value.'"/>'; |
||
809 | } |
||
810 | $result[] = '<select style="width: auto;" class="form-control" name="'.$this->param_prefix |
||
811 | .'per_page" onchange="javascript: this.form.submit();">'; |
||
812 | $list = [10, 20, 50, 100, 500, 1000]; |
||
813 | |||
814 | $rowList = api_get_configuration_value('table_row_list'); |
||
815 | if (!empty($rowList) && isset($rowList['options'])) { |
||
816 | $list = $rowList['options']; |
||
817 | } |
||
818 | |||
819 | foreach ($list as $nr) { |
||
820 | if ($total_number_of_items <= $nr) { |
||
821 | break; |
||
822 | } |
||
823 | $result[] = '<option value="'.$nr.'" '.($nr == $this->per_page ? 'selected="selected"' : '').'>'.$nr |
||
824 | .'</option>'; |
||
825 | } |
||
826 | |||
827 | $result[] = '<option value="'.$total_number_of_items.'" ' |
||
828 | .($total_number_of_items == $this->per_page ? 'selected="selected"' : '') |
||
829 | .'>'.api_ucfirst(get_lang('All')).'</option>'; |
||
830 | //} |
||
831 | $result[] = '</select>'; |
||
832 | $result[] = '<noscript>'; |
||
833 | $result[] = '<button class="btn btn-success" type="submit">'.get_lang('Save').'</button>'; |
||
834 | $result[] = '</noscript>'; |
||
835 | $result[] = '</form>'; |
||
836 | $result = implode("\n", $result); |
||
837 | |||
838 | return $result; |
||
839 | } |
||
840 | |||
841 | /** |
||
842 | * Get the table title. |
||
843 | */ |
||
844 | public function get_table_title() |
||
845 | { |
||
846 | $pager = $this->get_pager(); |
||
847 | $showed_items = $pager->getOffsetByPageId(); |
||
848 | |||
849 | return $showed_items[0].' - '.$showed_items[1].' / '.$this->get_total_number_of_items(); |
||
850 | } |
||
851 | |||
852 | /** |
||
853 | * @return array |
||
854 | */ |
||
855 | public function getHeaders() |
||
856 | { |
||
857 | return $this->headers; |
||
858 | } |
||
859 | |||
860 | /** |
||
861 | * Process headers. |
||
862 | */ |
||
863 | public function processHeaders() |
||
864 | { |
||
865 | $counter = 0; |
||
866 | foreach ($this->headers as $column => $columnInfo) { |
||
867 | $label = $columnInfo['label']; |
||
868 | $sortable = $columnInfo['sortable']; |
||
869 | $th_attributes = $columnInfo['th_attributes']; |
||
870 | $td_attributes = $columnInfo['td_attributes']; |
||
871 | |||
872 | if (!empty($this->columnsToHide)) { |
||
873 | if (isset($this->columnsToHide[$column])) { |
||
874 | continue; |
||
875 | } |
||
876 | } |
||
877 | |||
878 | $column = $counter; |
||
879 | $param['direction'] = 'ASC'; |
||
880 | if ($this->column == $column && 'ASC' == $this->direction) { |
||
881 | $param['direction'] = 'DESC'; |
||
882 | } |
||
883 | |||
884 | $param['page_nr'] = $this->page_nr; |
||
885 | $param['per_page'] = $this->per_page; |
||
886 | $param['column'] = $column; |
||
887 | $link = $label; |
||
888 | if ($sortable) { |
||
889 | $link = '<a href="'.api_get_self().'?'.api_get_cidreq().'&'; |
||
890 | foreach ($param as $key => &$value) { |
||
891 | $link .= $this->param_prefix.$key.'='.urlencode($value).'&'; |
||
892 | } |
||
893 | $link .= $this->get_additional_url_paramstring(); |
||
894 | $link .= '">'.$label.'</a>'; |
||
895 | if ($this->column == $column) { |
||
896 | $link .= 'ASC' == $this->direction ? ' ↓' : ' ↑'; |
||
897 | } |
||
898 | } |
||
899 | $this->setHeaderContents(0, $column, $link); |
||
900 | |||
901 | if (!is_null($td_attributes)) { |
||
902 | $this->td_attributes[$column] = $td_attributes; |
||
903 | } |
||
904 | if (!is_null($th_attributes)) { |
||
905 | $this->th_attributes[$column] = $th_attributes; |
||
906 | } |
||
907 | |||
908 | $counter++; |
||
909 | } |
||
910 | } |
||
911 | |||
912 | /** |
||
913 | * Set the header-label. |
||
914 | * |
||
915 | * @param int $column The column number |
||
916 | * @param string $label The label |
||
917 | * @param bool $sortable Is the table sortable by this column? (defatult |
||
918 | * = true) |
||
919 | * @param string $th_attributes Additional attributes for the th-tag of the |
||
920 | * table header |
||
921 | * @param string $td_attributes Additional attributes for the td-tags of the |
||
922 | * column |
||
923 | */ |
||
924 | public function set_header( |
||
925 | $column, |
||
926 | $label, |
||
927 | $sortable = true, |
||
928 | $th_attributes = ['class' => 'th-header'], |
||
929 | $td_attributes = null |
||
930 | ) { |
||
931 | $this->headers[$column] = [ |
||
932 | 'label' => $label, |
||
933 | 'sortable' => $sortable, |
||
934 | 'th_attributes' => $th_attributes, |
||
935 | 'td_attributes' => $td_attributes, |
||
936 | ]; |
||
937 | } |
||
938 | |||
939 | /** |
||
940 | * Get the parameter-string with additional parameters to use in the URLs |
||
941 | * generated by this SortableTable. |
||
942 | */ |
||
943 | public function get_additional_url_paramstring() |
||
944 | { |
||
945 | $param_string_parts = []; |
||
946 | if (is_array($this->additional_parameters) && count($this->additional_parameters) > 0) { |
||
947 | foreach ($this->additional_parameters as $key => $value) { |
||
948 | $param_string_parts[] = urlencode($key).'='.urlencode($value); |
||
949 | } |
||
950 | } |
||
951 | $result = implode('&', $param_string_parts); |
||
952 | foreach ($this->other_tables as $index => &$tablename) { |
||
953 | $param = []; |
||
954 | if (isset($_GET[$tablename.'_direction'])) { |
||
955 | $my_get_direction = $_GET[$tablename.'_direction']; |
||
956 | if (!in_array($my_get_direction, ['ASC', 'DESC'])) { |
||
957 | $param[$tablename.'_direction'] = 'ASC'; |
||
958 | } else { |
||
959 | $param[$tablename.'_direction'] = $my_get_direction; |
||
960 | } |
||
961 | } |
||
962 | if (isset($_GET[$tablename.'_page_nr'])) { |
||
963 | $param[$tablename.'_page_nr'] = intval($_GET[$tablename.'_page_nr']); |
||
964 | } |
||
965 | if (isset($_GET[$tablename.'_per_page'])) { |
||
966 | $param[$tablename.'_per_page'] = intval($_GET[$tablename.'_per_page']); |
||
967 | } |
||
968 | if (isset($_GET[$tablename.'_column'])) { |
||
969 | $param[$tablename.'_column'] = intval($_GET[$tablename.'_column']); |
||
970 | } |
||
971 | $param_string_parts = []; |
||
972 | foreach ($param as $key => &$value) { |
||
973 | $param_string_parts[] = urlencode($key).'='.urlencode($value); |
||
974 | } |
||
975 | if (count($param_string_parts) > 0) { |
||
976 | $result .= '&'.implode('&', $param_string_parts); |
||
977 | } |
||
978 | } |
||
979 | |||
980 | return $result; |
||
981 | } |
||
982 | |||
983 | /** |
||
984 | * Get the parameter-string with the SortableTable-related parameters to use |
||
985 | * in URLs. |
||
986 | */ |
||
987 | public function get_sortable_table_param_string() |
||
988 | { |
||
989 | $param[$this->param_prefix.'direction'] = $this->direction; |
||
990 | $param[$this->param_prefix.'page_nr'] = $this->page_nr; |
||
991 | $param[$this->param_prefix.'per_page'] = $this->per_page; |
||
992 | $param[$this->param_prefix.'column'] = $this->column; |
||
993 | $param_string_parts = []; |
||
994 | foreach ($param as $key => &$value) { |
||
995 | $param_string_parts[] = urlencode($key).'='.urlencode($value); |
||
996 | } |
||
997 | $res = implode('&', $param_string_parts); |
||
998 | |||
999 | return $res; |
||
1000 | } |
||
1001 | |||
1002 | /** |
||
1003 | * Add a filter to a column. If another filter was already defined for the |
||
1004 | * given column, it will be overwritten. |
||
1005 | * |
||
1006 | * @param int $column The number of the column |
||
1007 | * @param string $function The name of the filter-function. This should be a |
||
1008 | * function wich requires 1 parameter and returns the filtered value. |
||
1009 | */ |
||
1010 | public function set_column_filter($column, $function) |
||
1011 | { |
||
1012 | $this->column_filters[$column] = $function; |
||
1013 | } |
||
1014 | |||
1015 | /** |
||
1016 | * List of columns to hide. |
||
1017 | * |
||
1018 | * @param int $column |
||
1019 | */ |
||
1020 | public function setHideColumn($column) |
||
1021 | { |
||
1022 | $this->columnsToHide[$column] = $column; |
||
1023 | } |
||
1024 | |||
1025 | /** |
||
1026 | * Define a list of actions which can be performed on the table-date. |
||
1027 | * If you define a list of actions, the first column of the table will be |
||
1028 | * converted into checkboxes. |
||
1029 | * |
||
1030 | * @param array $actions A list of actions. The key is the name of the |
||
1031 | * action. The value is the label to show in the select-box |
||
1032 | * @param string $checkbox_name The name of the generated checkboxes. The |
||
1033 | * value of the checkbox will be the value of the first column. |
||
1034 | */ |
||
1035 | public function set_form_actions($actions, $checkbox_name = 'id') |
||
1036 | { |
||
1037 | $this->form_actions = $actions; |
||
1038 | $this->checkbox_name = $checkbox_name; |
||
1039 | } |
||
1040 | |||
1041 | /** |
||
1042 | * Define a list of additional parameters to use in the generated URLs |
||
1043 | * <code>$parameters['action'] = 'test'; will be convert in |
||
1044 | * <input type="hidden" name="action" value="test"></code>. |
||
1045 | * |
||
1046 | * @param array $parameters |
||
1047 | */ |
||
1048 | public function set_additional_parameters($parameters) |
||
1049 | { |
||
1050 | $this->additional_parameters = $parameters; |
||
1051 | } |
||
1052 | |||
1053 | /** |
||
1054 | * Set other tables on the same page. |
||
1055 | * If you have other sortable tables on the page displaying this sortable |
||
1056 | * tables, you can define those other tables with this function. If you |
||
1057 | * don't define the other tables, there sorting and pagination will return |
||
1058 | * to their default state when sorting this table. |
||
1059 | * |
||
1060 | * @param array $tablenames an array of table names |
||
1061 | */ |
||
1062 | public function set_other_tables($tablenames) |
||
1063 | { |
||
1064 | $this->other_tables = $tablenames; |
||
1065 | } |
||
1066 | |||
1067 | /** |
||
1068 | * Transform all data in a table-row, using the filters defined by the |
||
1069 | * function set_column_filter(...) defined elsewhere in this class. |
||
1070 | * If you've defined actions, the first element of the given row will be |
||
1071 | * converted into a checkbox. |
||
1072 | * |
||
1073 | * @param array $row a row from the table |
||
1074 | * |
||
1075 | * @return array |
||
1076 | */ |
||
1077 | public function filter_data($row) |
||
1078 | { |
||
1079 | $url_params = $this->get_sortable_table_param_string().'&'.$this->get_additional_url_paramstring(); |
||
1080 | foreach ($this->column_filters as $column => &$function) { |
||
1081 | $firstParam = isset($row[$column]) ? $row[$column] : 0; |
||
1082 | $row[$column] = call_user_func($function, $firstParam, $url_params, $row); |
||
1083 | } |
||
1084 | if (count($this->form_actions) > 0) { |
||
1085 | if (strlen($row[0]) > 0) { |
||
1086 | $row[0] = '<input type="checkbox" name="'.$this->checkbox_name.'[]" value="'.$row[0].'"'; |
||
1087 | if (isset($_GET[$this->param_prefix.'selectall'])) { |
||
1088 | $row[0] .= ' checked="checked"'; |
||
1089 | } |
||
1090 | $row[0] .= '/>'; |
||
1091 | } |
||
1092 | } |
||
1093 | if (is_array($row)) { |
||
1094 | foreach ($row as &$value) { |
||
1095 | if (empty($value)) { |
||
1096 | $value = '-'; |
||
1097 | } |
||
1098 | } |
||
1099 | } |
||
1100 | |||
1101 | return $row; |
||
1102 | } |
||
1103 | |||
1104 | /** |
||
1105 | * Get the total number of items. This function calls the function given as |
||
1106 | * 2nd argument in the constructor of a SortableTable. Make sure your |
||
1107 | * function has the same parameters as defined here. |
||
1108 | */ |
||
1109 | public function get_total_number_of_items() |
||
1110 | { |
||
1111 | if ($this->total_number_of_items == -1 && !is_null($this->get_total_number_function)) { |
||
1112 | $this->total_number_of_items = call_user_func( |
||
1113 | $this->get_total_number_function, |
||
1114 | $this->getDataFunctionParams() |
||
1115 | ); |
||
1116 | } |
||
1117 | |||
1118 | return $this->total_number_of_items; |
||
1119 | } |
||
1120 | |||
1121 | /** |
||
1122 | * @param int $value |
||
1123 | */ |
||
1124 | public function setTotalNumberOfItems($value) |
||
1125 | { |
||
1126 | $this->total_number_of_items = (int) $value; |
||
1127 | } |
||
1128 | |||
1129 | /** |
||
1130 | * Get the data to display. This function calls the function given as |
||
1131 | * 2nd argument in the constructor of a SortableTable. Make sure your |
||
1132 | * function has the same parameters as defined here. |
||
1133 | * |
||
1134 | * @param int $from index of the first item to return |
||
1135 | * @param int $per_page The number of items to return |
||
1136 | * @param int $column The number of the column on which the data should be |
||
1137 | * @param bool $sort Whether to sort or not |
||
1138 | * sorted |
||
1139 | * @param string $direction In which order should the data be sorted (ASC |
||
1140 | * or DESC) |
||
1141 | * |
||
1142 | * @return array |
||
1143 | */ |
||
1144 | public function get_table_data( |
||
1145 | $from = null, |
||
1146 | $per_page = null, |
||
1147 | $column = null, |
||
1148 | $direction = null, |
||
1149 | $sort = null |
||
1150 | ) { |
||
1151 | $data = []; |
||
1152 | if (null !== $this->get_data_function) { |
||
1153 | $data = call_user_func( |
||
1154 | $this->get_data_function, |
||
1155 | $from, |
||
1156 | $this->per_page, |
||
1157 | $this->column, |
||
1158 | $this->direction, |
||
1159 | $this->dataFunctionParams |
||
1160 | ); |
||
1161 | } |
||
1162 | |||
1163 | return $data; |
||
1164 | } |
||
1165 | |||
1166 | /** |
||
1167 | * @param array $data |
||
1168 | */ |
||
1169 | public function setTableData($data) |
||
1170 | { |
||
1171 | $this->table_data = $data; |
||
1172 | } |
||
1173 | } |
||
1174 |
When comparing two booleans, it is generally considered safer to use the strict comparison operator.