This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * @copyright Copyright (c) 2015 ublaboo <[email protected]> |
||
5 | * @author Pavel Janda <[email protected]> |
||
6 | * @package Ublaboo |
||
7 | */ |
||
8 | |||
9 | namespace Ublaboo\DataGrid; |
||
10 | |||
11 | use Nette; |
||
12 | use Nette\Application\UI\Form; |
||
13 | use Nette\Application\UI\Link; |
||
14 | use Nette\Application\UI\PresenterComponent; |
||
15 | use Ublaboo\DataGrid\AggregationFunction\TDataGridAggregationFunction; |
||
16 | use Ublaboo\DataGrid\ColumnsSummary; |
||
17 | use Ublaboo\DataGrid\Exception\DataGridColumnNotFoundException; |
||
18 | use Ublaboo\DataGrid\Exception\DataGridException; |
||
19 | use Ublaboo\DataGrid\Exception\DataGridFilterNotFoundException; |
||
20 | use Ublaboo\DataGrid\Exception\DataGridHasToBeAttachedToPresenterComponentException; |
||
21 | use Ublaboo\DataGrid\Filter\IFilterDate; |
||
22 | use Ublaboo\DataGrid\InlineEdit\InlineEdit; |
||
23 | use Ublaboo\DataGrid\Toolbar\ToolbarButton; |
||
24 | use Ublaboo\DataGrid\Utils\ArraysHelper; |
||
25 | use Ublaboo\DataGrid\Utils\Sorting; |
||
26 | |||
27 | /** |
||
28 | * @method onRedraw() |
||
29 | * @method onRender() |
||
30 | * @method onColumnAdd() |
||
31 | */ |
||
32 | 1 | class DataGrid extends Nette\Application\UI\Control |
|
33 | { |
||
34 | 1 | use TDataGridAggregationFunction; |
|
35 | |||
36 | /** |
||
37 | * @var callable[] |
||
38 | */ |
||
39 | public $onRedraw; |
||
40 | |||
41 | /** |
||
42 | * @var callable[] |
||
43 | */ |
||
44 | public $onRender = []; |
||
45 | |||
46 | /** |
||
47 | * @var callable[] |
||
48 | */ |
||
49 | public $onExport; |
||
50 | |||
51 | /** |
||
52 | * @var callable[] |
||
53 | */ |
||
54 | public $onColumnAdd; |
||
55 | |||
56 | /** |
||
57 | * @var callable[] |
||
58 | * @deprecated use $onFiltersAssembled |
||
59 | */ |
||
60 | public $onFiltersAssabled; |
||
61 | |||
62 | /** |
||
63 | * @var callable[] |
||
64 | */ |
||
65 | public $onFiltersAssembled; |
||
66 | |||
67 | /** |
||
68 | * @var string |
||
69 | */ |
||
70 | public static $icon_prefix = 'fa fa-'; |
||
71 | |||
72 | /** |
||
73 | * Default form method |
||
74 | * @var string |
||
75 | */ |
||
76 | public static $form_method = 'post'; |
||
77 | |||
78 | /** |
||
79 | * When set to TRUE, datagrid throws an exception |
||
80 | * when tring to get related entity within join and entity does not exist |
||
81 | * @var bool |
||
82 | */ |
||
83 | public $strict_entity_property = false; |
||
84 | |||
85 | /** |
||
86 | * When set to TRUE, datagrid throws an exception |
||
87 | * when tring to set filter value, that does not exist (select, multiselect, etc) |
||
88 | * @var bool |
||
89 | */ |
||
90 | public $strict_session_filter_values = true; |
||
91 | |||
92 | /** |
||
93 | * @var int |
||
94 | * @persistent |
||
95 | */ |
||
96 | public $page = 1; |
||
97 | |||
98 | /** |
||
99 | * @var int|string |
||
100 | * @persistent |
||
101 | */ |
||
102 | public $per_page; |
||
103 | |||
104 | /** |
||
105 | * @var array |
||
106 | * @persistent |
||
107 | */ |
||
108 | public $sort = []; |
||
109 | |||
110 | /** |
||
111 | * @var array |
||
112 | */ |
||
113 | public $default_sort = []; |
||
114 | |||
115 | /** |
||
116 | * @var array |
||
117 | */ |
||
118 | public $default_filter = []; |
||
119 | |||
120 | /** |
||
121 | * @var bool |
||
122 | */ |
||
123 | public $default_filter_use_on_reset = true; |
||
124 | |||
125 | /** |
||
126 | * @var bool |
||
127 | */ |
||
128 | public $default_sort_use_on_reset = true; |
||
129 | |||
130 | /** |
||
131 | * @var array |
||
132 | * @persistent |
||
133 | */ |
||
134 | public $filter = []; |
||
135 | |||
136 | /** |
||
137 | * @var callable|null |
||
138 | */ |
||
139 | protected $sort_callback = null; |
||
140 | |||
141 | /** |
||
142 | * @var bool |
||
143 | */ |
||
144 | protected $use_happy_components = true; |
||
145 | |||
146 | /** |
||
147 | * @var callable |
||
148 | */ |
||
149 | protected $rowCallback; |
||
150 | |||
151 | /** |
||
152 | * @var array |
||
153 | */ |
||
154 | protected $items_per_page_list; |
||
155 | |||
156 | /** |
||
157 | * @var int |
||
158 | */ |
||
159 | protected $default_per_page; |
||
160 | |||
161 | /** |
||
162 | * @var string |
||
163 | */ |
||
164 | protected $template_file; |
||
165 | |||
166 | /** |
||
167 | * @var Column\IColumn[] |
||
168 | */ |
||
169 | protected $columns = []; |
||
170 | |||
171 | /** |
||
172 | * @var Column\Action[] |
||
173 | */ |
||
174 | protected $actions = []; |
||
175 | |||
176 | /** |
||
177 | * @var GroupAction\GroupActionCollection |
||
178 | */ |
||
179 | protected $group_action_collection; |
||
180 | |||
181 | /** |
||
182 | * @var Filter\Filter[] |
||
183 | */ |
||
184 | protected $filters = []; |
||
185 | |||
186 | /** |
||
187 | * @var Export\Export[] |
||
188 | */ |
||
189 | protected $exports = []; |
||
190 | |||
191 | /** |
||
192 | * @var ToolbarButton[] |
||
193 | */ |
||
194 | protected $toolbar_buttons = []; |
||
195 | |||
196 | /** |
||
197 | * @var DataModel |
||
198 | */ |
||
199 | protected $dataModel; |
||
200 | |||
201 | /** |
||
202 | * @var DataFilter |
||
203 | */ |
||
204 | protected $dataFilter; |
||
205 | |||
206 | /** |
||
207 | * @var string |
||
208 | */ |
||
209 | protected $primary_key = 'id'; |
||
210 | |||
211 | /** |
||
212 | * @var bool |
||
213 | */ |
||
214 | protected $do_paginate = true; |
||
215 | |||
216 | /** |
||
217 | * @var bool |
||
218 | */ |
||
219 | protected $csv_export = true; |
||
220 | |||
221 | /** |
||
222 | * @var bool |
||
223 | */ |
||
224 | protected $csv_export_filtered = true; |
||
225 | |||
226 | /** |
||
227 | * @var bool |
||
228 | */ |
||
229 | protected $sortable = false; |
||
230 | |||
231 | /** |
||
232 | * @var bool |
||
233 | */ |
||
234 | protected $multiSort = false; |
||
235 | |||
236 | /** |
||
237 | * @var string |
||
238 | */ |
||
239 | protected $sortable_handler = 'sort!'; |
||
240 | |||
241 | /** |
||
242 | * @var string |
||
243 | */ |
||
244 | protected $original_template; |
||
245 | |||
246 | /** |
||
247 | * @var array |
||
248 | */ |
||
249 | protected $redraw_item; |
||
250 | |||
251 | /** |
||
252 | * @var mixed |
||
253 | */ |
||
254 | protected $translator; |
||
255 | |||
256 | /** |
||
257 | * @var bool |
||
258 | */ |
||
259 | protected $force_filter_active; |
||
260 | |||
261 | /** |
||
262 | * @var callable |
||
263 | */ |
||
264 | protected $tree_view_children_callback; |
||
265 | |||
266 | /** |
||
267 | * @var callable |
||
268 | */ |
||
269 | protected $tree_view_has_children_callback; |
||
270 | |||
271 | /** |
||
272 | * @var string |
||
273 | */ |
||
274 | protected $tree_view_has_children_column; |
||
275 | |||
276 | /** |
||
277 | * @var bool |
||
278 | */ |
||
279 | protected $outer_filter_rendering = false; |
||
280 | |||
281 | /** |
||
282 | * @var int |
||
283 | */ |
||
284 | protected $outer_filter_columns_count = 2; |
||
285 | |||
286 | /** |
||
287 | * @var bool |
||
288 | */ |
||
289 | protected $collapsible_outer_filters = true; |
||
290 | |||
291 | /** |
||
292 | * @var array |
||
293 | */ |
||
294 | protected $columns_export_order = []; |
||
295 | |||
296 | /** |
||
297 | * @var bool |
||
298 | */ |
||
299 | protected $remember_state = true; |
||
300 | |||
301 | /** |
||
302 | * @var bool |
||
303 | */ |
||
304 | protected $refresh_url = true; |
||
305 | |||
306 | /** |
||
307 | * @var Nette\Http\SessionSection |
||
308 | */ |
||
309 | protected $grid_session; |
||
310 | |||
311 | /** |
||
312 | * @var Column\ItemDetail |
||
313 | */ |
||
314 | protected $items_detail; |
||
315 | |||
316 | /** |
||
317 | * @var array |
||
318 | */ |
||
319 | protected $row_conditions = [ |
||
320 | 'group_action' => false, |
||
321 | 'action' => [], |
||
322 | ]; |
||
323 | |||
324 | /** |
||
325 | * @var array |
||
326 | */ |
||
327 | protected $column_callbacks = []; |
||
328 | |||
329 | /** |
||
330 | * @var bool |
||
331 | */ |
||
332 | protected $can_hide_columns = false; |
||
333 | |||
334 | /** |
||
335 | * @var array |
||
336 | */ |
||
337 | protected $columns_visibility = []; |
||
338 | |||
339 | /** |
||
340 | * @var InlineEdit |
||
341 | */ |
||
342 | protected $inlineEdit; |
||
343 | |||
344 | /** |
||
345 | * @var InlineEdit |
||
346 | */ |
||
347 | protected $inlineAdd; |
||
348 | |||
349 | /** |
||
350 | * @var bool |
||
351 | */ |
||
352 | protected $snippets_set = false; |
||
353 | |||
354 | /** |
||
355 | * @var bool |
||
356 | */ |
||
357 | protected $some_column_default_hide = false; |
||
358 | |||
359 | /** |
||
360 | * @var ColumnsSummary |
||
361 | */ |
||
362 | protected $columnsSummary; |
||
363 | |||
364 | /** |
||
365 | * @var bool |
||
366 | */ |
||
367 | protected $auto_submit = true; |
||
368 | |||
369 | /** |
||
370 | * @var Filter\SubmitButton|NULL |
||
371 | */ |
||
372 | protected $filter_submit_button = null; |
||
373 | |||
374 | /** |
||
375 | * @var bool |
||
376 | */ |
||
377 | protected $has_column_reset = true; |
||
378 | |||
379 | /** |
||
380 | * @var bool |
||
381 | */ |
||
382 | protected $show_selected_rows_count = true; |
||
383 | |||
384 | |||
385 | /** |
||
386 | * @param Nette\ComponentModel\IContainer|NULL $parent |
||
387 | * @param string $name |
||
388 | */ |
||
389 | public function __construct(Nette\ComponentModel\IContainer $parent = null, $name = null) |
||
390 | { |
||
391 | 1 | parent::__construct(); |
|
392 | |||
393 | 1 | if ($parent !== null) { |
|
394 | 1 | $parent->addComponent($this, $name); |
|
395 | } |
||
396 | |||
397 | 1 | $this->monitor('Nette\Application\UI\Presenter'); |
|
398 | |||
399 | /** |
||
400 | * Try to find previous filters, pagination, per_page and other values in session |
||
401 | */ |
||
402 | 1 | $this->onRender[] = [$this, 'findSessionValues']; |
|
403 | 1 | $this->onExport[] = [$this, 'findSessionValues']; |
|
404 | |||
405 | /** |
||
406 | * Find default filter values |
||
407 | */ |
||
408 | 1 | $this->onRender[] = [$this, 'findDefaultFilter']; |
|
409 | 1 | $this->onExport[] = [$this, 'findDefaultFilter']; |
|
410 | |||
411 | /** |
||
412 | * Find default sort |
||
413 | */ |
||
414 | 1 | $this->onRender[] = [$this, 'findDefaultSort']; |
|
415 | 1 | $this->onExport[] = [$this, 'findDefaultSort']; |
|
416 | |||
417 | /** |
||
418 | * Find default items per page |
||
419 | */ |
||
420 | 1 | $this->onRender[] = [$this, 'findDefaultPerPage']; |
|
421 | |||
422 | /** |
||
423 | * Notify about that json js extension |
||
424 | */ |
||
425 | 1 | $this->onFiltersAssembled[] = [$this, 'sendNonEmptyFiltersInPayload']; |
|
426 | 1 | } |
|
427 | |||
428 | |||
429 | /** |
||
430 | * {inheritDoc} |
||
431 | * @return void |
||
432 | */ |
||
433 | public function attached($presenter) |
||
434 | { |
||
435 | 1 | parent::attached($presenter); |
|
436 | |||
437 | 1 | if ($presenter instanceof Nette\Application\UI\Presenter) { |
|
438 | /** |
||
439 | * Get session |
||
440 | */ |
||
441 | 1 | if ($this->remember_state) { |
|
442 | 1 | $this->grid_session = $presenter->getSession($this->getSessionSectionName()); |
|
443 | } |
||
444 | } |
||
445 | 1 | } |
|
446 | |||
447 | |||
448 | /******************************************************************************** |
||
449 | * RENDERING * |
||
450 | ********************************************************************************/ |
||
451 | |||
452 | |||
453 | /** |
||
454 | * Render template |
||
455 | * @return void |
||
456 | */ |
||
457 | public function render() |
||
458 | { |
||
459 | /** |
||
460 | * Check whether datagrid has set some columns, initiated data source, etc |
||
461 | */ |
||
462 | if (!($this->dataModel instanceof DataModel)) { |
||
463 | throw new DataGridException('You have to set a data source first.'); |
||
464 | } |
||
465 | |||
466 | if (empty($this->columns)) { |
||
467 | throw new DataGridException('You have to add at least one column.'); |
||
468 | } |
||
469 | |||
470 | $template = $this->getTemplate(); |
||
471 | $template->setTranslator($this->getTranslator()); |
||
472 | |||
473 | /** |
||
474 | * Invoke possible events |
||
475 | */ |
||
476 | $this->onRender($this); |
||
477 | |||
478 | /** |
||
479 | * Prepare data for rendering (datagrid may render just one item) |
||
480 | */ |
||
481 | $rows = []; |
||
482 | |||
483 | if (!empty($this->redraw_item)) { |
||
484 | $items = $this->dataModel->filterRow($this->redraw_item); |
||
485 | } else { |
||
486 | $items = Nette\Utils\Callback::invokeArgs( |
||
487 | [$this->dataModel, 'filterData'], |
||
488 | [ |
||
489 | $this->getPaginator(), |
||
490 | $this->createSorting($this->sort, $this->sort_callback), |
||
491 | $this->assembleFilters(), |
||
492 | ] |
||
493 | ); |
||
494 | } |
||
495 | |||
496 | $callback = $this->rowCallback ?: null; |
||
497 | $hasGroupActionOnRows = false; |
||
498 | |||
499 | foreach ($items as $item) { |
||
500 | $rows[] = $row = new Row($this, $item, $this->getPrimaryKey()); |
||
501 | |||
502 | if (!$hasGroupActionOnRows && $row->hasGroupAction()) { |
||
503 | $hasGroupActionOnRows = true; |
||
504 | } |
||
505 | |||
506 | if ($callback) { |
||
507 | $callback($item, $row->getControl()); |
||
508 | } |
||
509 | |||
510 | /** |
||
511 | * Walkaround for item snippet - snippet is the <tr> element and its class has to be also updated |
||
512 | */ |
||
513 | if (!empty($this->redraw_item)) { |
||
514 | $this->getPresenter()->payload->_datagrid_redraw_item_class = $row->getControlClass(); |
||
515 | $this->getPresenter()->payload->_datagrid_redraw_item_id = $row->getId(); |
||
516 | } |
||
517 | } |
||
518 | |||
519 | if ($hasGroupActionOnRows) { |
||
520 | $hasGroupActionOnRows = $this->hasGroupActions(); |
||
521 | } |
||
522 | |||
523 | if ($this->isTreeView()) { |
||
524 | $template->add('tree_view_has_children_column', $this->tree_view_has_children_column); |
||
525 | } |
||
526 | |||
527 | $template->rows = $rows; |
||
528 | |||
529 | $template->columns = $this->getColumns(); |
||
530 | $template->actions = $this->actions; |
||
531 | $template->exports = $this->exports; |
||
532 | $template->filters = $this->filters; |
||
533 | $template->toolbar_buttons = $this->toolbar_buttons; |
||
534 | $template->aggregation_functions = $this->getAggregationFunctions(); |
||
535 | $template->multiple_aggregation_function = $this->getMultipleAggregationFunction(); |
||
536 | |||
537 | $template->filter_active = $this->isFilterActive(); |
||
538 | $template->original_template = $this->getOriginalTemplateFile(); |
||
539 | $template->icon_prefix = static::$icon_prefix; |
||
540 | $template->icon_prefix = static::$icon_prefix; |
||
541 | $template->items_detail = $this->items_detail; |
||
542 | $template->columns_visibility = $this->getColumnsVisibility(); |
||
543 | $template->columnsSummary = $this->columnsSummary; |
||
544 | |||
545 | $template->inlineEdit = $this->inlineEdit; |
||
546 | $template->inlineAdd = $this->inlineAdd; |
||
547 | |||
548 | $template->hasGroupActions = $this->hasGroupActions(); |
||
549 | $template->hasGroupActionOnRows = $hasGroupActionOnRows; |
||
550 | |||
551 | /** |
||
552 | * Walkaround for Latte (does not know $form in snippet in {form} etc) |
||
553 | */ |
||
554 | $template->filter = $this['filter']; |
||
555 | |||
556 | /** |
||
557 | * Set template file and render it |
||
558 | */ |
||
559 | $template->setFile($this->getTemplateFile()); |
||
560 | $template->render(); |
||
561 | } |
||
562 | |||
563 | |||
564 | /******************************************************************************** |
||
565 | * ROW CALLBACK * |
||
566 | ********************************************************************************/ |
||
567 | |||
568 | |||
569 | /** |
||
570 | * Each row can be modified with user callback |
||
571 | * @param callable $callback |
||
572 | * @return static |
||
573 | */ |
||
574 | public function setRowCallback(callable $callback) |
||
575 | { |
||
576 | $this->rowCallback = $callback; |
||
577 | |||
578 | return $this; |
||
579 | } |
||
580 | |||
581 | |||
582 | /******************************************************************************** |
||
583 | * DATA SOURCE * |
||
584 | ********************************************************************************/ |
||
585 | |||
586 | |||
587 | /** |
||
588 | * By default ID, you can change that |
||
589 | * @param string $primary_key |
||
590 | * @return static |
||
591 | */ |
||
592 | public function setPrimaryKey($primary_key) |
||
593 | { |
||
594 | if ($this->dataModel instanceof DataModel) { |
||
595 | throw new DataGridException('Please set datagrid primary key before setting datasource.'); |
||
596 | } |
||
597 | |||
598 | $this->primary_key = $primary_key; |
||
599 | |||
600 | return $this; |
||
601 | } |
||
602 | |||
603 | |||
604 | /** |
||
605 | * Set Grid data source |
||
606 | * @param DataSource\IDataSource|array|\Dibi\Fluent|Nette\Database\Table\Selection|\Doctrine\ORM\QueryBuilder $source |
||
607 | * @return static |
||
608 | */ |
||
609 | public function setDataSource($source) |
||
610 | { |
||
611 | 1 | $this->dataModel = new DataModel($source, $this->primary_key); |
|
612 | |||
613 | 1 | $this->dataModel->onBeforeFilter[] = [$this, 'beforeDataModelFilter']; |
|
614 | 1 | $this->dataModel->onAfterFilter[] = [$this, 'afterDataModelFilter']; |
|
615 | 1 | $this->dataModel->onAfterPaginated[] = [$this, 'afterDataModelPaginated']; |
|
616 | |||
617 | 1 | return $this; |
|
618 | } |
||
619 | |||
620 | |||
621 | /** |
||
622 | * @return DataSource\IDataSource|NULL |
||
623 | */ |
||
624 | public function getDataSource() |
||
625 | { |
||
626 | if (!$this->dataModel) { |
||
627 | return null; |
||
628 | } |
||
629 | |||
630 | return $this->dataModel->getDataSource(); |
||
631 | } |
||
632 | |||
633 | |||
634 | /******************************************************************************** |
||
635 | * TEMPLATING * |
||
636 | ********************************************************************************/ |
||
637 | |||
638 | |||
639 | /** |
||
640 | * Set custom template file to render |
||
641 | * @param string $template_file |
||
642 | * @return static |
||
643 | */ |
||
644 | public function setTemplateFile($template_file) |
||
645 | { |
||
646 | $this->template_file = $template_file; |
||
647 | |||
648 | return $this; |
||
649 | } |
||
650 | |||
651 | |||
652 | /** |
||
653 | * Get DataGrid template file |
||
654 | * @return string |
||
655 | * @return static |
||
656 | */ |
||
657 | public function getTemplateFile() |
||
658 | { |
||
659 | return $this->template_file ?: $this->getOriginalTemplateFile(); |
||
660 | } |
||
661 | |||
662 | |||
663 | /** |
||
664 | * Get DataGrid original template file |
||
665 | * @return string |
||
666 | */ |
||
667 | public function getOriginalTemplateFile() |
||
668 | { |
||
669 | return __DIR__ . '/templates/datagrid.latte'; |
||
670 | } |
||
671 | |||
672 | |||
673 | /** |
||
674 | * Tell datagrid wheteher to use or not happy components |
||
675 | * @param bool|NULL $use If not given, return value of static::$use_happy_components |
||
676 | * @return void|bool |
||
677 | */ |
||
678 | public function useHappyComponents($use = null) |
||
679 | { |
||
680 | if ($use === null) { |
||
681 | return $this->use_happy_components; |
||
682 | } |
||
683 | |||
684 | $this->use_happy_components = (bool) $use; |
||
685 | } |
||
686 | |||
687 | |||
688 | /******************************************************************************** |
||
689 | * SORTING * |
||
690 | ********************************************************************************/ |
||
691 | |||
692 | |||
693 | /** |
||
694 | * Set default sorting |
||
695 | * @param array $sort |
||
696 | * @param bool $use_on_reset |
||
697 | * @return static |
||
698 | */ |
||
699 | public function setDefaultSort($sort, $use_on_reset = true) |
||
700 | { |
||
701 | if (is_string($sort)) { |
||
702 | $sort = [$sort => 'ASC']; |
||
703 | } else { |
||
704 | $sort = (array) $sort; |
||
705 | } |
||
706 | |||
707 | $this->default_sort = $sort; |
||
708 | $this->default_sort_use_on_reset = (bool) $use_on_reset; |
||
709 | |||
710 | return $this; |
||
711 | } |
||
712 | |||
713 | |||
714 | /** |
||
715 | * Return default sort for column, if specified |
||
716 | * @param string $columnKey |
||
717 | * @return string|NULL |
||
718 | */ |
||
719 | public function getColumnDefaultSort($columnKey) |
||
720 | { |
||
721 | if (isset($this->default_sort[$columnKey])) { |
||
722 | return $this->default_sort[$columnKey]; |
||
723 | } |
||
724 | |||
725 | return NULL; |
||
726 | } |
||
727 | |||
728 | |||
729 | /** |
||
730 | * User may set default sorting, apply it |
||
731 | * @return void |
||
732 | */ |
||
733 | public function findDefaultSort() |
||
734 | { |
||
735 | 1 | if (!empty($this->sort)) { |
|
736 | return; |
||
737 | } |
||
738 | |||
739 | 1 | if ($this->getSessionData('_grid_has_sorted')) { |
|
740 | return; |
||
741 | } |
||
742 | |||
743 | 1 | if (!empty($this->default_sort)) { |
|
744 | $this->sort = $this->default_sort; |
||
745 | } |
||
746 | |||
747 | 1 | $this->saveSessionData('_grid_sort', $this->sort); |
|
748 | 1 | } |
|
749 | |||
750 | |||
751 | /** |
||
752 | * Set grido to be sortable |
||
753 | * @param bool $sortable |
||
754 | * @return static |
||
755 | */ |
||
756 | public function setSortable($sortable = true) |
||
757 | { |
||
758 | if ($this->getItemsDetail()) { |
||
759 | throw new DataGridException('You can not use both sortable datagrid and items detail.'); |
||
760 | } |
||
761 | |||
762 | $this->sortable = (bool) $sortable; |
||
763 | |||
764 | return $this; |
||
765 | } |
||
766 | |||
767 | |||
768 | /** |
||
769 | * Tell whether DataGrid is sortable |
||
770 | * @return bool |
||
771 | */ |
||
772 | public function isSortable() |
||
773 | { |
||
774 | return $this->sortable; |
||
775 | } |
||
776 | |||
777 | |||
778 | /** |
||
779 | * Enable multi-sorting capability |
||
780 | * @param bool $multiSort |
||
781 | * @return static |
||
782 | */ |
||
783 | public function setMultiSortEnabled($multiSort = true) |
||
784 | { |
||
785 | $this->multiSort = (bool) $multiSort; |
||
786 | |||
787 | return $this; |
||
788 | } |
||
789 | |||
790 | |||
791 | /** |
||
792 | * Tell wether DataGrid can be sorted by multiple columns |
||
793 | * @return bool |
||
794 | */ |
||
795 | public function isMultiSortEnabled() |
||
796 | { |
||
797 | return $this->multiSort; |
||
798 | } |
||
799 | |||
800 | |||
801 | /** |
||
802 | * Set sortable handle |
||
803 | * @param string $handler |
||
804 | * @return static |
||
805 | */ |
||
806 | public function setSortableHandler($handler = 'sort!') |
||
807 | { |
||
808 | $this->sortable_handler = (string) $handler; |
||
809 | |||
810 | return $this; |
||
811 | } |
||
812 | |||
813 | |||
814 | /** |
||
815 | * Return sortable handle name |
||
816 | * @return string |
||
817 | */ |
||
818 | public function getSortableHandler() |
||
819 | { |
||
820 | return $this->sortable_handler; |
||
821 | } |
||
822 | |||
823 | |||
824 | /** |
||
825 | * @param Column $column |
||
826 | * @return array |
||
827 | * @internal |
||
828 | */ |
||
829 | public function getSortNext(\Ublaboo\DataGrid\Column\Column $column) |
||
830 | { |
||
831 | $sort = $column->getSortNext(); |
||
832 | |||
833 | if ($this->isMultiSortEnabled()) { |
||
834 | $sort = array_merge($this->sort, $sort); |
||
835 | } |
||
836 | |||
837 | return array_filter($sort); |
||
838 | } |
||
839 | |||
840 | |||
841 | /** |
||
842 | * @param array $sort |
||
843 | * @param callable|NULL $sort_callback |
||
844 | * @return Sorting |
||
845 | */ |
||
846 | protected function createSorting(array $sort, callable $sort_callback = null) |
||
847 | { |
||
848 | 1 | foreach ($sort as $key => $order) { |
|
849 | unset($sort[$key]); |
||
850 | |||
851 | try { |
||
852 | $column = $this->getColumn($key); |
||
853 | |||
854 | } catch (DataGridColumnNotFoundException $e) { |
||
855 | continue; |
||
856 | } |
||
857 | |||
858 | $sort[$column->getSortingColumn()] = $order; |
||
859 | } |
||
860 | |||
861 | 1 | if (!$sort_callback && isset($column)) { |
|
862 | $sort_callback = $column->getSortableCallback(); |
||
863 | } |
||
864 | |||
865 | 1 | return new Sorting($sort, $sort_callback); |
|
866 | } |
||
867 | |||
868 | |||
869 | /******************************************************************************** |
||
870 | * TREE VIEW * |
||
871 | ********************************************************************************/ |
||
872 | |||
873 | |||
874 | /** |
||
875 | * Is tree view set? |
||
876 | * @return bool |
||
877 | */ |
||
878 | public function isTreeView() |
||
879 | { |
||
880 | return (bool) $this->tree_view_children_callback; |
||
881 | } |
||
882 | |||
883 | |||
884 | /** |
||
885 | * Setting tree view |
||
886 | * @param callable $get_children_callback |
||
887 | * @param string|callable $tree_view_has_children_column |
||
888 | * @return static |
||
889 | */ |
||
890 | public function setTreeView($get_children_callback, $tree_view_has_children_column = 'has_children') |
||
891 | { |
||
892 | if (!is_callable($get_children_callback)) { |
||
893 | throw new DataGridException( |
||
894 | 'Parameters to method DataGrid::setTreeView must be of type callable' |
||
895 | ); |
||
896 | } |
||
897 | |||
898 | if (is_callable($tree_view_has_children_column)) { |
||
899 | $this->tree_view_has_children_callback = $tree_view_has_children_column; |
||
900 | $tree_view_has_children_column = null; |
||
901 | } |
||
902 | |||
903 | $this->tree_view_children_callback = $get_children_callback; |
||
904 | $this->tree_view_has_children_column = $tree_view_has_children_column; |
||
905 | |||
906 | /** |
||
907 | * TUrn off pagination |
||
908 | */ |
||
909 | $this->setPagination(false); |
||
910 | |||
911 | /** |
||
912 | * Set tree view template file |
||
913 | */ |
||
914 | if (!$this->template_file) { |
||
915 | $this->setTemplateFile(__DIR__ . '/templates/datagrid_tree.latte'); |
||
916 | } |
||
917 | |||
918 | return $this; |
||
919 | } |
||
920 | |||
921 | |||
922 | /** |
||
923 | * Is tree view children callback set? |
||
924 | * @return bool |
||
925 | */ |
||
926 | public function hasTreeViewChildrenCallback() |
||
927 | { |
||
928 | return is_callable($this->tree_view_has_children_callback); |
||
929 | } |
||
930 | |||
931 | |||
932 | /** |
||
933 | * @param mixed $item |
||
934 | * @return bool |
||
935 | */ |
||
936 | public function treeViewChildrenCallback($item) |
||
937 | { |
||
938 | return call_user_func($this->tree_view_has_children_callback, $item); |
||
939 | } |
||
940 | |||
941 | |||
942 | /******************************************************************************** |
||
943 | * COLUMNS * |
||
944 | ********************************************************************************/ |
||
945 | |||
946 | |||
947 | /** |
||
948 | * Add text column with no other formating |
||
949 | * @param string $key |
||
950 | * @param string $name |
||
951 | * @param string|null $column |
||
952 | * @return Column\ColumnText |
||
953 | */ |
||
954 | public function addColumnText($key, $name, $column = null) |
||
955 | { |
||
956 | 1 | $this->addColumnCheck($key); |
|
957 | 1 | $column = $column ?: $key; |
|
958 | |||
959 | 1 | return $this->addColumn($key, new Column\ColumnText($this, $key, $column, $name)); |
|
960 | } |
||
961 | |||
962 | |||
963 | /** |
||
964 | * Add column with link |
||
965 | * @param string $key |
||
966 | * @param string $name |
||
967 | * @param string|null $column |
||
968 | * @return Column\ColumnLink |
||
969 | */ |
||
970 | public function addColumnLink($key, $name, $href = null, $column = null, array $params = null) |
||
971 | { |
||
972 | 1 | $this->addColumnCheck($key); |
|
973 | 1 | $column = $column ?: $key; |
|
974 | 1 | $href = $href ?: $key; |
|
975 | |||
976 | 1 | if ($params === null) { |
|
977 | 1 | $params = [$this->primary_key]; |
|
978 | } |
||
979 | |||
980 | 1 | return $this->addColumn($key, new Column\ColumnLink($this, $key, $column, $name, $href, $params)); |
|
981 | } |
||
982 | |||
983 | |||
984 | /** |
||
985 | * Add column with possible number formating |
||
986 | * @param string $key |
||
987 | * @param string $name |
||
988 | * @param string|null $column |
||
989 | * @return Column\ColumnNumber |
||
990 | */ |
||
991 | public function addColumnNumber($key, $name, $column = null) |
||
992 | { |
||
993 | 1 | $this->addColumnCheck($key); |
|
994 | 1 | $column = $column ?: $key; |
|
995 | |||
996 | 1 | return $this->addColumn($key, new Column\ColumnNumber($this, $key, $column, $name)); |
|
997 | } |
||
998 | |||
999 | |||
1000 | /** |
||
1001 | * Add column with date formating |
||
1002 | * @param string $key |
||
1003 | * @param string $name |
||
1004 | * @param string|null $column |
||
1005 | * @return Column\ColumnDateTime |
||
1006 | */ |
||
1007 | public function addColumnDateTime($key, $name, $column = null) |
||
1008 | { |
||
1009 | 1 | $this->addColumnCheck($key); |
|
1010 | 1 | $column = $column ?: $key; |
|
1011 | |||
1012 | 1 | return $this->addColumn($key, new Column\ColumnDateTime($this, $key, $column, $name)); |
|
1013 | } |
||
1014 | |||
1015 | |||
1016 | /** |
||
1017 | * Add column status |
||
1018 | * @param string $key |
||
1019 | * @param string $name |
||
1020 | * @param string|null $column |
||
1021 | * @return Column\ColumnStatus |
||
1022 | */ |
||
1023 | public function addColumnStatus($key, $name, $column = null) |
||
1024 | { |
||
1025 | 1 | $this->addColumnCheck($key); |
|
1026 | 1 | $column = $column ?: $key; |
|
1027 | |||
1028 | 1 | return $this->addColumn($key, new Column\ColumnStatus($this, $key, $column, $name)); |
|
1029 | } |
||
1030 | |||
1031 | |||
1032 | /** |
||
1033 | * @param string $key |
||
1034 | * @param Column\Column $column |
||
1035 | * @return Column\Column |
||
1036 | */ |
||
1037 | protected function addColumn($key, Column\Column $column) |
||
1038 | { |
||
1039 | 1 | $this->onColumnAdd($key, $column); |
|
1040 | |||
1041 | 1 | $this->columns_visibility[$key] = [ |
|
1042 | 'visible' => true, |
||
1043 | ]; |
||
1044 | |||
1045 | 1 | return $this->columns[$key] = $column; |
|
1046 | } |
||
1047 | |||
1048 | |||
1049 | /** |
||
1050 | * Return existing column |
||
1051 | * @param string $key |
||
1052 | * @return Column\Column |
||
1053 | * @throws DataGridException |
||
1054 | */ |
||
1055 | public function getColumn($key) |
||
1056 | { |
||
1057 | 1 | if (!isset($this->columns[$key])) { |
|
1058 | throw new DataGridColumnNotFoundException("There is no column at key [$key] defined."); |
||
1059 | } |
||
1060 | |||
1061 | 1 | return $this->columns[$key]; |
|
1062 | } |
||
1063 | |||
1064 | |||
1065 | /** |
||
1066 | * Remove column |
||
1067 | * @param string $key |
||
1068 | * @return static |
||
1069 | */ |
||
1070 | public function removeColumn($key) |
||
1071 | { |
||
1072 | 1 | unset($this->columns_visibility[$key], $this->columns[$key]); |
|
1073 | |||
1074 | |||
1075 | 1 | return $this; |
|
1076 | } |
||
1077 | |||
1078 | |||
1079 | /** |
||
1080 | * Check whether given key already exists in $this->columns |
||
1081 | * @param string $key |
||
1082 | * @throws DataGridException |
||
1083 | */ |
||
1084 | protected function addColumnCheck($key) |
||
1085 | { |
||
1086 | 1 | if (isset($this->columns[$key])) { |
|
1087 | throw new DataGridException("There is already column at key [$key] defined."); |
||
1088 | } |
||
1089 | 1 | } |
|
1090 | |||
1091 | |||
1092 | /******************************************************************************** |
||
1093 | * ACTIONS * |
||
1094 | ********************************************************************************/ |
||
1095 | |||
1096 | |||
1097 | /** |
||
1098 | * Create action |
||
1099 | * @param string $key |
||
1100 | * @param string $name |
||
1101 | * @param string $href |
||
1102 | * @param array|null $params |
||
1103 | * @return Column\Action |
||
1104 | */ |
||
1105 | public function addAction($key, $name, $href = null, array $params = null) |
||
1106 | { |
||
1107 | 1 | $this->addActionCheck($key); |
|
1108 | |||
1109 | 1 | $href = $href ?: $key; |
|
1110 | |||
1111 | 1 | if ($params === null) { |
|
1112 | 1 | $params = [$this->primary_key]; |
|
1113 | } |
||
1114 | |||
1115 | 1 | return $this->actions[$key] = new Column\Action($this, $href, $name, $params); |
|
1116 | } |
||
1117 | |||
1118 | |||
1119 | /** |
||
1120 | * Create action callback |
||
1121 | * @param string $key |
||
1122 | * @param string $name |
||
1123 | * @return Column\Action |
||
1124 | */ |
||
1125 | public function addActionCallback($key, $name, $callback = null) |
||
1126 | { |
||
1127 | $this->addActionCheck($key); |
||
1128 | |||
1129 | $params = ['__id' => $this->primary_key]; |
||
1130 | |||
1131 | $this->actions[$key] = $action = new Column\ActionCallback($this, $key, $name, $params); |
||
1132 | |||
1133 | if ($callback) { |
||
1134 | if (!is_callable($callback)) { |
||
1135 | throw new DataGridException('ActionCallback callback has to be callable.'); |
||
1136 | } |
||
1137 | |||
1138 | $action->onClick[] = $callback; |
||
1139 | } |
||
1140 | |||
1141 | return $action; |
||
1142 | } |
||
1143 | |||
1144 | |||
1145 | /** |
||
1146 | * @param string $key |
||
1147 | */ |
||
1148 | public function addMultiAction($key, $name) |
||
1149 | { |
||
1150 | $this->addActionCheck($key); |
||
1151 | |||
1152 | $this->actions[$key] = $action = new Column\MultiAction($this, $name); |
||
1153 | |||
1154 | return $action; |
||
1155 | } |
||
1156 | |||
1157 | |||
1158 | /** |
||
1159 | * Get existing action |
||
1160 | * @param string $key |
||
1161 | * @return Column\Action |
||
1162 | * @throws DataGridException |
||
1163 | */ |
||
1164 | View Code Duplication | public function getAction($key) |
|
1165 | { |
||
1166 | if (!isset($this->actions[$key])) { |
||
1167 | throw new DataGridException("There is no action at key [$key] defined."); |
||
1168 | } |
||
1169 | |||
1170 | return $this->actions[$key]; |
||
1171 | } |
||
1172 | |||
1173 | |||
1174 | /** |
||
1175 | * Remove action |
||
1176 | * @param string $key |
||
1177 | * @return static |
||
1178 | */ |
||
1179 | public function removeAction($key) |
||
1180 | { |
||
1181 | unset($this->actions[$key]); |
||
1182 | |||
1183 | return $this; |
||
1184 | } |
||
1185 | |||
1186 | |||
1187 | /** |
||
1188 | * Check whether given key already exists in $this->filters |
||
1189 | * @param string $key |
||
1190 | * @throws DataGridException |
||
1191 | */ |
||
1192 | protected function addActionCheck($key) |
||
1193 | { |
||
1194 | 1 | if (isset($this->actions[$key])) { |
|
1195 | 1 | throw new DataGridException("There is already action at key [$key] defined."); |
|
1196 | } |
||
1197 | 1 | } |
|
1198 | |||
1199 | |||
1200 | /******************************************************************************** |
||
1201 | * FILTERS * |
||
1202 | ********************************************************************************/ |
||
1203 | |||
1204 | |||
1205 | /** |
||
1206 | * Add filter fot text search |
||
1207 | * @param string $key |
||
1208 | * @param string $name |
||
1209 | * @param array|string $columns |
||
1210 | * @return Filter\FilterText |
||
1211 | * @throws DataGridException |
||
1212 | */ |
||
1213 | public function addFilterText($key, $name, $columns = null) |
||
1214 | { |
||
1215 | 1 | $columns = $columns === null? [$key] : (is_string($columns) ? [$columns] : $columns); |
|
1216 | |||
1217 | 1 | if (!is_array($columns)) { |
|
1218 | throw new DataGridException('Filter Text can accept only array or string.'); |
||
1219 | } |
||
1220 | |||
1221 | 1 | $this->addFilterCheck($key); |
|
1222 | |||
1223 | 1 | return $this->filters[$key] = new Filter\FilterText($this, $key, $name, $columns); |
|
1224 | } |
||
1225 | |||
1226 | |||
1227 | /** |
||
1228 | * Add select box filter |
||
1229 | * @param string $key |
||
1230 | * @param string $name |
||
1231 | * @param array $options |
||
1232 | * @param string $column |
||
1233 | * @return Filter\FilterSelect |
||
1234 | * @throws DataGridException |
||
1235 | */ |
||
1236 | View Code Duplication | public function addFilterSelect($key, $name, array $options, $column = null) |
|
1237 | { |
||
1238 | $column = $column ?: $key; |
||
1239 | |||
1240 | if (!is_string($column)) { |
||
1241 | throw new DataGridException('Filter Select can only filter in one column.'); |
||
1242 | } |
||
1243 | |||
1244 | $this->addFilterCheck($key); |
||
1245 | |||
1246 | return $this->filters[$key] = new Filter\FilterSelect($this, $key, $name, $options, $column); |
||
1247 | } |
||
1248 | |||
1249 | |||
1250 | /** |
||
1251 | * Add multi select box filter |
||
1252 | * @param string $key |
||
1253 | * @param string $name |
||
1254 | * @param array $options |
||
1255 | * @param string $column |
||
1256 | * @return Filter\FilterSelect |
||
1257 | * @throws DataGridException |
||
1258 | */ |
||
1259 | View Code Duplication | public function addFilterMultiSelect($key, $name, array $options, $column = null) |
|
1260 | { |
||
1261 | $column = $column ?: $key; |
||
1262 | |||
1263 | if (!is_string($column)) { |
||
1264 | throw new DataGridException('Filter MultiSelect can only filter in one column.'); |
||
1265 | } |
||
1266 | |||
1267 | $this->addFilterCheck($key); |
||
1268 | |||
1269 | return $this->filters[$key] = new Filter\FilterMultiSelect($this, $key, $name, $options, $column); |
||
1270 | } |
||
1271 | |||
1272 | |||
1273 | /** |
||
1274 | * Add datepicker filter |
||
1275 | * @param string $key |
||
1276 | * @param string $name |
||
1277 | * @param string $column |
||
1278 | * @return Filter\FilterDate |
||
1279 | * @throws DataGridException |
||
1280 | */ |
||
1281 | View Code Duplication | public function addFilterDate($key, $name, $column = null) |
|
1282 | { |
||
1283 | $column = $column ?: $key; |
||
1284 | |||
1285 | if (!is_string($column)) { |
||
1286 | throw new DataGridException('FilterDate can only filter in one column.'); |
||
1287 | } |
||
1288 | |||
1289 | $this->addFilterCheck($key); |
||
1290 | |||
1291 | return $this->filters[$key] = new Filter\FilterDate($this, $key, $name, $column); |
||
1292 | } |
||
1293 | |||
1294 | |||
1295 | /** |
||
1296 | * Add range filter (from - to) |
||
1297 | * @param string $key |
||
1298 | * @param string $name |
||
1299 | * @param string $column |
||
1300 | * @return Filter\FilterRange |
||
1301 | * @throws DataGridException |
||
1302 | */ |
||
1303 | View Code Duplication | public function addFilterRange($key, $name, $column = null, $name_second = '-') |
|
1304 | { |
||
1305 | $column = $column ?: $key; |
||
1306 | |||
1307 | if (!is_string($column)) { |
||
1308 | throw new DataGridException('FilterRange can only filter in one column.'); |
||
1309 | } |
||
1310 | |||
1311 | $this->addFilterCheck($key); |
||
1312 | |||
1313 | return $this->filters[$key] = new Filter\FilterRange($this, $key, $name, $column, $name_second); |
||
1314 | } |
||
1315 | |||
1316 | |||
1317 | /** |
||
1318 | * Add datepicker filter (from - to) |
||
1319 | * @param string $key |
||
1320 | * @param string $name |
||
1321 | * @param string $column |
||
1322 | * @return Filter\FilterDateRange |
||
1323 | * @throws DataGridException |
||
1324 | */ |
||
1325 | View Code Duplication | public function addFilterDateRange($key, $name, $column = null, $name_second = '-') |
|
1326 | { |
||
1327 | $column = $column ?: $key; |
||
1328 | |||
1329 | if (!is_string($column)) { |
||
1330 | throw new DataGridException('FilterDateRange can only filter in one column.'); |
||
1331 | } |
||
1332 | |||
1333 | $this->addFilterCheck($key); |
||
1334 | |||
1335 | return $this->filters[$key] = new Filter\FilterDateRange($this, $key, $name, $column, $name_second); |
||
1336 | } |
||
1337 | |||
1338 | |||
1339 | /** |
||
1340 | * Check whether given key already exists in $this->filters |
||
1341 | * @param string $key |
||
1342 | * @throws DataGridException |
||
1343 | */ |
||
1344 | protected function addFilterCheck($key) |
||
1345 | { |
||
1346 | 1 | if (isset($this->filters[$key])) { |
|
1347 | throw new DataGridException("There is already action at key [$key] defined."); |
||
1348 | } |
||
1349 | 1 | } |
|
1350 | |||
1351 | |||
1352 | /** |
||
1353 | * Fill array of Filter\Filter[] with values from $this->filter persistent parameter |
||
1354 | * Fill array of Column\Column[] with values from $this->sort persistent parameter |
||
1355 | * @return Filter\Filter[] $this->filters === Filter\Filter[] |
||
1356 | */ |
||
1357 | public function assembleFilters() |
||
1358 | { |
||
1359 | 1 | foreach ($this->filter as $key => $value) { |
|
1360 | if (!isset($this->filters[$key])) { |
||
1361 | $this->deleteSessionData($key); |
||
1362 | |||
1363 | continue; |
||
1364 | } |
||
1365 | |||
1366 | if (is_array($value) || $value instanceof \Traversable) { |
||
1367 | if (!ArraysHelper::testEmpty($value)) { |
||
1368 | $this->filters[$key]->setValue($value); |
||
1369 | } |
||
1370 | } else { |
||
1371 | if ($value !== '' && $value !== null) { |
||
1372 | $this->filters[$key]->setValue($value); |
||
1373 | } |
||
1374 | } |
||
1375 | } |
||
1376 | |||
1377 | 1 | foreach ($this->columns as $key => $column) { |
|
1378 | if (isset($this->sort[$key])) { |
||
1379 | $column->setSort($this->sort); |
||
1380 | } |
||
1381 | } |
||
1382 | |||
1383 | /** |
||
1384 | * Invoke possible events |
||
1385 | */ |
||
1386 | 1 | if (!empty($this->onFiltersAssabled)) { |
|
0 ignored issues
–
show
|
|||
1387 | @trigger_error('onFiltersAssabled is deprecated, use onFiltersAssembled instead', E_USER_DEPRECATED); |
||
1388 | $this->onFiltersAssabled($this->filters); |
||
1389 | } |
||
1390 | |||
1391 | 1 | $this->onFiltersAssembled($this->filters); |
|
1392 | 1 | return $this->filters; |
|
1393 | } |
||
1394 | |||
1395 | |||
1396 | /** |
||
1397 | * Fill array of Filter\Filter[] with values from $this->filter persistent parameter |
||
1398 | * Fill array of Column\Column[] with values from $this->sort persistent parameter |
||
1399 | * @return Filter\Filter[] $this->filters === Filter\Filter[] |
||
1400 | * @deprecated use assembleFilters instead |
||
1401 | */ |
||
1402 | public function assableFilters() |
||
1403 | { |
||
1404 | @trigger_error('assableFilters is deprecated, use assembleFilters instead', E_USER_DEPRECATED); |
||
1405 | return $this->assembleFilters(); |
||
1406 | } |
||
1407 | |||
1408 | |||
1409 | /** |
||
1410 | * Remove filter |
||
1411 | * @param string $key |
||
1412 | * @return static |
||
1413 | */ |
||
1414 | public function removeFilter($key) |
||
1415 | { |
||
1416 | unset($this->filters[$key]); |
||
1417 | |||
1418 | return $this; |
||
1419 | } |
||
1420 | |||
1421 | |||
1422 | /** |
||
1423 | * Get defined filter |
||
1424 | * @param string $key |
||
1425 | * @return Filter\Filter |
||
1426 | */ |
||
1427 | public function getFilter($key) |
||
1428 | { |
||
1429 | if (!isset($this->filters[$key])) { |
||
1430 | throw new DataGridException("Filter [{$key}] is not defined"); |
||
1431 | } |
||
1432 | |||
1433 | return $this->filters[$key]; |
||
1434 | } |
||
1435 | |||
1436 | |||
1437 | /** |
||
1438 | * @param bool $strict |
||
1439 | * @return static |
||
1440 | */ |
||
1441 | public function setStrictSessionFilterValues($strict = true) |
||
1442 | { |
||
1443 | $this->strict_session_filter_values = (bool) $strict; |
||
1444 | |||
1445 | return $this; |
||
1446 | } |
||
1447 | |||
1448 | |||
1449 | /******************************************************************************** |
||
1450 | * FILTERING * |
||
1451 | ********************************************************************************/ |
||
1452 | |||
1453 | |||
1454 | /** |
||
1455 | * Is filter active? |
||
1456 | * @return bool |
||
1457 | */ |
||
1458 | public function isFilterActive() |
||
1459 | { |
||
1460 | $is_filter = ArraysHelper::testTruthy($this->filter); |
||
1461 | |||
1462 | return ($is_filter) || $this->force_filter_active; |
||
1463 | } |
||
1464 | |||
1465 | |||
1466 | /** |
||
1467 | * Tell that filter is active from whatever reasons |
||
1468 | * return static |
||
1469 | */ |
||
1470 | public function setFilterActive() |
||
1471 | { |
||
1472 | $this->force_filter_active = true; |
||
1473 | |||
1474 | return $this; |
||
1475 | } |
||
1476 | |||
1477 | |||
1478 | /** |
||
1479 | * Set filter values (force - overwrite user data) |
||
1480 | * @param array $filter |
||
1481 | * @return static |
||
1482 | */ |
||
1483 | public function setFilter(array $filter) |
||
1484 | { |
||
1485 | $this->filter = $filter; |
||
1486 | |||
1487 | $this->saveSessionData('_grid_has_filtered', 1); |
||
1488 | |||
1489 | return $this; |
||
1490 | } |
||
1491 | |||
1492 | |||
1493 | /** |
||
1494 | * If we want to sent some initial filter |
||
1495 | * @param array $filter |
||
1496 | * @param bool $use_on_reset |
||
1497 | * @return static |
||
1498 | */ |
||
1499 | public function setDefaultFilter(array $default_filter, $use_on_reset = true) |
||
1500 | { |
||
1501 | foreach ($default_filter as $key => $value) { |
||
1502 | $filter = $this->getFilter($key); |
||
1503 | |||
1504 | if (!$filter) { |
||
1505 | throw new DataGridException("Can not set default value to nonexisting filter [$key]"); |
||
1506 | } |
||
1507 | |||
1508 | if ($filter instanceof Filter\FilterMultiSelect && !is_array($value)) { |
||
1509 | throw new DataGridException( |
||
1510 | "Default value of filter [$key] - MultiSelect has to be an array" |
||
1511 | ); |
||
1512 | } |
||
1513 | |||
1514 | if ($filter instanceof Filter\FilterRange || $filter instanceof Filter\FilterDateRange) { |
||
1515 | if (!is_array($value)) { |
||
1516 | throw new DataGridException( |
||
1517 | "Default value of filter [$key] - Range/DateRange has to be an array [from/to => ...]" |
||
1518 | ); |
||
1519 | } |
||
1520 | |||
1521 | $temp = $value; |
||
1522 | unset($temp['from'], $temp['to']); |
||
1523 | |||
1524 | if (!empty($temp)) { |
||
1525 | throw new DataGridException( |
||
1526 | "Default value of filter [$key] - Range/DateRange can contain only [from/to => ...] values" |
||
1527 | ); |
||
1528 | } |
||
1529 | } |
||
1530 | } |
||
1531 | |||
1532 | $this->default_filter = $default_filter; |
||
1533 | $this->default_filter_use_on_reset = (bool) $use_on_reset; |
||
1534 | |||
1535 | return $this; |
||
1536 | } |
||
1537 | |||
1538 | |||
1539 | /** |
||
1540 | * User may set default filter, find it |
||
1541 | * @return void |
||
1542 | */ |
||
1543 | public function findDefaultFilter() |
||
1544 | { |
||
1545 | 1 | if (!empty($this->filter)) { |
|
1546 | return; |
||
1547 | } |
||
1548 | |||
1549 | 1 | if ($this->getSessionData('_grid_has_filtered')) { |
|
1550 | return; |
||
1551 | } |
||
1552 | |||
1553 | 1 | if (!empty($this->default_filter)) { |
|
1554 | $this->filter = $this->default_filter; |
||
1555 | } |
||
1556 | |||
1557 | 1 | foreach ($this->filter as $key => $value) { |
|
1558 | $this->saveSessionData($key, $value); |
||
1559 | } |
||
1560 | 1 | } |
|
1561 | |||
1562 | |||
1563 | /** |
||
1564 | * FilterAndGroupAction form factory |
||
1565 | * @return Form |
||
1566 | */ |
||
1567 | public function createComponentFilter() |
||
1568 | { |
||
1569 | $form = new Form($this, 'filter'); |
||
1570 | |||
1571 | $form->setMethod(static::$form_method); |
||
1572 | |||
1573 | $form->setTranslator($this->getTranslator()); |
||
1574 | |||
1575 | /** |
||
1576 | * InlineEdit part |
||
1577 | */ |
||
1578 | $inline_edit_container = $form->addContainer('inline_edit'); |
||
1579 | |||
1580 | View Code Duplication | if ($this->inlineEdit instanceof InlineEdit) { |
|
1581 | $inline_edit_container->addSubmit('submit', 'ublaboo_datagrid.save') |
||
1582 | ->setValidationScope([$inline_edit_container]); |
||
1583 | $inline_edit_container->addSubmit('cancel', 'ublaboo_datagrid.cancel') |
||
1584 | ->setValidationScope(false); |
||
1585 | |||
1586 | $this->inlineEdit->onControlAdd($inline_edit_container); |
||
1587 | $this->inlineEdit->onControlAfterAdd($inline_edit_container); |
||
1588 | } |
||
1589 | |||
1590 | /** |
||
1591 | * InlineAdd part |
||
1592 | */ |
||
1593 | $inline_add_container = $form->addContainer('inline_add'); |
||
1594 | |||
1595 | View Code Duplication | if ($this->inlineAdd instanceof InlineEdit) { |
|
1596 | $inline_add_container->addSubmit('submit', 'ublaboo_datagrid.save') |
||
1597 | ->setValidationScope([$inline_add_container]); |
||
1598 | $inline_add_container->addSubmit('cancel', 'ublaboo_datagrid.cancel') |
||
1599 | ->setValidationScope(false) |
||
1600 | ->setAttribute('data-datagrid-cancel-inline-add', true); |
||
1601 | |||
1602 | $this->inlineAdd->onControlAdd($inline_add_container); |
||
1603 | $this->inlineAdd->onControlAfterAdd($inline_add_container); |
||
1604 | } |
||
1605 | |||
1606 | /** |
||
1607 | * ItemDetail form part |
||
1608 | */ |
||
1609 | $items_detail_form = $this->getItemDetailForm(); |
||
1610 | |||
1611 | if ($items_detail_form instanceof Nette\Forms\Container) { |
||
1612 | $form['items_detail_form'] = $items_detail_form; |
||
1613 | } |
||
1614 | |||
1615 | /** |
||
1616 | * Filter part |
||
1617 | */ |
||
1618 | $filter_container = $form->addContainer('filter'); |
||
1619 | |||
1620 | foreach ($this->filters as $filter) { |
||
1621 | $filter->addToFormContainer($filter_container); |
||
1622 | } |
||
1623 | |||
1624 | if (!$this->hasAutoSubmit()) { |
||
1625 | $filter_container['submit'] = $this->getFilterSubmitButton(); |
||
1626 | } |
||
1627 | |||
1628 | /** |
||
1629 | * Group action part |
||
1630 | */ |
||
1631 | $group_action_container = $form->addContainer('group_action'); |
||
1632 | |||
1633 | if ($this->hasGroupActions()) { |
||
1634 | $this->getGroupActionCollection()->addToFormContainer($group_action_container); |
||
1635 | } |
||
1636 | |||
1637 | if (!$form->isSubmitted()) { |
||
1638 | $this->setFilterContainerDefaults($form['filter'], $this->filter); |
||
1639 | } |
||
1640 | |||
1641 | /** |
||
1642 | * Per page part |
||
1643 | */ |
||
1644 | $form->addSelect('per_page', '', $this->getItemsPerPageList()) |
||
1645 | ->setTranslator(null); |
||
1646 | |||
1647 | if (!$form->isSubmitted()) { |
||
1648 | $form['per_page']->setValue($this->getPerPage()); |
||
1649 | } |
||
1650 | |||
1651 | $form->addSubmit('per_page_submit', 'ublaboo_datagrid.per_page_submit') |
||
1652 | ->setValidationScope([$form['per_page']]); |
||
1653 | |||
1654 | $form->onSubmit[] = [$this, 'filterSucceeded']; |
||
1655 | } |
||
1656 | |||
1657 | |||
1658 | /** |
||
1659 | * @param Nette\Forms\Container $container |
||
1660 | * @param array|\Iterator $values |
||
1661 | * @return void |
||
1662 | */ |
||
1663 | public function setFilterContainerDefaults(Nette\Forms\Container $container, $values) |
||
1664 | { |
||
1665 | foreach ($container->getComponents() as $key => $control) { |
||
1666 | if (!isset($values[$key])) { |
||
1667 | continue; |
||
1668 | } |
||
1669 | |||
1670 | if ($control instanceof Nette\Forms\Container) { |
||
1671 | $this->setFilterContainerDefaults($control, $values[$key]); |
||
1672 | |||
1673 | continue; |
||
1674 | } |
||
1675 | |||
1676 | $value = $values[$key]; |
||
1677 | |||
1678 | if ($value instanceof \DateTime && ($filter = $this->getFilter($key)) instanceof IFilterDate) { |
||
1679 | $value = $value->format($filter->getPhpFormat()); |
||
1680 | } |
||
1681 | |||
1682 | try { |
||
1683 | $control->setValue($value); |
||
1684 | |||
1685 | } catch (Nette\InvalidArgumentException $e) { |
||
1686 | if ($this->strict_session_filter_values) { |
||
1687 | throw $e; |
||
1688 | } |
||
1689 | } |
||
1690 | } |
||
1691 | } |
||
1692 | |||
1693 | |||
1694 | /** |
||
1695 | * Set $this->filter values after filter form submitted |
||
1696 | * @param Form $form |
||
1697 | * @return void |
||
1698 | */ |
||
1699 | public function filterSucceeded(Form $form) |
||
1700 | { |
||
1701 | if ($this->snippets_set) { |
||
1702 | return; |
||
1703 | } |
||
1704 | |||
1705 | $values = $form->getValues(); |
||
1706 | |||
1707 | if ($this->getPresenter()->isAjax()) { |
||
1708 | if (isset($form['group_action']['submit']) && $form['group_action']['submit']->isSubmittedBy()) { |
||
1709 | return; |
||
1710 | } |
||
1711 | } |
||
1712 | |||
1713 | /** |
||
1714 | * Per page |
||
1715 | */ |
||
1716 | $this->saveSessionData('_grid_per_page', $values->per_page); |
||
1717 | $this->per_page = $values->per_page; |
||
1718 | |||
1719 | /** |
||
1720 | * Inline edit |
||
1721 | */ |
||
1722 | if (isset($form['inline_edit']) && isset($form['inline_edit']['submit']) && isset($form['inline_edit']['cancel'])) { |
||
1723 | $edit = $form['inline_edit']; |
||
1724 | |||
1725 | if ($edit['submit']->isSubmittedBy() || $edit['cancel']->isSubmittedBy()) { |
||
1726 | $id = $form->getHttpData(Form::DATA_LINE, 'inline_edit[_id]'); |
||
1727 | $primary_where_column = $form->getHttpData( |
||
1728 | Form::DATA_LINE, |
||
1729 | 'inline_edit[_primary_where_column]' |
||
1730 | ); |
||
1731 | |||
1732 | if ($edit['submit']->isSubmittedBy() && !$edit->getErrors()) { |
||
1733 | $this->inlineEdit->onSubmit($id, $values->inline_edit); |
||
1734 | $this->getPresenter()->payload->_datagrid_inline_edited = $id; |
||
1735 | $this->getPresenter()->payload->_datagrid_name = $this->getName(); |
||
1736 | } else { |
||
1737 | $this->getPresenter()->payload->_datagrid_inline_edit_cancel = $id; |
||
1738 | $this->getPresenter()->payload->_datagrid_name = $this->getName(); |
||
1739 | } |
||
1740 | |||
1741 | if ($edit['submit']->isSubmittedBy() && !empty($this->inlineEdit->onCustomRedraw)) { |
||
1742 | $this->inlineEdit->onCustomRedraw(); |
||
1743 | } else { |
||
1744 | $this->redrawItem($id, $primary_where_column); |
||
1745 | $this->redrawControl('summary'); |
||
1746 | } |
||
1747 | |||
1748 | return; |
||
1749 | } |
||
1750 | } |
||
1751 | |||
1752 | /** |
||
1753 | * Inline add |
||
1754 | */ |
||
1755 | if (isset($form['inline_add']) && isset($form['inline_add']['submit']) && isset($form['inline_add']['cancel'])) { |
||
1756 | $add = $form['inline_add']; |
||
1757 | |||
1758 | if ($add['submit']->isSubmittedBy() || $add['cancel']->isSubmittedBy()) { |
||
1759 | if ($add['submit']->isSubmittedBy() && !$add->getErrors()) { |
||
1760 | $this->inlineAdd->onSubmit($values->inline_add); |
||
1761 | |||
1762 | if ($this->getPresenter()->isAjax()) { |
||
1763 | $this->getPresenter()->payload->_datagrid_inline_added = true; |
||
1764 | } |
||
1765 | } |
||
1766 | |||
1767 | return; |
||
1768 | } |
||
1769 | } |
||
1770 | |||
1771 | /** |
||
1772 | * Filter itself |
||
1773 | */ |
||
1774 | $values = $values['filter']; |
||
1775 | |||
1776 | foreach ($values as $key => $value) { |
||
1777 | /** |
||
1778 | * Session stuff |
||
1779 | */ |
||
1780 | if ($this->remember_state && $this->getSessionData($key) != $value) { |
||
1781 | /** |
||
1782 | * Has been filter changed? |
||
1783 | */ |
||
1784 | $this->page = 1; |
||
1785 | $this->saveSessionData('_grid_page', 1); |
||
1786 | } |
||
1787 | |||
1788 | $this->saveSessionData($key, $value); |
||
1789 | |||
1790 | /** |
||
1791 | * Other stuff |
||
1792 | */ |
||
1793 | $this->filter[$key] = $value; |
||
1794 | } |
||
1795 | |||
1796 | if (!empty($values)) { |
||
1797 | $this->saveSessionData('_grid_has_filtered', 1); |
||
1798 | } |
||
1799 | |||
1800 | if ($this->getPresenter()->isAjax()) { |
||
1801 | $this->getPresenter()->payload->_datagrid_sort = []; |
||
1802 | |||
1803 | foreach ($this->columns as $key => $column) { |
||
1804 | if ($column->isSortable()) { |
||
1805 | $this->getPresenter()->payload->_datagrid_sort[$key] = $this->link('sort!', [ |
||
1806 | 'sort' => $column->getSortNext(), |
||
1807 | ]); |
||
1808 | } |
||
1809 | } |
||
1810 | } |
||
1811 | |||
1812 | $this->reload(); |
||
1813 | } |
||
1814 | |||
1815 | |||
1816 | /** |
||
1817 | * Should be datagrid filters rendered separately? |
||
1818 | * @param bool $out |
||
1819 | * @return static |
||
1820 | */ |
||
1821 | public function setOuterFilterRendering($out = true) |
||
1822 | { |
||
1823 | $this->outer_filter_rendering = (bool) $out; |
||
1824 | |||
1825 | return $this; |
||
1826 | } |
||
1827 | |||
1828 | |||
1829 | /** |
||
1830 | * Are datagrid filters rendered separately? |
||
1831 | * @return bool |
||
1832 | */ |
||
1833 | public function hasOuterFilterRendering() |
||
1834 | { |
||
1835 | return $this->outer_filter_rendering; |
||
1836 | } |
||
1837 | |||
1838 | |||
1839 | /** |
||
1840 | * Set the number of columns in the outer filter |
||
1841 | * @param int $count |
||
1842 | * @return static |
||
1843 | * @throws \InvalidArgumentException |
||
1844 | */ |
||
1845 | public function setOuterFilterColumnsCount($count) |
||
1846 | { |
||
1847 | if (!in_array($count, [1, 2, 3, 4, 6, 12], true)) { |
||
1848 | throw new \InvalidArgumentException( |
||
1849 | "Columns count must be one of following values: 1, 2, 3, 4, 6, 12. Value {$count} given." |
||
1850 | ); |
||
1851 | } |
||
1852 | |||
1853 | $this->outer_filter_columns_count = (int) $count; |
||
1854 | |||
1855 | return $this; |
||
1856 | } |
||
1857 | |||
1858 | |||
1859 | /** |
||
1860 | * @return bool |
||
1861 | */ |
||
1862 | public function getOuterFilterColumnsCount() |
||
1863 | { |
||
1864 | return $this->outer_filter_columns_count; |
||
1865 | } |
||
1866 | |||
1867 | |||
1868 | /** |
||
1869 | * @param bool $collapsible_outer_filters |
||
1870 | */ |
||
1871 | public function setCollapsibleOuterFilters($collapsible_outer_filters = true) |
||
1872 | { |
||
1873 | $this->collapsible_outer_filters = (bool) $collapsible_outer_filters; |
||
1874 | } |
||
1875 | |||
1876 | |||
1877 | /** |
||
1878 | * @return bool |
||
1879 | */ |
||
1880 | public function hasCollapsibleOuterFilters() |
||
1881 | { |
||
1882 | return $this->collapsible_outer_filters; |
||
1883 | } |
||
1884 | |||
1885 | |||
1886 | /** |
||
1887 | * Try to restore session stuff |
||
1888 | * @return void |
||
1889 | * @throws DataGridFilterNotFoundException |
||
1890 | */ |
||
1891 | public function findSessionValues() |
||
1892 | { |
||
1893 | 1 | if (!ArraysHelper::testEmpty($this->filter) || ($this->page != 1) || !empty($this->sort)) { |
|
1894 | return; |
||
1895 | } |
||
1896 | |||
1897 | 1 | if (!$this->remember_state) { |
|
1898 | return; |
||
1899 | } |
||
1900 | |||
1901 | 1 | if ($page = $this->getSessionData('_grid_page')) { |
|
1902 | $this->page = $page; |
||
1903 | } |
||
1904 | |||
1905 | 1 | if ($per_page = $this->getSessionData('_grid_per_page')) { |
|
1906 | $this->per_page = $per_page; |
||
1907 | } |
||
1908 | |||
1909 | 1 | if ($sort = $this->getSessionData('_grid_sort')) { |
|
1910 | $this->sort = $sort; |
||
1911 | } |
||
1912 | |||
1913 | 1 | foreach ($this->getSessionData() as $key => $value) { |
|
1914 | $other_session_keys = [ |
||
1915 | 1 | '_grid_per_page', |
|
1916 | '_grid_sort', |
||
1917 | '_grid_page', |
||
1918 | '_grid_has_sorted', |
||
1919 | '_grid_has_filtered', |
||
1920 | '_grid_hidden_columns', |
||
1921 | '_grid_hidden_columns_manipulated', |
||
1922 | ]; |
||
1923 | |||
1924 | 1 | if (!in_array($key, $other_session_keys, true)) { |
|
1925 | try { |
||
1926 | $this->getFilter($key); |
||
1927 | |||
1928 | $this->filter[$key] = $value; |
||
1929 | |||
1930 | } catch (DataGridException $e) { |
||
1931 | if ($this->strict_session_filter_values) { |
||
1932 | 1 | throw new DataGridFilterNotFoundException("Session filter: Filter [$key] not found"); |
|
1933 | } |
||
1934 | } |
||
1935 | } |
||
1936 | } |
||
1937 | |||
1938 | /** |
||
1939 | * When column is sorted via custom callback, apply it |
||
1940 | */ |
||
1941 | 1 | if (empty($this->sort_callback) && !empty($this->sort)) { |
|
1942 | foreach ($this->sort as $key => $order) { |
||
1943 | try { |
||
1944 | $column = $this->getColumn($key); |
||
1945 | |||
1946 | } catch (DataGridColumnNotFoundException $e) { |
||
1947 | $this->deleteSessionData('_grid_sort'); |
||
1948 | $this->sort = []; |
||
1949 | |||
1950 | return; |
||
1951 | } |
||
1952 | |||
1953 | if ($column && $column->isSortable() && is_callable($column->getSortableCallback())) { |
||
1954 | $this->sort_callback = $column->getSortableCallback(); |
||
1955 | } |
||
1956 | } |
||
1957 | } |
||
1958 | 1 | } |
|
1959 | |||
1960 | |||
1961 | /******************************************************************************** |
||
1962 | * EXPORTS * |
||
1963 | ********************************************************************************/ |
||
1964 | |||
1965 | |||
1966 | /** |
||
1967 | * Add export of type callback |
||
1968 | * @param string $text |
||
1969 | * @param callable $callback |
||
1970 | * @param bool $filtered |
||
1971 | * @return Export\Export |
||
1972 | */ |
||
1973 | public function addExportCallback($text, $callback, $filtered = false) |
||
1974 | { |
||
1975 | 1 | if (!is_callable($callback)) { |
|
1976 | throw new DataGridException('Second parameter of ExportCallback must be callable.'); |
||
1977 | } |
||
1978 | |||
1979 | 1 | return $this->addToExports(new Export\Export($this, $text, $callback, $filtered)); |
|
1980 | } |
||
1981 | |||
1982 | |||
1983 | /** |
||
1984 | * Add already implemented csv export |
||
1985 | * @param string $text |
||
1986 | * @param string $csv_file_name |
||
1987 | * @param string|null $output_encoding |
||
1988 | * @param string|null $delimiter |
||
1989 | * @param bool $include_bom |
||
1990 | * @return Export\Export |
||
1991 | */ |
||
1992 | View Code Duplication | public function addExportCsv( |
|
1993 | $text, |
||
1994 | $csv_file_name, |
||
1995 | $output_encoding = null, |
||
1996 | $delimiter = null, |
||
1997 | $include_bom = false |
||
1998 | ) { |
||
1999 | 1 | return $this->addToExports(new Export\ExportCsv( |
|
2000 | 1 | $this, |
|
2001 | 1 | $text, |
|
2002 | 1 | $csv_file_name, |
|
2003 | 1 | false, |
|
2004 | 1 | $output_encoding, |
|
2005 | 1 | $delimiter, |
|
2006 | 1 | $include_bom |
|
2007 | )); |
||
2008 | } |
||
2009 | |||
2010 | |||
2011 | /** |
||
2012 | * Add already implemented csv export, but for filtered data |
||
2013 | * @param string $text |
||
2014 | * @param string $csv_file_name |
||
2015 | * @param string|null $output_encoding |
||
2016 | * @param string|null $delimiter |
||
2017 | * @param bool $include_bom |
||
2018 | * @return Export\Export |
||
2019 | */ |
||
2020 | View Code Duplication | public function addExportCsvFiltered( |
|
2021 | $text, |
||
2022 | $csv_file_name, |
||
2023 | $output_encoding = null, |
||
2024 | $delimiter = null, |
||
2025 | $include_bom = false |
||
2026 | ) { |
||
2027 | return $this->addToExports(new Export\ExportCsv( |
||
2028 | $this, |
||
2029 | $text, |
||
2030 | $csv_file_name, |
||
2031 | true, |
||
2032 | $output_encoding, |
||
2033 | $delimiter, |
||
2034 | $include_bom |
||
2035 | )); |
||
2036 | } |
||
2037 | |||
2038 | |||
2039 | /** |
||
2040 | * Add export to array |
||
2041 | * @param Export\Export $export |
||
2042 | * @return Export\Export |
||
2043 | */ |
||
2044 | protected function addToExports(Export\Export $export) |
||
2045 | { |
||
2046 | 1 | $id = ($s = sizeof($this->exports)) ? ($s + 1) : 1; |
|
2047 | |||
2048 | 1 | $export->setLink(new Link($this, 'export!', ['id' => $id])); |
|
2049 | |||
2050 | 1 | return $this->exports[$id] = $export; |
|
2051 | } |
||
2052 | |||
2053 | |||
2054 | /** |
||
2055 | * @return void |
||
2056 | */ |
||
2057 | public function resetExportsLinks() |
||
2058 | { |
||
2059 | foreach ($this->exports as $id => $export) { |
||
2060 | $export->setLink(new Link($this, 'export!', ['id' => $id])); |
||
2061 | } |
||
2062 | } |
||
2063 | |||
2064 | |||
2065 | /******************************************************************************** |
||
2066 | * TOOLBAR BUTTONS * |
||
2067 | ********************************************************************************/ |
||
2068 | |||
2069 | |||
2070 | /** |
||
2071 | * Add toolbar button |
||
2072 | * @param string $href |
||
2073 | * @param string $text |
||
2074 | * @param array $params |
||
2075 | * @return ToolbarButton |
||
2076 | * @throws DataGridException |
||
2077 | */ |
||
2078 | public function addToolbarButton($href, $text = '', $params = []) |
||
2079 | { |
||
2080 | if (isset($this->toolbar_buttons[$href])) { |
||
2081 | throw new DataGridException("There is already toolbar button at key [$href] defined."); |
||
2082 | } |
||
2083 | |||
2084 | return $this->toolbar_buttons[$href] = new ToolbarButton($this, $href, $text, $params); |
||
2085 | } |
||
2086 | |||
2087 | |||
2088 | /** |
||
2089 | * Get existing toolbar button |
||
2090 | * @param string $key |
||
2091 | * @return ToolbarButton |
||
2092 | * @throws DataGridException |
||
2093 | */ |
||
2094 | public function getToolbarButton($key) |
||
2095 | { |
||
2096 | if (!isset($this->toolbar_buttons[$key])) { |
||
2097 | throw new DataGridException("There is no toolbar button at key [$key] defined."); |
||
2098 | } |
||
2099 | |||
2100 | return $this->toolbar_buttons[$key]; |
||
2101 | } |
||
2102 | |||
2103 | |||
2104 | /** |
||
2105 | * Remove toolbar button. |
||
2106 | * @param string $key |
||
2107 | * @return static |
||
2108 | */ |
||
2109 | public function removeToolbarButton($key) |
||
2110 | { |
||
2111 | unset($this->toolbar_buttons[$key]); |
||
2112 | |||
2113 | return $this; |
||
2114 | } |
||
2115 | |||
2116 | |||
2117 | /******************************************************************************** |
||
2118 | * GROUP ACTIONS * |
||
2119 | ********************************************************************************/ |
||
2120 | |||
2121 | |||
2122 | /** |
||
2123 | * Alias for add group select action |
||
2124 | * @param string $title |
||
2125 | * @param array $options |
||
2126 | * @return GroupAction\GroupAction |
||
2127 | */ |
||
2128 | public function addGroupAction($title, $options = []) |
||
2129 | { |
||
2130 | return $this->getGroupActionCollection()->addGroupSelectAction($title, $options); |
||
2131 | } |
||
2132 | |||
2133 | |||
2134 | /** |
||
2135 | * Add group action (select box) |
||
2136 | * @param string $title |
||
2137 | * @param array $options |
||
2138 | * @return GroupAction\GroupAction |
||
2139 | */ |
||
2140 | public function addGroupSelectAction($title, $options = []) |
||
2141 | { |
||
2142 | return $this->getGroupActionCollection()->addGroupSelectAction($title, $options); |
||
2143 | } |
||
2144 | |||
2145 | |||
2146 | /** |
||
2147 | * Add group action (multiselect box) |
||
2148 | * @param string $title |
||
2149 | * @param array $options |
||
2150 | * @return GroupAction\GroupAction |
||
2151 | */ |
||
2152 | public function addGroupMultiSelectAction($title, $options = []) |
||
2153 | { |
||
2154 | return $this->getGroupActionCollection()->addGroupMultiSelectAction($title, $options); |
||
2155 | } |
||
2156 | |||
2157 | |||
2158 | /** |
||
2159 | * Add group action (text input) |
||
2160 | * @param string $title |
||
2161 | * @return GroupAction\GroupAction |
||
2162 | */ |
||
2163 | public function addGroupTextAction($title) |
||
2164 | { |
||
2165 | return $this->getGroupActionCollection()->addGroupTextAction($title); |
||
2166 | } |
||
2167 | |||
2168 | |||
2169 | /** |
||
2170 | * Add group action (textarea) |
||
2171 | * @param string $title |
||
2172 | * @return GroupAction\GroupAction |
||
2173 | */ |
||
2174 | public function addGroupTextareaAction($title) |
||
2175 | { |
||
2176 | return $this->getGroupActionCollection()->addGroupTextareaAction($title); |
||
2177 | } |
||
2178 | |||
2179 | |||
2180 | /** |
||
2181 | * Get collection of all group actions |
||
2182 | * @return GroupAction\GroupActionCollection |
||
2183 | */ |
||
2184 | public function getGroupActionCollection() |
||
2185 | { |
||
2186 | if (!$this->group_action_collection) { |
||
2187 | $this->group_action_collection = new GroupAction\GroupActionCollection($this); |
||
2188 | } |
||
2189 | |||
2190 | return $this->group_action_collection; |
||
2191 | } |
||
2192 | |||
2193 | |||
2194 | /** |
||
2195 | * Has datagrid some group actions? |
||
2196 | * @return bool |
||
2197 | */ |
||
2198 | public function hasGroupActions() |
||
2199 | { |
||
2200 | return (bool) $this->group_action_collection; |
||
2201 | } |
||
2202 | |||
2203 | |||
2204 | /** |
||
2205 | * @return bool |
||
2206 | */ |
||
2207 | public function shouldShowSelectedRowsCount() |
||
2208 | { |
||
2209 | return $this->show_selected_rows_count; |
||
2210 | } |
||
2211 | |||
2212 | |||
2213 | /** |
||
2214 | * @return static |
||
2215 | */ |
||
2216 | public function setShowSelectedRowsCount($show = true) |
||
2217 | { |
||
2218 | $this->show_selected_rows_count = (bool) $show; |
||
2219 | |||
2220 | return $this; |
||
2221 | } |
||
2222 | |||
2223 | |||
2224 | /******************************************************************************** |
||
2225 | * HANDLERS * |
||
2226 | ********************************************************************************/ |
||
2227 | |||
2228 | |||
2229 | /** |
||
2230 | * Handler for changind page (just refresh site with page as persistent paramter set) |
||
2231 | * @param int $page |
||
2232 | * @return void |
||
2233 | */ |
||
2234 | public function handlePage($page) |
||
2235 | { |
||
2236 | /** |
||
2237 | * Session stuff |
||
2238 | */ |
||
2239 | $this->page = $page; |
||
2240 | $this->saveSessionData('_grid_page', $page); |
||
2241 | |||
2242 | $this->reload(['table']); |
||
2243 | } |
||
2244 | |||
2245 | |||
2246 | /** |
||
2247 | * Handler for sorting |
||
2248 | * @param array $sort |
||
2249 | * @return void |
||
2250 | * @throws DataGridColumnNotFoundException |
||
2251 | */ |
||
2252 | public function handleSort(array $sort) |
||
2253 | { |
||
2254 | foreach ($sort as $key => $value) { |
||
2255 | try { |
||
2256 | $column = $this->getColumn($key); |
||
2257 | |||
2258 | } catch (DataGridColumnNotFoundException $e) { |
||
2259 | unset($sort[$key]); |
||
2260 | continue; |
||
2261 | } |
||
2262 | |||
2263 | if ($column->sortableResetPagination()) { |
||
2264 | $this->saveSessionData('_grid_page', $this->page = 1); |
||
2265 | } |
||
2266 | |||
2267 | if ($column->getSortableCallback()) { |
||
2268 | $this->sort_callback = $column->getSortableCallback(); |
||
2269 | } |
||
2270 | } |
||
2271 | |||
2272 | $this->saveSessionData('_grid_has_sorted', 1); |
||
2273 | $this->saveSessionData('_grid_sort', $this->sort = $sort); |
||
2274 | |||
2275 | $this->reloadTheWholeGrid(); |
||
2276 | } |
||
2277 | |||
2278 | |||
2279 | /** |
||
2280 | * Handler for reseting the filter |
||
2281 | * @return void |
||
2282 | */ |
||
2283 | public function handleResetFilter() |
||
2284 | { |
||
2285 | /** |
||
2286 | * Session stuff |
||
2287 | */ |
||
2288 | $this->deleteSessionData('_grid_page'); |
||
2289 | |||
2290 | if ($this->default_filter_use_on_reset) { |
||
2291 | $this->deleteSessionData('_grid_has_filtered'); |
||
2292 | } |
||
2293 | |||
2294 | if ($this->default_sort_use_on_reset) { |
||
2295 | $this->deleteSessionData('_grid_has_sorted'); |
||
2296 | } |
||
2297 | |||
2298 | foreach ($this->getSessionData() as $key => $value) { |
||
2299 | if (!in_array($key, [ |
||
2300 | '_grid_per_page', |
||
2301 | '_grid_sort', |
||
2302 | '_grid_page', |
||
2303 | '_grid_has_filtered', |
||
2304 | '_grid_has_sorted', |
||
2305 | '_grid_hidden_columns', |
||
2306 | '_grid_hidden_columns_manipulated', |
||
2307 | ], true)) { |
||
2308 | $this->deleteSessionData($key); |
||
2309 | } |
||
2310 | } |
||
2311 | |||
2312 | $this->filter = []; |
||
2313 | |||
2314 | $this->reloadTheWholeGrid(); |
||
2315 | } |
||
2316 | |||
2317 | |||
2318 | /** |
||
2319 | * @param string $key |
||
2320 | * @return void |
||
2321 | */ |
||
2322 | public function handleResetColumnFilter($key) |
||
2323 | { |
||
2324 | $this->deleteSessionData($key); |
||
2325 | unset($this->filter[$key]); |
||
2326 | |||
2327 | $this->reloadTheWholeGrid(); |
||
2328 | } |
||
2329 | |||
2330 | |||
2331 | /** |
||
2332 | * @param bool $reset |
||
2333 | * @return static |
||
2334 | */ |
||
2335 | public function setColumnReset($reset = true) |
||
2336 | { |
||
2337 | $this->has_column_reset = (bool) $reset; |
||
2338 | |||
2339 | return $this; |
||
2340 | } |
||
2341 | |||
2342 | |||
2343 | /** |
||
2344 | * @return bool |
||
2345 | */ |
||
2346 | public function hasColumnReset() |
||
2347 | { |
||
2348 | 1 | return $this->has_column_reset; |
|
2349 | } |
||
2350 | |||
2351 | |||
2352 | /** |
||
2353 | * @param Filter\Filter[] $filters |
||
2354 | * @return void |
||
2355 | */ |
||
2356 | public function sendNonEmptyFiltersInPayload($filters) |
||
2357 | { |
||
2358 | 1 | if (!$this->hasColumnReset()) { |
|
2359 | return; |
||
2360 | } |
||
2361 | |||
2362 | 1 | $non_empty_filters = []; |
|
2363 | |||
2364 | 1 | foreach ($filters as $filter) { |
|
2365 | 1 | if ($filter->isValueSet()) { |
|
2366 | 1 | $non_empty_filters[] = $filter->getKey(); |
|
2367 | } |
||
2368 | } |
||
2369 | |||
2370 | 1 | $this->getPresenter()->payload->non_empty_filters = $non_empty_filters; |
|
2371 | 1 | } |
|
2372 | |||
2373 | |||
2374 | /** |
||
2375 | * Handler for export |
||
2376 | * @param int $id Key for particular export class in array $this->exports |
||
2377 | * @return void |
||
2378 | */ |
||
2379 | public function handleExport($id) |
||
2380 | { |
||
2381 | 1 | if (!isset($this->exports[$id])) { |
|
2382 | throw new Nette\Application\ForbiddenRequestException; |
||
2383 | } |
||
2384 | |||
2385 | 1 | if (!empty($this->columns_export_order)) { |
|
2386 | $this->setColumnsOrder($this->columns_export_order); |
||
2387 | } |
||
2388 | |||
2389 | 1 | $export = $this->exports[$id]; |
|
2390 | |||
2391 | /** |
||
2392 | * Invoke possible events |
||
2393 | */ |
||
2394 | 1 | $this->onExport($this); |
|
2395 | |||
2396 | 1 | if ($export->isFiltered()) { |
|
2397 | 1 | $sort = $this->sort; |
|
2398 | 1 | $filter = $this->assembleFilters(); |
|
2399 | } else { |
||
2400 | 1 | $sort = [$this->primary_key => 'ASC']; |
|
2401 | 1 | $filter = []; |
|
2402 | } |
||
2403 | |||
2404 | 1 | if ($this->dataModel === null) { |
|
2405 | 1 | throw new DataGridException('You have to set a data source first.'); |
|
2406 | } |
||
2407 | |||
2408 | 1 | $rows = []; |
|
2409 | |||
2410 | 1 | $items = Nette\Utils\Callback::invokeArgs( |
|
2411 | 1 | [$this->dataModel, 'filterData'], [ |
|
2412 | 1 | null, |
|
2413 | 1 | $this->createSorting($this->sort, $this->sort_callback), |
|
2414 | 1 | $filter, |
|
2415 | ] |
||
2416 | ); |
||
2417 | |||
2418 | 1 | foreach ($items as $item) { |
|
2419 | 1 | $rows[] = new Row($this, $item, $this->getPrimaryKey()); |
|
2420 | } |
||
2421 | |||
2422 | 1 | if ($export instanceof Export\ExportCsv) { |
|
2423 | 1 | $export->invoke($rows); |
|
2424 | } else { |
||
2425 | 1 | $export->invoke($items); |
|
2426 | } |
||
2427 | |||
2428 | 1 | if ($export->isAjax()) { |
|
2429 | $this->reload(); |
||
2430 | } |
||
2431 | 1 | } |
|
2432 | |||
2433 | |||
2434 | /** |
||
2435 | * Handler for getting children of parent item (e.g. category) |
||
2436 | * @param int $parent |
||
2437 | * @return void |
||
2438 | */ |
||
2439 | View Code Duplication | public function handleGetChildren($parent) |
|
2440 | { |
||
2441 | $this->setDataSource( |
||
2442 | call_user_func($this->tree_view_children_callback, $parent) |
||
2443 | ); |
||
2444 | |||
2445 | if ($this->getPresenter()->isAjax()) { |
||
2446 | $this->getPresenter()->payload->_datagrid_url = $this->refresh_url; |
||
2447 | $this->getPresenter()->payload->_datagrid_tree = $parent; |
||
2448 | |||
2449 | $this->redrawControl('items'); |
||
2450 | |||
2451 | $this->onRedraw(); |
||
2452 | } else { |
||
2453 | $this->getPresenter()->redirect('this'); |
||
2454 | } |
||
2455 | } |
||
2456 | |||
2457 | |||
2458 | /** |
||
2459 | * Handler for getting item detail |
||
2460 | * @param mixed $id |
||
2461 | * @return void |
||
2462 | */ |
||
2463 | public function handleGetItemDetail($id) |
||
2464 | { |
||
2465 | $this->getTemplate()->add('toggle_detail', $id); |
||
2466 | $this->redraw_item = [$this->items_detail->getPrimaryWhereColumn() => $id]; |
||
2467 | |||
2468 | if ($this->getPresenter()->isAjax()) { |
||
2469 | $this->getPresenter()->payload->_datagrid_toggle_detail = $id; |
||
2470 | $this->redrawControl('items'); |
||
2471 | |||
2472 | /** |
||
2473 | * Only for nette 2.4 |
||
2474 | */ |
||
2475 | if (method_exists($this->getTemplate()->getLatte(), 'addProvider')) { |
||
2476 | $this->redrawControl('gridSnippets'); |
||
2477 | } |
||
2478 | |||
2479 | $this->onRedraw(); |
||
2480 | } else { |
||
2481 | $this->getPresenter()->redirect('this'); |
||
2482 | } |
||
2483 | } |
||
2484 | |||
2485 | |||
2486 | /** |
||
2487 | * Handler for inline editing |
||
2488 | * @param mixed $id |
||
2489 | * @param mixed $key |
||
2490 | * @return void |
||
2491 | */ |
||
2492 | public function handleEdit($id, $key) |
||
2493 | { |
||
2494 | $column = $this->getColumn($key); |
||
2495 | $value = $this->getPresenter()->getRequest()->getPost('value'); |
||
2496 | |||
2497 | /** |
||
2498 | * @var mixed Could be NULL of course |
||
2499 | */ |
||
2500 | $new_value = call_user_func_array($column->getEditableCallback(), [$id, $value]); |
||
2501 | |||
2502 | $this->getPresenter()->payload->_datagrid_editable_new_value = $new_value; |
||
2503 | } |
||
2504 | |||
2505 | |||
2506 | /** |
||
2507 | * Redraw $this |
||
2508 | * @return void |
||
2509 | */ |
||
2510 | public function reload($snippets = []) |
||
2511 | { |
||
2512 | if ($this->getPresenter()->isAjax()) { |
||
2513 | $this->redrawControl('tbody'); |
||
2514 | $this->redrawControl('pagination'); |
||
2515 | $this->redrawControl('summary'); |
||
2516 | $this->redrawControl('thead-group-action'); |
||
2517 | |||
2518 | /** |
||
2519 | * manualy reset exports links... |
||
2520 | */ |
||
2521 | $this->resetExportsLinks(); |
||
2522 | $this->redrawControl('exports'); |
||
2523 | |||
2524 | foreach ($snippets as $snippet) { |
||
2525 | $this->redrawControl($snippet); |
||
2526 | } |
||
2527 | |||
2528 | $this->getPresenter()->payload->_datagrid_url = $this->refresh_url; |
||
2529 | $this->getPresenter()->payload->_datagrid_name = $this->getName(); |
||
2530 | |||
2531 | $this->onRedraw(); |
||
2532 | } else { |
||
2533 | $this->getPresenter()->redirect('this'); |
||
2534 | } |
||
2535 | } |
||
2536 | |||
2537 | |||
2538 | /** |
||
2539 | * @return void |
||
2540 | */ |
||
2541 | View Code Duplication | public function reloadTheWholeGrid() |
|
2542 | { |
||
2543 | if ($this->getPresenter()->isAjax()) { |
||
2544 | $this->redrawControl('grid'); |
||
2545 | |||
2546 | $this->getPresenter()->payload->_datagrid_url = $this->refresh_url; |
||
2547 | $this->getPresenter()->payload->_datagrid_name = $this->getName(); |
||
2548 | |||
2549 | $this->onRedraw(); |
||
2550 | } else { |
||
2551 | $this->getPresenter()->redirect('this'); |
||
2552 | } |
||
2553 | } |
||
2554 | |||
2555 | |||
2556 | /** |
||
2557 | * Handler for column status |
||
2558 | * @param string $id |
||
2559 | * @param string $key |
||
2560 | * @param string $value |
||
2561 | * @return void |
||
2562 | */ |
||
2563 | public function handleChangeStatus($id, $key, $value) |
||
2564 | { |
||
2565 | if (empty($this->columns[$key])) { |
||
2566 | throw new DataGridException("ColumnStatus[$key] does not exist"); |
||
2567 | } |
||
2568 | |||
2569 | $this->columns[$key]->onChange($id, $value); |
||
2570 | } |
||
2571 | |||
2572 | |||
2573 | /** |
||
2574 | * Redraw just one row via ajax |
||
2575 | * @param int $id |
||
2576 | * @param mixed $primary_where_column |
||
2577 | * @return void |
||
2578 | */ |
||
2579 | public function redrawItem($id, $primary_where_column = null) |
||
2580 | { |
||
2581 | $this->snippets_set = true; |
||
2582 | |||
2583 | $this->redraw_item = [($primary_where_column ?: $this->primary_key) => $id]; |
||
2584 | |||
2585 | $this->redrawControl('items'); |
||
2586 | |||
2587 | $this->getPresenter()->payload->_datagrid_url = $this->refresh_url; |
||
2588 | |||
2589 | $this->onRedraw(); |
||
2590 | } |
||
2591 | |||
2592 | |||
2593 | /** |
||
2594 | * Tell datagrid to display all columns |
||
2595 | * @return void |
||
2596 | */ |
||
2597 | public function handleShowAllColumns() |
||
2598 | { |
||
2599 | $this->deleteSessionData('_grid_hidden_columns'); |
||
2600 | $this->saveSessionData('_grid_hidden_columns_manipulated', true); |
||
2601 | |||
2602 | $this->redrawControl(); |
||
2603 | |||
2604 | $this->onRedraw(); |
||
2605 | } |
||
2606 | |||
2607 | |||
2608 | /** |
||
2609 | * Tell datagrid to display default columns |
||
2610 | * @return void |
||
2611 | */ |
||
2612 | public function handleShowDefaultColumns() |
||
2613 | { |
||
2614 | $this->deleteSessionData('_grid_hidden_columns'); |
||
2615 | $this->saveSessionData('_grid_hidden_columns_manipulated', false); |
||
2616 | |||
2617 | $this->redrawControl(); |
||
2618 | |||
2619 | $this->onRedraw(); |
||
2620 | } |
||
2621 | |||
2622 | |||
2623 | /** |
||
2624 | * Reveal particular column |
||
2625 | * @param string $column |
||
2626 | * @return void |
||
2627 | */ |
||
2628 | View Code Duplication | public function handleShowColumn($column) |
|
2629 | { |
||
2630 | $columns = $this->getSessionData('_grid_hidden_columns'); |
||
2631 | |||
2632 | if (!empty($columns)) { |
||
2633 | $pos = array_search($column, $columns, true); |
||
2634 | |||
2635 | if ($pos !== false) { |
||
2636 | unset($columns[$pos]); |
||
2637 | } |
||
2638 | } |
||
2639 | |||
2640 | $this->saveSessionData('_grid_hidden_columns', $columns); |
||
2641 | $this->saveSessionData('_grid_hidden_columns_manipulated', true); |
||
2642 | |||
2643 | $this->redrawControl(); |
||
2644 | |||
2645 | $this->onRedraw(); |
||
2646 | } |
||
2647 | |||
2648 | |||
2649 | /** |
||
2650 | * Notice datagrid to not display particular columns |
||
2651 | * @param string $column |
||
2652 | * @return void |
||
2653 | */ |
||
2654 | View Code Duplication | public function handleHideColumn($column) |
|
2655 | { |
||
2656 | /** |
||
2657 | * Store info about hiding a column to session |
||
2658 | */ |
||
2659 | $columns = $this->getSessionData('_grid_hidden_columns'); |
||
2660 | |||
2661 | if (empty($columns)) { |
||
2662 | $columns = [$column]; |
||
2663 | } elseif (!in_array($column, $columns, true)) { |
||
2664 | array_push($columns, $column); |
||
2665 | } |
||
2666 | |||
2667 | $this->saveSessionData('_grid_hidden_columns', $columns); |
||
2668 | $this->saveSessionData('_grid_hidden_columns_manipulated', true); |
||
2669 | |||
2670 | $this->redrawControl(); |
||
2671 | |||
2672 | $this->onRedraw(); |
||
2673 | } |
||
2674 | |||
2675 | |||
2676 | public function handleActionCallback($__key, $__id) |
||
2677 | { |
||
2678 | $action = $this->getAction($__key); |
||
2679 | |||
2680 | if (!($action instanceof Column\ActionCallback)) { |
||
2681 | throw new DataGridException("Action [$__key] does not exist or is not an callback aciton."); |
||
2682 | } |
||
2683 | |||
2684 | $action->onClick($__id); |
||
2685 | } |
||
2686 | |||
2687 | |||
2688 | /******************************************************************************** |
||
2689 | * PAGINATION * |
||
2690 | ********************************************************************************/ |
||
2691 | |||
2692 | |||
2693 | /** |
||
2694 | * Set options of select "items_per_page" |
||
2695 | * @param array $items_per_page_list |
||
2696 | * @return static |
||
2697 | */ |
||
2698 | public function setItemsPerPageList(array $items_per_page_list, $include_all = true) |
||
2699 | { |
||
2700 | $this->items_per_page_list = $items_per_page_list; |
||
2701 | |||
2702 | if ($include_all) { |
||
2703 | $this->items_per_page_list[] = 'all'; |
||
2704 | } |
||
2705 | |||
2706 | return $this; |
||
2707 | } |
||
2708 | |||
2709 | |||
2710 | /** |
||
2711 | * Set default "items per page" value in pagination select |
||
2712 | * @param $count |
||
2713 | * @return static |
||
2714 | */ |
||
2715 | public function setDefaultPerPage($count) |
||
2716 | { |
||
2717 | $this->default_per_page = $count; |
||
2718 | |||
2719 | return $this; |
||
2720 | } |
||
2721 | |||
2722 | |||
2723 | /** |
||
2724 | * User may set default "items per page" value, apply it |
||
2725 | * @return void |
||
2726 | */ |
||
2727 | public function findDefaultPerPage() |
||
2728 | { |
||
2729 | if (!empty($this->per_page)) { |
||
2730 | return; |
||
2731 | } |
||
2732 | |||
2733 | if (!empty($this->default_per_page)) { |
||
2734 | $this->per_page = $this->default_per_page; |
||
2735 | } |
||
2736 | |||
2737 | $this->saveSessionData('_grid_per_page', $this->per_page); |
||
2738 | } |
||
2739 | |||
2740 | |||
2741 | /** |
||
2742 | * Paginator factory |
||
2743 | * @return Components\DataGridPaginator\DataGridPaginator |
||
2744 | */ |
||
2745 | public function createComponentPaginator() |
||
2746 | { |
||
2747 | /** |
||
2748 | * Init paginator |
||
2749 | */ |
||
2750 | $component = new Components\DataGridPaginator\DataGridPaginator( |
||
2751 | $this->getTranslator(), |
||
2752 | static::$icon_prefix |
||
2753 | ); |
||
2754 | $paginator = $component->getPaginator(); |
||
2755 | |||
2756 | $paginator->setPage($this->page); |
||
2757 | $paginator->setItemsPerPage($this->getPerPage()); |
||
2758 | |||
2759 | return $component; |
||
2760 | } |
||
2761 | |||
2762 | |||
2763 | /** |
||
2764 | * Get parameter per_page |
||
2765 | * @return int |
||
2766 | */ |
||
2767 | public function getPerPage() |
||
2768 | { |
||
2769 | $items_per_page_list = $this->getItemsPerPageList(); |
||
2770 | |||
2771 | $per_page = $this->per_page ?: reset($items_per_page_list); |
||
2772 | |||
2773 | if ($per_page !== 'all' && !in_array((int) $this->per_page, $items_per_page_list, true)) { |
||
2774 | $per_page = reset($items_per_page_list); |
||
2775 | } |
||
2776 | |||
2777 | return $per_page; |
||
2778 | } |
||
2779 | |||
2780 | |||
2781 | /** |
||
2782 | * Get associative array of items_per_page_list |
||
2783 | * @return array |
||
2784 | */ |
||
2785 | public function getItemsPerPageList() |
||
2786 | { |
||
2787 | if (empty($this->items_per_page_list)) { |
||
2788 | $this->setItemsPerPageList([10, 20, 50], true); |
||
2789 | } |
||
2790 | |||
2791 | $list = array_flip($this->items_per_page_list); |
||
2792 | |||
2793 | foreach ($list as $key => $value) { |
||
2794 | $list[$key] = $key; |
||
2795 | } |
||
2796 | |||
2797 | if (array_key_exists('all', $list)) { |
||
2798 | $list['all'] = $this->getTranslator()->translate('ublaboo_datagrid.all'); |
||
2799 | } |
||
2800 | |||
2801 | return $list; |
||
2802 | } |
||
2803 | |||
2804 | |||
2805 | /** |
||
2806 | * Order Grid to "be paginated" |
||
2807 | * @param bool $do |
||
2808 | * @return static |
||
2809 | */ |
||
2810 | public function setPagination($do) |
||
2811 | { |
||
2812 | $this->do_paginate = (bool) $do; |
||
2813 | |||
2814 | return $this; |
||
2815 | } |
||
2816 | |||
2817 | |||
2818 | /** |
||
2819 | * Tell whether Grid is paginated |
||
2820 | * @return bool |
||
2821 | */ |
||
2822 | public function isPaginated() |
||
2823 | { |
||
2824 | return $this->do_paginate; |
||
2825 | } |
||
2826 | |||
2827 | |||
2828 | /** |
||
2829 | * Return current paginator class |
||
2830 | * @return NULL|Components\DataGridPaginator\DataGridPaginator |
||
2831 | */ |
||
2832 | public function getPaginator() |
||
2833 | { |
||
2834 | if ($this->isPaginated() && $this->getPerPage() !== 'all') { |
||
2835 | return $this['paginator']; |
||
2836 | } |
||
2837 | |||
2838 | return null; |
||
2839 | } |
||
2840 | |||
2841 | |||
2842 | /******************************************************************************** |
||
2843 | * I18N * |
||
2844 | ********************************************************************************/ |
||
2845 | |||
2846 | |||
2847 | /** |
||
2848 | * Set datagrid translator |
||
2849 | * @param Nette\Localization\ITranslator $translator |
||
2850 | * @return static |
||
2851 | */ |
||
2852 | public function setTranslator(Nette\Localization\ITranslator $translator) |
||
2853 | { |
||
2854 | $this->translator = $translator; |
||
2855 | |||
2856 | return $this; |
||
2857 | } |
||
2858 | |||
2859 | |||
2860 | /** |
||
2861 | * Get translator for datagrid |
||
2862 | * @return Nette\Localization\ITranslator |
||
2863 | */ |
||
2864 | public function getTranslator() |
||
2865 | { |
||
2866 | 1 | if (!$this->translator) { |
|
2867 | 1 | $this->translator = new Localization\SimpleTranslator; |
|
2868 | } |
||
2869 | |||
2870 | 1 | return $this->translator; |
|
2871 | } |
||
2872 | |||
2873 | |||
2874 | /******************************************************************************** |
||
2875 | * COLUMNS ORDER * |
||
2876 | ********************************************************************************/ |
||
2877 | |||
2878 | |||
2879 | /** |
||
2880 | * Set order of datagrid columns |
||
2881 | * @param array $order |
||
2882 | * @return static |
||
2883 | */ |
||
2884 | public function setColumnsOrder($order) |
||
2885 | { |
||
2886 | $new_order = []; |
||
2887 | |||
2888 | foreach ($order as $key) { |
||
2889 | if (isset($this->columns[$key])) { |
||
2890 | $new_order[$key] = $this->columns[$key]; |
||
2891 | } |
||
2892 | } |
||
2893 | |||
2894 | if (sizeof($new_order) === sizeof($this->columns)) { |
||
2895 | $this->columns = $new_order; |
||
2896 | } else { |
||
2897 | throw new DataGridException('When changing columns order, you have to specify all columns'); |
||
2898 | } |
||
2899 | |||
2900 | return $this; |
||
2901 | } |
||
2902 | |||
2903 | |||
2904 | /** |
||
2905 | * Columns order may be different for export and normal grid |
||
2906 | * @param array $order |
||
2907 | */ |
||
2908 | public function setColumnsExportOrder($order) |
||
2909 | { |
||
2910 | $this->columns_export_order = (array) $order; |
||
2911 | } |
||
2912 | |||
2913 | |||
2914 | /******************************************************************************** |
||
2915 | * SESSION & URL * |
||
2916 | ********************************************************************************/ |
||
2917 | |||
2918 | |||
2919 | /** |
||
2920 | * Find some unique session key name |
||
2921 | * @return string |
||
2922 | */ |
||
2923 | public function getSessionSectionName() |
||
2924 | { |
||
2925 | 1 | return $this->getPresenter()->getName() . ':' . $this->getUniqueId(); |
|
2926 | } |
||
2927 | |||
2928 | |||
2929 | /** |
||
2930 | * Should datagrid remember its filters/pagination/etc using session? |
||
2931 | * @param bool $remember |
||
2932 | * @return static |
||
2933 | */ |
||
2934 | public function setRememberState($remember = true) |
||
2935 | { |
||
2936 | $this->remember_state = (bool) $remember; |
||
2937 | |||
2938 | return $this; |
||
2939 | } |
||
2940 | |||
2941 | |||
2942 | /** |
||
2943 | * Should datagrid refresh url using history API? |
||
2944 | * @param bool $refresh |
||
2945 | * @return static |
||
2946 | */ |
||
2947 | public function setRefreshUrl($refresh = true) |
||
2948 | { |
||
2949 | $this->refresh_url = (bool) $refresh; |
||
2950 | |||
2951 | |||
2952 | return $this; |
||
2953 | } |
||
2954 | |||
2955 | |||
2956 | /** |
||
2957 | * Get session data if functionality is enabled |
||
2958 | * @param string $key |
||
2959 | * @return mixed |
||
2960 | */ |
||
2961 | public function getSessionData($key = null, $default_value = null) |
||
2962 | { |
||
2963 | 1 | if (!$this->remember_state) { |
|
2964 | return $key ? $default_value : []; |
||
2965 | } |
||
2966 | |||
2967 | 1 | return ($key ? $this->grid_session->{$key} : $this->grid_session) ?: $default_value; |
|
2968 | } |
||
2969 | |||
2970 | |||
2971 | /** |
||
2972 | * Save session data - just if it is enabled |
||
2973 | * @param string $key |
||
2974 | * @param mixed $value |
||
2975 | * @return void |
||
2976 | */ |
||
2977 | public function saveSessionData($key, $value) |
||
2978 | { |
||
2979 | 1 | if ($this->remember_state) { |
|
2980 | 1 | $this->grid_session->{$key} = $value; |
|
2981 | } |
||
2982 | 1 | } |
|
2983 | |||
2984 | |||
2985 | /** |
||
2986 | * Delete session data |
||
2987 | * @return void |
||
2988 | */ |
||
2989 | public function deleteSessionData($key) |
||
2990 | { |
||
2991 | unset($this->grid_session->{$key}); |
||
2992 | } |
||
2993 | |||
2994 | |||
2995 | /** |
||
2996 | * Delete session data |
||
2997 | * @return void |
||
2998 | * @deprecated |
||
2999 | */ |
||
3000 | public function deleteSesssionData($key) |
||
3001 | { |
||
3002 | @trigger_error('deleteSesssionData is deprecated, use deleteSessionData instead', E_USER_DEPRECATED); |
||
3003 | return $this->deleteSessionData($key); |
||
3004 | } |
||
3005 | |||
3006 | |||
3007 | /******************************************************************************** |
||
3008 | * ITEM DETAIL * |
||
3009 | ********************************************************************************/ |
||
3010 | |||
3011 | |||
3012 | /** |
||
3013 | * Get items detail parameters |
||
3014 | * @return array |
||
3015 | */ |
||
3016 | public function getItemsDetail() |
||
3017 | { |
||
3018 | return $this->items_detail; |
||
3019 | } |
||
3020 | |||
3021 | |||
3022 | /** |
||
3023 | * Items can have thair detail - toggled |
||
3024 | * @param mixed $detail callable|string|bool |
||
3025 | * @param bool|NULL $primary_where_column |
||
3026 | * @return Column\ItemDetail |
||
3027 | */ |
||
3028 | public function setItemsDetail($detail = true, $primary_where_column = null) |
||
3029 | { |
||
3030 | if ($this->isSortable()) { |
||
3031 | throw new DataGridException('You can not use both sortable datagrid and items detail.'); |
||
3032 | } |
||
3033 | |||
3034 | $this->items_detail = new Column\ItemDetail( |
||
3035 | $this, |
||
3036 | $primary_where_column ?: $this->primary_key |
||
3037 | ); |
||
3038 | |||
3039 | if (is_string($detail)) { |
||
3040 | /** |
||
3041 | * Item detail will be in separate template |
||
3042 | */ |
||
3043 | $this->items_detail->setType('template'); |
||
3044 | $this->items_detail->setTemplate($detail); |
||
3045 | |||
3046 | } elseif (is_callable($detail)) { |
||
3047 | /** |
||
3048 | * Item detail will be rendered via custom callback renderer |
||
3049 | */ |
||
3050 | $this->items_detail->setType('renderer'); |
||
3051 | $this->items_detail->setRenderer($detail); |
||
3052 | |||
3053 | } elseif ($detail === true) { |
||
3054 | /** |
||
3055 | * Item detail will be rendered probably via block #detail |
||
3056 | */ |
||
3057 | $this->items_detail->setType('block'); |
||
3058 | |||
3059 | } else { |
||
3060 | throw new DataGridException( |
||
3061 | '::setItemsDetail() can be called either with no parameters or with parameter = template path or callable renderer.' |
||
3062 | ); |
||
3063 | } |
||
3064 | |||
3065 | return $this->items_detail; |
||
3066 | } |
||
3067 | |||
3068 | |||
3069 | /** |
||
3070 | * @param callable $callable_set_container |
||
3071 | * @return static |
||
3072 | */ |
||
3073 | public function setItemsDetailForm(callable $callable_set_container) |
||
3074 | { |
||
3075 | if ($this->items_detail instanceof Column\ItemDetail) { |
||
3076 | $this->items_detail->setForm( |
||
3077 | new Utils\ItemDetailForm($callable_set_container) |
||
3078 | ); |
||
3079 | |||
3080 | return $this; |
||
3081 | } |
||
3082 | |||
3083 | throw new DataGridException('Please set the ItemDetail first.'); |
||
3084 | } |
||
3085 | |||
3086 | |||
3087 | /** |
||
3088 | * @return Nette\Forms\Container|NULL |
||
3089 | */ |
||
3090 | public function getItemDetailForm() |
||
3091 | { |
||
3092 | if ($this->items_detail instanceof Column\ItemDetail) { |
||
3093 | return $this->items_detail->getForm(); |
||
3094 | } |
||
3095 | |||
3096 | return null; |
||
3097 | } |
||
3098 | |||
3099 | |||
3100 | /******************************************************************************** |
||
3101 | * ROW PRIVILEGES * |
||
3102 | ********************************************************************************/ |
||
3103 | |||
3104 | |||
3105 | /** |
||
3106 | * @param callable $condition |
||
3107 | * @return void |
||
3108 | */ |
||
3109 | public function allowRowsGroupAction(callable $condition) |
||
3110 | { |
||
3111 | $this->row_conditions['group_action'] = $condition; |
||
3112 | } |
||
3113 | |||
3114 | |||
3115 | /** |
||
3116 | * @param callable $condition |
||
3117 | * @return void |
||
3118 | */ |
||
3119 | public function allowRowsInlineEdit(callable $condition) |
||
3120 | { |
||
3121 | $this->row_conditions['inline_edit'] = $condition; |
||
3122 | } |
||
3123 | |||
3124 | |||
3125 | /** |
||
3126 | * @param string $key |
||
3127 | * @param callable $condition |
||
3128 | * @return void |
||
3129 | */ |
||
3130 | public function allowRowsAction($key, callable $condition) |
||
3131 | { |
||
3132 | $this->row_conditions['action'][$key] = $condition; |
||
3133 | } |
||
3134 | |||
3135 | |||
3136 | /** |
||
3137 | * @param string $multiActionKey |
||
3138 | * @param string $actionKey |
||
3139 | * @param callable $condition |
||
3140 | * @return void |
||
3141 | */ |
||
3142 | public function allowRowsMultiAction($multiActionKey, $actionKey, callable $condition) |
||
3143 | { |
||
3144 | if (!isset($this->actions[$multiActionKey])) { |
||
3145 | throw new DataGridException("There is no action at key [$multiActionKey] defined."); |
||
3146 | } |
||
3147 | |||
3148 | if (!$this->actions[$multiActionKey] instanceof Column\MultiAction) { |
||
3149 | throw new DataGridException("Action at key [$multiActionKey] is not a MultiAction."); |
||
3150 | } |
||
3151 | |||
3152 | $this->actions[$multiActionKey]->setRowCondition((string) $actionKey, $condition); |
||
3153 | } |
||
3154 | |||
3155 | |||
3156 | /** |
||
3157 | * @param string $name |
||
3158 | * @param string|null $key |
||
3159 | * @return bool|callable |
||
3160 | */ |
||
3161 | public function getRowCondition($name, $key = null) |
||
3162 | { |
||
3163 | if (!isset($this->row_conditions[$name])) { |
||
3164 | return false; |
||
3165 | } |
||
3166 | |||
3167 | $condition = $this->row_conditions[$name]; |
||
3168 | |||
3169 | if (!$key) { |
||
3170 | return $condition; |
||
3171 | } |
||
3172 | |||
3173 | return isset($condition[$key]) ? $condition[$key] : false; |
||
3174 | } |
||
3175 | |||
3176 | |||
3177 | /******************************************************************************** |
||
3178 | * COLUMN CALLBACK * |
||
3179 | ********************************************************************************/ |
||
3180 | |||
3181 | |||
3182 | /** |
||
3183 | * @param string $key |
||
3184 | * @param callable $callback |
||
3185 | * @return void |
||
3186 | */ |
||
3187 | public function addColumnCallback($key, callable $callback) |
||
3188 | { |
||
3189 | $this->column_callbacks[$key] = $callback; |
||
3190 | } |
||
3191 | |||
3192 | |||
3193 | /** |
||
3194 | * @param string $key |
||
3195 | * @return callable|null |
||
3196 | */ |
||
3197 | public function getColumnCallback($key) |
||
3198 | { |
||
3199 | return empty($this->column_callbacks[$key]) ? null : $this->column_callbacks[$key]; |
||
3200 | } |
||
3201 | |||
3202 | |||
3203 | /******************************************************************************** |
||
3204 | * INLINE EDIT * |
||
3205 | ********************************************************************************/ |
||
3206 | |||
3207 | |||
3208 | /** |
||
3209 | * @return InlineEdit |
||
3210 | */ |
||
3211 | public function addInlineEdit($primary_where_column = null) |
||
3212 | { |
||
3213 | $this->inlineEdit = new InlineEdit($this, $primary_where_column ?: $this->primary_key); |
||
3214 | |||
3215 | return $this->inlineEdit; |
||
3216 | } |
||
3217 | |||
3218 | |||
3219 | /** |
||
3220 | * @return InlineEdit|null |
||
3221 | */ |
||
3222 | public function getInlineEdit() |
||
3223 | { |
||
3224 | return $this->inlineEdit; |
||
3225 | } |
||
3226 | |||
3227 | |||
3228 | /** |
||
3229 | * @param mixed $id |
||
3230 | * @return void |
||
3231 | */ |
||
3232 | public function handleInlineEdit($id) |
||
3233 | { |
||
3234 | if ($this->inlineEdit) { |
||
3235 | $this->inlineEdit->setItemId($id); |
||
3236 | |||
3237 | $primary_where_column = $this->inlineEdit->getPrimaryWhereColumn(); |
||
3238 | |||
3239 | $this['filter']['inline_edit']->addHidden('_id', $id); |
||
3240 | $this['filter']['inline_edit']->addHidden('_primary_where_column', $primary_where_column); |
||
3241 | |||
3242 | if ($this->getPresenter()->isAjax()) { |
||
3243 | $this->getPresenter()->payload->_datagrid_inline_editing = true; |
||
3244 | $this->getPresenter()->payload->_datagrid_name = $this->getName(); |
||
3245 | } |
||
3246 | |||
3247 | $this->redrawItem($id, $primary_where_column); |
||
3248 | } |
||
3249 | } |
||
3250 | |||
3251 | |||
3252 | /******************************************************************************** |
||
3253 | * INLINE ADD * |
||
3254 | ********************************************************************************/ |
||
3255 | |||
3256 | |||
3257 | /** |
||
3258 | * @return InlineEdit |
||
3259 | */ |
||
3260 | public function addInlineAdd() |
||
3261 | { |
||
3262 | $this->inlineAdd = new InlineEdit($this); |
||
3263 | |||
3264 | $this->inlineAdd |
||
3265 | ->setTitle('ublaboo_datagrid.add') |
||
3266 | ->setIcon('plus') |
||
3267 | ->setClass('btn btn-xs btn-default'); |
||
3268 | |||
3269 | return $this->inlineAdd; |
||
3270 | } |
||
3271 | |||
3272 | |||
3273 | /** |
||
3274 | * @return InlineEdit|null |
||
3275 | */ |
||
3276 | public function getInlineAdd() |
||
3277 | { |
||
3278 | return $this->inlineAdd; |
||
3279 | } |
||
3280 | |||
3281 | |||
3282 | /******************************************************************************** |
||
3283 | * HIDEABLE COLUMNS * |
||
3284 | ********************************************************************************/ |
||
3285 | |||
3286 | |||
3287 | /** |
||
3288 | * Can datagrid hide colums? |
||
3289 | * @return bool |
||
3290 | */ |
||
3291 | public function canHideColumns() |
||
3292 | { |
||
3293 | return (bool) $this->can_hide_columns; |
||
3294 | } |
||
3295 | |||
3296 | |||
3297 | /** |
||
3298 | * Order Grid to set columns hideable. |
||
3299 | * @return static |
||
3300 | */ |
||
3301 | public function setColumnsHideable() |
||
3302 | { |
||
3303 | $this->can_hide_columns = true; |
||
3304 | |||
3305 | return $this; |
||
3306 | } |
||
3307 | |||
3308 | |||
3309 | /******************************************************************************** |
||
3310 | * COLUMNS SUMMARY * |
||
3311 | ********************************************************************************/ |
||
3312 | |||
3313 | |||
3314 | /** |
||
3315 | * Will datagrid show summary in the end? |
||
3316 | * @return bool |
||
3317 | */ |
||
3318 | public function hasColumnsSummary() |
||
3319 | { |
||
3320 | 1 | return $this->columnsSummary instanceof ColumnsSummary; |
|
3321 | } |
||
3322 | |||
3323 | |||
3324 | /** |
||
3325 | * Set columns to be summarized in the end. |
||
3326 | * @param array $columns |
||
3327 | * @param callable $rowCallback |
||
3328 | * @return \Ublaboo\DataGrid\ColumnsSummary |
||
3329 | */ |
||
3330 | public function setColumnsSummary(array $columns, $rowCallback = null) |
||
3331 | { |
||
3332 | if ($this->hasSomeAggregationFunction()) { |
||
3333 | throw new DataGridException('You can use either ColumnsSummary or AggregationFunctions'); |
||
3334 | } |
||
3335 | |||
3336 | if (!empty($rowCallback)) { |
||
3337 | if (!is_callable($rowCallback)) { |
||
3338 | throw new \InvalidArgumentException('Row summary callback must be callable'); |
||
3339 | } |
||
3340 | } |
||
3341 | |||
3342 | $this->columnsSummary = new ColumnsSummary($this, $columns, $rowCallback); |
||
3343 | |||
3344 | return $this->columnsSummary; |
||
3345 | } |
||
3346 | |||
3347 | |||
3348 | /** |
||
3349 | * @return ColumnsSummary|NULL |
||
3350 | */ |
||
3351 | public function getColumnsSummary() |
||
3352 | { |
||
3353 | return $this->columnsSummary; |
||
3354 | } |
||
3355 | |||
3356 | |||
3357 | /******************************************************************************** |
||
3358 | * INTERNAL * |
||
3359 | ********************************************************************************/ |
||
3360 | |||
3361 | |||
3362 | /** |
||
3363 | * Tell grid filters to by submitted automatically |
||
3364 | * @param bool $auto |
||
3365 | */ |
||
3366 | public function setAutoSubmit($auto = true) |
||
3367 | { |
||
3368 | $this->auto_submit = (bool) $auto; |
||
3369 | |||
3370 | return $this; |
||
3371 | } |
||
3372 | |||
3373 | |||
3374 | /** |
||
3375 | * @return bool |
||
3376 | */ |
||
3377 | public function hasAutoSubmit() |
||
3378 | { |
||
3379 | return $this->auto_submit; |
||
3380 | } |
||
3381 | |||
3382 | |||
3383 | /** |
||
3384 | * Submit button when no auto-submitting is used |
||
3385 | * @return Filter\SubmitButton |
||
3386 | */ |
||
3387 | public function getFilterSubmitButton() |
||
3388 | { |
||
3389 | if ($this->hasAutoSubmit()) { |
||
3390 | throw new DataGridException( |
||
3391 | 'DataGrid has auto-submit. Turn it off before setting filter submit button.' |
||
3392 | ); |
||
3393 | } |
||
3394 | |||
3395 | if ($this->filter_submit_button === null) { |
||
3396 | $this->filter_submit_button = new Filter\SubmitButton($this); |
||
3397 | } |
||
3398 | |||
3399 | return $this->filter_submit_button; |
||
3400 | } |
||
3401 | |||
3402 | |||
3403 | /******************************************************************************** |
||
3404 | * INTERNAL * |
||
3405 | ********************************************************************************/ |
||
3406 | |||
3407 | |||
3408 | /** |
||
3409 | * Get count of columns |
||
3410 | * @return int |
||
3411 | */ |
||
3412 | public function getColumnsCount() |
||
3413 | { |
||
3414 | $count = sizeof($this->getColumns()); |
||
3415 | |||
3416 | if (!empty($this->actions) |
||
3417 | || $this->isSortable() |
||
3418 | || $this->getItemsDetail() |
||
3419 | || $this->getInlineEdit() |
||
3420 | || $this->getInlineAdd()) { |
||
3421 | $count++; |
||
3422 | } |
||
3423 | |||
3424 | if ($this->hasGroupActions()) { |
||
3425 | $count++; |
||
3426 | } |
||
3427 | |||
3428 | return $count; |
||
3429 | } |
||
3430 | |||
3431 | |||
3432 | /** |
||
3433 | * Get primary key of datagrid data source |
||
3434 | * @return string |
||
3435 | */ |
||
3436 | public function getPrimaryKey() |
||
3437 | { |
||
3438 | 1 | return $this->primary_key; |
|
3439 | } |
||
3440 | |||
3441 | |||
3442 | /** |
||
3443 | * Get set of set columns |
||
3444 | * @return Column\IColumn[] |
||
3445 | */ |
||
3446 | public function getColumns() |
||
3447 | { |
||
3448 | 1 | $return = $this->columns; |
|
3449 | |||
3450 | try { |
||
3451 | 1 | $this->getParent(); |
|
3452 | |||
3453 | 1 | if (!$this->getSessionData('_grid_hidden_columns_manipulated', false)) { |
|
3454 | 1 | $columns_to_hide = []; |
|
3455 | |||
3456 | 1 | foreach ($this->columns as $key => $column) { |
|
3457 | if ($column->getDefaultHide()) { |
||
3458 | $columns_to_hide[] = $key; |
||
3459 | } |
||
3460 | } |
||
3461 | |||
3462 | 1 | if (!empty($columns_to_hide)) { |
|
3463 | $this->saveSessionData('_grid_hidden_columns', $columns_to_hide); |
||
3464 | $this->saveSessionData('_grid_hidden_columns_manipulated', true); |
||
3465 | } |
||
3466 | } |
||
3467 | |||
3468 | 1 | $hidden_columns = $this->getSessionData('_grid_hidden_columns', []); |
|
3469 | |||
3470 | 1 | foreach ($hidden_columns as $column) { |
|
3471 | if (!empty($this->columns[$column])) { |
||
3472 | $this->columns_visibility[$column] = [ |
||
3473 | 'visible' => false, |
||
3474 | ]; |
||
3475 | |||
3476 | 1 | unset($return[$column]); |
|
3477 | } |
||
3478 | } |
||
3479 | |||
3480 | } catch (DataGridHasToBeAttachedToPresenterComponentException $e) { |
||
3481 | } |
||
3482 | |||
3483 | 1 | return $return; |
|
3484 | } |
||
3485 | |||
3486 | |||
3487 | public function getColumnsVisibility() |
||
3488 | { |
||
3489 | 1 | $return = $this->columns_visibility; |
|
3490 | |||
3491 | 1 | foreach ($this->columns_visibility as $key => $column) { |
|
3492 | $return[$key]['column'] = $this->columns[$key]; |
||
3493 | } |
||
3494 | |||
3495 | 1 | return $return; |
|
3496 | } |
||
3497 | |||
3498 | |||
3499 | /** |
||
3500 | * @return PresenterComponent |
||
3501 | */ |
||
3502 | public function getParent() |
||
3503 | { |
||
3504 | 1 | $parent = parent::getParent(); |
|
3505 | |||
3506 | 1 | if (!($parent instanceof PresenterComponent)) { |
|
3507 | throw new DataGridHasToBeAttachedToPresenterComponentException( |
||
3508 | "DataGrid is attached to: '" . get_class($parent) . "', but instance of PresenterComponent is needed." |
||
3509 | ); |
||
3510 | } |
||
3511 | |||
3512 | 1 | return $parent; |
|
3513 | } |
||
3514 | |||
3515 | |||
3516 | /** |
||
3517 | * @return string |
||
3518 | */ |
||
3519 | public function getSortableParentPath() |
||
3520 | { |
||
3521 | return $this->getParent()->lookupPath(Nette\Application\IPresenter::class, false); |
||
3522 | } |
||
3523 | |||
3524 | |||
3525 | /** |
||
3526 | * Some of datagrid columns is hidden by default |
||
3527 | * @param bool $default_hide |
||
3528 | */ |
||
3529 | public function setSomeColumnDefaultHide($default_hide) |
||
3530 | { |
||
3531 | $this->some_column_default_hide = $default_hide; |
||
3532 | } |
||
3533 | |||
3534 | |||
3535 | /** |
||
3536 | * Are some of columns hidden bydefault? |
||
3537 | */ |
||
3538 | public function hasSomeColumnDefaultHide() |
||
3539 | { |
||
3540 | return $this->some_column_default_hide; |
||
3541 | } |
||
3542 | |||
3543 | |||
3544 | /** |
||
3545 | * Simply refresh url |
||
3546 | * @return void |
||
3547 | */ |
||
3548 | public function handleRefreshState() |
||
3549 | { |
||
3550 | $this->findSessionValues(); |
||
3551 | $this->findDefaultFilter(); |
||
3552 | $this->findDefaultSort(); |
||
3553 | $this->findDefaultPerPage(); |
||
3554 | |||
3555 | $this->getPresenter()->payload->_datagrid_url = $this->refresh_url; |
||
3556 | $this->redrawControl('non-existing-snippet'); |
||
3557 | } |
||
3558 | } |
||
3559 | |||
3560 |
This property has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.