Grid::getData()   B
last analyzed

Complexity

Conditions 11
Paths 20

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 11.1412

Importance

Changes 0
Metric Value
dl 0
loc 37
ccs 17
cts 19
cp 0.8947
rs 7.3166
c 0
b 0
f 0
cc 11
nc 20
nop 3
crap 11.1412

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file is part of the Grido (https://github.com/o5/grido)
5
 *
6
 * Copyright (c) 2011 Petr Bugyík (http://petr.bugyik.cz)
7
 *
8
 * For the full copyright and license information, please view
9
 * the file LICENSE.md that was distributed with this source code.
10
 */
11
12
namespace Grido;
13
14
use Grido\Exception;
15
use Grido\Components\Button;
16
use Grido\Components\Paginator;
17
use Grido\Components\Columns\Column;
18
use Grido\Components\Filters\Filter;
19
use Grido\Components\Actions\Action;
20
21
use Nette\Application\UI\Presenter;
22
use Symfony\Component\PropertyAccess\PropertyAccessor;
23
24
/**
25
 * Grido - DataGrid for Nette Framework.
26
 *
27
 * @package     Grido
28
 * @author      Petr Bugyík
29 1
 *
30
 * @property-read int $count
31
 * @property-read mixed $data
32
 * @property-read \Nette\Utils\Html $tablePrototype
33
 * @property-read PropertyAccessor $propertyAccessor
34
 * @property-read Customization $customization
35
 * @property-write string $templateFile
36
 * @property bool $rememberState
37
 * @property array $defaultPerPage
38
 * @property array $defaultFilter
39
 * @property array $defaultSort
40 1
 * @property array $perPageList
41
 * @property \Nette\Localization\ITranslator $translator
42 1
 * @property Paginator $paginator
43
 * @property string $primaryKey
44 1
 * @property string $filterRenderType
45
 * @property DataSources\IDataSource $model
46 1
 * @property callback $rowCallback
47
 * @property bool $strictMode
48
 * @method void onRegistered(Grid $grid)
49
 * @method void onRender(Grid $grid)
50 1
 * @method void onFetchData(Grid $grid)
51
 */
52 1
class Grid extends Components\Container
53
{
54
    /***** DEFAULTS ****/
55
    const BUTTONS = 'buttons';
56
57
    const CLIENT_SIDE_OPTIONS = 'grido-options';
58
59
    /** @var int @persistent */
60
    public $page = 1;
61
62
    /** @var int @persistent */
63
    public $perPage;
64
65
    /** @var array @persistent */
66
    public $sort = [];
67 1
68
    /** @var array @persistent */
69
    public $filter = [];
70
71
    /** @var array event on all grid's components registered */
72
    public $onRegistered;
73
74
    /** @var array event on render */
75
    public $onRender;
76
77
    /** @var array event for modifying data */
78
    public $onFetchData;
79
80
    /** @var callback returns tr html element; function($row, Html $tr) */
81
    protected $rowCallback;
82
83
    /** @var \Nette\Utils\Html */
84
    protected $tablePrototype;
85
86
    /** @var bool */
87
    protected $rememberState = FALSE;
88
89
    /** @var string */
90
    protected $rememberStateSectionName;
91
92
    /** @var string */
93
    protected $primaryKey = 'id';
94
95
    /** @var string */
96
    protected $filterRenderType;
97
98
    /** @var array */
99
    protected $perPageList = [10, 20, 30, 50, 100];
100
101
    /** @var int */
102
    protected $defaultPerPage = 20;
103
104
    /** @var array */
105
    protected $defaultFilter = [];
106
107
    /** @var array */
108
    protected $defaultSort = [];
109
110
    /** @var DataSources\IDataSource */
111
    protected $model;
112
113
    /** @var int total count of items */
114
    protected $count;
115
116
    /** @var mixed */
117
    protected $data;
118
119
    /** @var Paginator */
120
    protected $paginator;
121
122
    /** @var \Nette\Localization\ITranslator */
123
    protected $translator;
124
125
    /** @var PropertyAccessor */
126
    protected $propertyAccessor;
127
128
    /** @var bool */
129
    protected $strictMode = TRUE;
130
131
    /** @var array */
132
    protected $options = [
133
        self::CLIENT_SIDE_OPTIONS => []
134
    ];
135
136
    /** @var Customization */
137
    protected $customization;
138
139
    /**
140
     * Grid constructor.
141
     */
142
    public function __construct()
143
    {
144
        list($parent, $name) = func_get_args() + [NULL, NULL];
145
        if ($parent !== NULL) {
146
            $parent->addComponent($this, $name);
147 1
        } elseif (is_string($name)) {
148 1
            $this->name = $name;
149 1
        }
150 1
    }
151 1
152
    /**
153
     * Sets a model that implements the interface Grido\DataSources\IDataSource or data-source object.
154
     * @param mixed $model
155
     * @param bool $forceWrapper
156
     * @throws Exception
157
     * @return Grid
158
     */
159
    public function setModel($model, $forceWrapper = FALSE)
160 1
    {
161 1
        $this->model = $model instanceof DataSources\IDataSource && $forceWrapper === FALSE
162 1
            ? $model
163
            : new DataSources\Model($model);
164 1
165 1
        return $this;
166 1
    }
167 1
168 1
    /**
169 1
     * Sets the default number of items per page.
170
     * @param int $perPage
171
     * @return Grid
172
     */
173
    public function setDefaultPerPage($perPage)
174
    {
175
        $perPage = (int) $perPage;
176
        $this->defaultPerPage = $perPage;
177
178
        if (!in_array($perPage, $this->perPageList)) {
179 1
            $this->perPageList[] = $perPage;
180 1
            sort($this->perPageList);
181
        }
182
183
        return $this;
184
    }
185
186
    /**
187 1
     * Sets default filtering.
188
     * @param array $filter
189
     * @return Grid
190
     */
191 1
    public function setDefaultFilter(array $filter)
192
    {
193 1
        $this->defaultFilter = array_merge($this->defaultFilter, $filter);
194 1
        return $this;
195 1
    }
196 1
197
    /**
198
     * Sets default sorting.
199 1
     * @param array $sort
200 1
     * @return Grid
201
     * @throws Exception
202 1
     */
203 1
    public function setDefaultSort(array $sort)
204
    {
205
        static $replace = ['asc' => Column::ORDER_ASC, 'desc' => Column::ORDER_DESC];
206
207
        foreach ($sort as $column => $dir) {
208 1
            $dir = strtr(strtolower($dir), $replace);
209
            if (!in_array($dir, $replace)) {
210
                throw new Exception("Dir '$dir' for column '$column' is not allowed.");
211
            }
212 1
213
            $this->defaultSort[$column] = $dir;
214 1
        }
215 1
216 1
        return $this;
217
    }
218 1
219
    /**
220 1
     * Sets items to per-page select.
221
     * @param array $perPageList
222
     * @return Grid
223
     */
224
    public function setPerPageList(array $perPageList)
225
    {
226
        $this->perPageList = $perPageList;
227
228 1
        if ($this->hasFilters(FALSE) || $this->hasOperation(FALSE)) {
229 1
            $this['form']['count']->setItems($this->getItemsForCountSelect());
230
        }
231
232
        return $this;
233
    }
234
235
    /**
236 1
     * Sets translator.
237
     * @param \Nette\Localization\ITranslator $translator
238
     * @return Grid
239
     */
240
    public function setTranslator(\Nette\Localization\ITranslator $translator)
241 1
    {
242 1
        $this->translator = $translator;
243 1
        return $this;
244
    }
245
246 1
    /**
247 1
     * Sets type of filter rendering.
248
     * Defaults inner (Filter::RENDER_INNER) if column does not exist then outer filter (Filter::RENDER_OUTER).
249
     * @param string $type
250
     * @throws Exception
251
     * @return Grid
252
     */
253
    public function setFilterRenderType($type)
254
    {
255
        $type = strtolower($type);
256
        if (!in_array($type, [Filter::RENDER_INNER, Filter::RENDER_OUTER])) {
257 1
            throw new Exception('Type must be Filter::RENDER_INNER or Filter::RENDER_OUTER.');
258 1
        }
259
260
        $this->filterRenderType = $type;
261
        return $this;
262
    }
263
264
    /**
265
     * Sets custom paginator.
266
     * @param Paginator $paginator
267
     * @return Grid
268
     */
269 1
    public function setPaginator(Paginator $paginator)
270 1
    {
271
        $this->paginator = $paginator;
272
        return $this;
273
    }
274
275 1
    /**
276
     * Sets grid primary key.
277
     * Defaults is "id".
278
     * @param string $key
279
     * @return Grid
280 1
     */
281 1
    public function setPrimaryKey($key)
282 1
    {
283 1
        $this->primaryKey = $key;
284
        return $this;
285 1
    }
286
287
    /**
288
     * Sets file name of custom template.
289
     * @param string $file
290
     * @return Grid
291
     */
292
    public function setTemplateFile($file)
293
    {
294
        $this->onRender[] = function() use ($file) {
295
            $this->getTemplate()->add('gridoTemplate', $this->getTemplate()->getFile());
296 1
            $this->getTemplate()->setFile($file);
297 1
        };
298 1
299 1
        return $this;
300
    }
301 1
302
    /**
303
     * Sets saving state to session.
304
     * @param bool $state
305
     * @param string $sectionName
306
     * @return Grid
307
     */
308
    public function setRememberState($state = TRUE, $sectionName = NULL)
309
    {
310
        $this->getPresenter(); //component must be attached to presenter
311
        $this->getRememberSession(TRUE); //start session if not
312 1
        $this->rememberState = (bool) $state;
313 1
        $this->rememberStateSectionName = $sectionName;
314
315
        return $this;
316
    }
317
318
    /**
319
     * Sets callback for customizing tr html object.
320
     * Callback returns tr html element; function($row, Html $tr).
321
     * @param $callback
322
     * @return Grid
323 1
     */
324 1
    public function setRowCallback($callback)
325
    {
326
        $this->rowCallback = $callback;
327
        return $this;
328
    }
329
330
    /**
331
     * Sets client-side options.
332
     * @param array $options
333
     * @return Grid
334 1
     */
335 1
    public function setClientSideOptions(array $options)
336
    {
337
        $this->options[self::CLIENT_SIDE_OPTIONS] = $options;
338
        return $this;
339
    }
340
341
    /**
342
     * Determines whether any user error will cause a notice.
343 1
     * @param bool $mode
344 1
     * @return \Grido\Grid
345
     */
346
    public function setStrictMode($mode)
347
    {
348
        $this->strictMode = (bool) $mode;
349
        return $this;
350
    }
351
352
    /**
353
     * @param \Grido\Customization $customization
354 1
     */
355 1
    public function setCustomization(Customization $customization)
356 1
    {
357
        $this->customization = $customization;
358 1
    }
359
360
    /**********************************************************************************************/
361
362
    /**
363
     * Returns total count of data.
364
     * @return int
365
     */
366
    public function getCount()
367 1
    {
368 1
        if ($this->count === NULL) {
369 1
            $this->count = $this->getModel()->getCount();
370
        }
371 1
372
        return $this->count;
373
    }
374
375
    /**
376
     * Returns default per page.
377
     * @return int
378
     */
379
    public function getDefaultPerPage()
380 1
    {
381
        if (!in_array($this->defaultPerPage, $this->perPageList)) {
382
            $this->defaultPerPage = $this->perPageList[0];
383
        }
384
385
        return $this->defaultPerPage;
386
    }
387
388
    /**
389 1
     * Returns default filter.
390
     * @return array
391 1
     */
392
    public function getDefaultFilter()
393
    {
394
        return $this->defaultFilter;
395
    }
396
397
    /**
398 1
     * Returns default sort.
399
     * @return array
400
     */
401
    public function getDefaultSort()
402
    {
403
        return $this->defaultSort;
404
    }
405
406
    /**
407 1
     * Returns list of possible items per page.
408
     * @return array
409
     */
410
    public function getPerPageList()
411
    {
412
        return $this->perPageList;
413
    }
414
415
    /**
416 1
     * Returns primary key.
417
     * @return string
418
     */
419 1
    public function getPrimaryKey()
420
    {
421
        return $this->primaryKey;
422
    }
423
424
    /**
425 1
     * Returns remember state.
426
     * @return bool
427
     */
428
    public function getRememberState()
429
    {
430
        return $this->rememberState;
431
    }
432
433
    /**
434 1
     * Returns row callback.
435 1
     * @return callback
436 1
     */
437
    public function getRowCallback()
438
    {
439
        return $this->rowCallback;
440
    }
441
442
    /**
443
     * Returns items per page.
444
     * @return int
445
     */
446 1
    public function getPerPage()
447 1
    {
448
        return $this->perPage === NULL
449
            ? $this->getDefaultPerPage()
450
            : $this->perPage;
451
    }
452
453
    /**
454
     * Returns actual filter values.
455
     * @param string $key
456
     * @return mixed
457
     */
458
    public function getActualFilter($key = NULL)
459
    {
460 1
        $filter = $this->filter ? $this->filter : $this->defaultFilter;
461 1
        return $key !== NULL && isset($filter[$key]) ? $filter[$key] : $filter;
462
    }
463
464 1
    /**
465 1
     * Returns fetched data.
466 1
     * @param bool $applyPaging
467 1
     * @param bool $useCache
468
     * @param bool $fetch
469 1
     * @throws Exception
470 1
     * @return array|DataSources\IDataSource|\Nette\Database\Table\Selection
471 1
     */
472
    public function getData($applyPaging = TRUE, $useCache = TRUE, $fetch = TRUE)
473 1
    {
474 1
        if ($this->getModel() === NULL) {
475
            throw new Exception('Model cannot be empty, please use method $grid->setModel().');
476
        }
477 1
478
        $data = $this->data;
479 1
        if ($data === NULL || $useCache === FALSE) {
480 1
            $this->applyFiltering();
481 1
            $this->applySorting();
482
483 1
            if ($applyPaging) {
484 1
                $this->applyPaging();
485 1
            }
486 1
487
            if ($fetch === FALSE) {
488 1
                return $this->getModel();
489
            }
490
491 1
            $data = $this->getModel()->getData();
492
493 1
            if ($useCache === TRUE) {
494
                $this->data = $data;
495
            }
496
497
            if ($applyPaging && !empty($data) && !in_array($this->page, range(1, $this->getPaginator()->pageCount))) {
498
                $this->__triggerUserNotice("Page is out of range.");
499
                $this->page = 1;
500
            }
501
502 1
            if (!empty($this->onFetchData)) {
503 1
                $this->onFetchData($this);
504 1
            }
505
        }
506 1
507
        return $data;
508
    }
509
510
    /**
511
     * Returns translator.
512
     * @return Translations\FileTranslator
513
     */
514
    public function getTranslator()
515
    {
516 1
        if ($this->translator === NULL) {
517 1
            $this->setTranslator(new Translations\FileTranslator);
518
        }
519 1
520 1
        return $this->translator;
521 1
    }
522
523 1
    /**
524 1
     * Returns remember session for set expiration, etc.
525 1
     * @param bool $forceStart - if TRUE, session will be started if not
526
     * @return \Nette\Http\SessionSection|NULL
527
     */
528
    public function getRememberSession($forceStart = FALSE)
529
    {
530
        $presenter = $this->getPresenter();
531
        $session = $presenter->getSession();
532
533
        if (!$session->isStarted() && $forceStart) {
534 1
            $session->start();
535 1
        }
536 1
537 1
        return $session->isStarted()
538
            ? ($session->getSection($this->rememberStateSectionName ?: ($presenter->name . ':' . $this->getUniqueId())))
539 1
            : NULL;
540
    }
541
542
    /**
543
     * Returns table html element of grid.
544
     * @return \Nette\Utils\Html
545
     */
546
    public function getTablePrototype()
547
    {
548 1
        if ($this->tablePrototype === NULL) {
549 1
            $this->tablePrototype = \Nette\Utils\Html::el('table');
550
            $this->tablePrototype->id($this->getName());
551
        }
552 1
553 1
        return $this->tablePrototype;
554 1
    }
555
556 1
    /**
557 1
     * @return string
558 1
     * @internal
559 1
     */
560 1
    public function getFilterRenderType()
561
    {
562 1
        if ($this->filterRenderType !== NULL) {
563 1
            return $this->filterRenderType;
564
        }
565 1
566
        $this->filterRenderType = Filter::RENDER_OUTER;
567
        if ($this->hasColumns() && $this->hasFilters() && $this->hasActions()) {
568
            $this->filterRenderType = Filter::RENDER_INNER;
569
570
            $filters = $this[Filter::ID]->getComponents();
571
            foreach ($filters as $filter) {
572
                if (!$this[Column::ID]->getComponent($filter->name, FALSE)) {
573 1
                    $this->filterRenderType = Filter::RENDER_OUTER;
574
                    break;
575
                }
576
            }
577
        }
578
579
        return $this->filterRenderType;
580
    }
581
582 1
    /**
583 1
     * @return DataSources\IDataSource
584 1
     */
585 1
    public function getModel()
586 1
    {
587
        return $this->model;
588 1
    }
589
590
    /**
591
     * @return Paginator
592
     * @internal
593
     */
594
    public function getPaginator()
595
    {
596
        if ($this->paginator === NULL) {
597
            $this->paginator = new Paginator;
598
            $this->paginator->setItemsPerPage($this->getPerPage())
599
                ->setGrid($this);
600 1
        }
601 1
602 1
        return $this->paginator;
603 1
    }
604 1
605 1
    /**
606 1
     * A simple wrapper around symfony/property-access with Nette Database dot notation support.
607
     * @param array|object $object
608 1
     * @param string $name
609
     * @return mixed
610
     * @internal
611 1
     */
612 1
    public function getProperty($object, $name)
613 1
    {
614
        if ($object instanceof \Nette\Database\Table\IRow && \Nette\Utils\Strings::contains($name, '.')) {
0 ignored issues
show
Bug introduced by
The class Nette\Database\Table\IRow does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
615 1
            $parts = explode('.', $name);
616
            foreach ($parts as $item) {
617
                if (is_object($object)) {
618
                    $object = $object->$item;
619
                }
620
            }
621
622
            return $object;
623
        }
624 1
625 1
        if (is_array($object)) {
626 1
            $name = "[$name]";
627
        }
628 1
629
        return $this->getPropertyAccessor()->getValue($object, $name);
630
    }
631
632
    /**
633
     * @return PropertyAccessor
634
     * @internal
635
     */
636
    public function getPropertyAccessor()
637
    {
638
        if ($this->propertyAccessor === NULL) {
639 1
            $this->propertyAccessor = new PropertyAccessor(TRUE, TRUE);
640 1
        }
641 1
642
        return $this->propertyAccessor;
643
    }
644 1
645 1
    /**
646
     * @param mixed $row item from db
647 1
     * @return \Nette\Utils\Html
648 1
     * @internal
649 1
     */
650
    public function getRowPrototype($row)
651 1
    {
652
        try {
653
            $primaryValue = $this->getProperty($row, $this->getPrimaryKey());
654
        } catch (\Exception $e) {
655
            $primaryValue = NULL;
656
        }
657
658
        $tr = \Nette\Utils\Html::el('tr');
659
        $primaryValue ? $tr->class[] = "grid-row-$primaryValue" : NULL;
660 1
661
        if ($this->rowCallback) {
662
            $tr = call_user_func_array($this->rowCallback, [$row, $tr]);
663
        }
664
665
        return $tr;
666
    }
667
668 1
    /**
669
     * Returns client-side options.
670
     * @return array
671
     */
672
    public function getClientSideOptions()
673
    {
674
        return (array) $this->options[self::CLIENT_SIDE_OPTIONS];
675
    }
676 1
677 1
    /**
678 1
     * @return bool
679
     */
680 1
    public function isStrictMode()
681
    {
682
        return $this->strictMode;
683
    }
684
685
    /**
686
     * @return Customization
687
     */
688
    public function getCustomization()
689
    {
690
        if ($this->customization === NULL) {
691
            $this->customization = new Customization($this);
692
        }
693 1
694 1
        return $this->customization;
695 1
    }
696 1
697 1
    /**********************************************************************************************/
698 1
699
    /**
700 1
     * Loads state informations.
701 1
     * @param array $params
702
     * @internal
703
     */
704
    public function loadState(array $params): void
705
    {
706
        //loads state from session
707
        $session = $this->getRememberSession();
708
        if ($session && $this->getPresenter()->isSignalReceiver($this)) {
709
            $session->remove();
710
        } elseif ($session && empty($params) && $session->params) {
711 1
            $params = (array) $session->params;
712 1
        }
713
714
        parent::loadState($params);
715
    }
716
717
    /**
718
     * Saves state informations for next request.
719
     * @param array $params
720
     * @param \Nette\Application\UI\PresenterComponentReflection $reflection (internal, used by Presenter)
721
     * @internal
722
     */
723
    public function saveState(array &$params, $reflection = NULL): void
724
    {
725
        !empty($this->onRegistered) && $this->onRegistered($this);
726
        parent::saveState($params, $reflection);
727
    }
728
729
    /**
730 1
     * Ajax method.
731
     * @internal
732
     */
733
    public function handleRefresh()
734
    {
735
        $this->reload();
736
    }
737
738
    /**
739 1
     * @param int $page
740 1
     * @internal
741
     */
742
    public function handlePage($page)
743
    {
744
        $this->reload();
745
    }
746
747
    /**
748
     * @param array $sort
749 1
     * @internal
750 1
     */
751 1
    public function handleSort(array $sort)
752 1
    {
753 1
        $this->page = 1;
754 1
        $this->reload();
755
    }
756 1
757 1
    /**
758 1
     * @param \Nette\Forms\Controls\SubmitButton $button
759 1
     * @internal
760
     */
761
    public function handleFilter(\Nette\Forms\Controls\SubmitButton $button)
762 1
    {
763
        $values = $button->form->values[Filter::ID];
764 1
        $session = $this->rememberState //session filter
765 1
            ? isset($this->getRememberSession(TRUE)->params['filter'])
766
                ? $this->getRememberSession(TRUE)->params['filter']
767
                : []
768
            : [];
769
770
        foreach ($values as $name => $value) {
771
            if (is_numeric($value) || !empty($value) || isset($this->defaultFilter[$name]) || isset($session[$name])) {
772
                $this->filter[$name] = $this->getFilter($name)->changeValue($value);
773
            } elseif (isset($this->filter[$name])) {
774 1
                unset($this->filter[$name]);
775 1
            }
776 1
        }
777
778 1
        $this->page = 1;
779 1
        $this->reload();
780 1
    }
781
782 1
    /**
783
     * @param \Nette\Forms\Controls\SubmitButton $button
784 1
     * @internal
785 1
     */
786
    public function handleReset(\Nette\Forms\Controls\SubmitButton $button)
787
    {
788
        $this->sort = [];
789
        $this->filter = [];
790
        $this->perPage = NULL;
791
792
        if ($session = $this->getRememberSession()) {
793
            $session->remove();
794 1
        }
795 1
796 1
        $button->form->setValues([Filter::ID => $this->defaultFilter], TRUE);
797
798
        $this->page = 1;
799 1
        $this->reload();
800 1
    }
801
802
    /**
803
     * @param \Nette\Forms\Controls\SubmitButton $button
804
     * @internal
805
     */
806
    public function handlePerPage(\Nette\Forms\Controls\SubmitButton $button)
807
    {
808
        $perPage = (int) $button->form['count']->value;
809
        $this->perPage = $perPage == $this->defaultPerPage
810 1
            ? NULL
811
            : $perPage;
812
813
        $this->page = 1;
814 1
        $this->reload();
815
    }
816
817
    /**
818
     * Refresh wrapper.
819
     * @return void
820
     * @internal
821
     */
822
    public function reload()
823
    {
824
        if ($this->presenter->isAjax()) {
825
            $this->presenter->payload->grido = TRUE;
826 1
            $this->redrawControl();
827 1
        } else {
828 1
            $this->redirect('this');
829
        }
830 1
    }
831
832
    /**********************************************************************************************/
833
834
    /**
835
     * @internal
836
     */
837
    public function createTemplate(): \Nette\Application\UI\ITemplate
838
    {
839 1
        $template = parent::createTemplate();
840
        $template->setFile($this->getCustomization()->getTemplateFiles()[Customization::TEMPLATE_DEFAULT]);
841
        $template->getLatte()->addFilter('translate', [$this->getTranslator(), 'translate']);
842
843 1
        return $template;
844 1
    }
845
846 1
    /**
847 1
     * @internal
848 1
     * @throws Exception
849
     */
850 1
    public function render()
851
    {
852 1
        if (!$this->hasColumns()) {
853 1
            throw new Exception('Grid must have defined a column, please use method $grid->addColumn*().');
854 1
        }
855 1
856 1
        $this->saveRememberState();
857 1
        $data = $this->getData();
858 1
859 1
        if (!empty($this->onRender)) {
860 1
            $this->onRender($this);
861
        }
862 1
863 1
        $form = $this['form'];
864 1
865 1
        $this->getTemplate()->add('data', $data);
866
        $this->getTemplate()->add('form', $form);
867 1
        $this->getTemplate()->add('paginator', $this->getPaginator());
868 1
        $this->getTemplate()->add('customization', $this->getCustomization());
869 1
        $this->getTemplate()->add('columns', $this->getComponent(Column::ID)->getComponents());
870 1
        $this->getTemplate()->add('actions', $this->hasActions()
871
            ? $this->getComponent(Action::ID)->getComponents()
872 1
            : []
873
        );
874 1
875 1
        $this->getTemplate()->add('buttons', $this->hasButtons()
876 1
            ? $this->getComponent(Button::ID)->getComponents()
877
            : []
878 1
        );
879 1
880
        $this->getTemplate()->add('formFilters', $this->hasFilters()
881
            ? $form->getComponent(Filter::ID)->getComponents()
882
            : []
883 1
        );
884 1
885 1
        $form['count']->setValue($this->getPerPage());
886 1
887 1
        if ($options = $this->options[self::CLIENT_SIDE_OPTIONS]) {
888 1
            $this->getTablePrototype()->setAttribute('data-' . self::CLIENT_SIDE_OPTIONS, json_encode($options));
889 1
        }
890 1
891
        $this->getTemplate()->render();
892
    }
893
894 1
    protected function saveRememberState()
895 1
    {
896 1
        if ($this->rememberState) {
897
            $session = $this->getRememberSession(TRUE);
898
            $params = array_keys($this->getReflection()->getPersistentParams());
899
            foreach ($params as $param) {
900
                $session->params[$param] = $this->$param;
901
            }
902
        }
903
    }
904
905 1
    protected function applyFiltering()
906 1
    {
907
        $conditions = $this->__getConditions($this->getActualFilter());
908 1
        $this->getModel()->filter($conditions);
909 1
    }
910
911
    /**
912
     * @param array $filter
913
     * @return array
914
     * @internal
915
     */
916
    public function __getConditions(array $filter)
917 1
    {
918 1
        $conditions = [];
919 1
        if (!empty($filter)) {
920 1
            try {
921 1
                $this['form']->setDefaults([Filter::ID => $filter]);
922 1
            } catch (\Nette\InvalidArgumentException $e) {
0 ignored issues
show
Bug introduced by
The class Nette\InvalidArgumentException does not exist. Did you forget a USE statement, or did you not list all dependencies?

Scrutinizer analyzes your composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis.

Loading history...
923 1
                $this->__triggerUserNotice($e->getMessage());
924
                $filter = [];
925 1
                if ($session = $this->getRememberSession()) {
926 1
                    $session->remove();
927
                }
928 1
            }
929
930
            foreach ($filter as $column => $value) {
931
                if ($component = $this->getFilter($column, FALSE)) {
932
                    if ($condition = $component->__getCondition($value)) {
933 1
                        $conditions[] = $condition;
934 1
                    }
935
                } else {
936 1
                    $this->__triggerUserNotice("Filter with name '$column' does not exist.");
937 1
                }
938 1
            }
939 1
        }
940 1
941 1
        return $conditions;
942
    }
943
944 1
    protected function applySorting()
945 1
    {
946 1
        $sort = [];
947 1
        $this->sort = $this->sort ? $this->sort : $this->defaultSort;
948 1
949 1
        foreach ($this->sort as $column => $dir) {
950
            $component = $this->getColumn($column, FALSE);
951 1
            if (!$component) {
952
                if (!isset($this->defaultSort[$column])) {
953 1
                    $this->__triggerUserNotice("Column with name '$column' does not exist.");
954 1
                    break;
955
                }
956
957
            } elseif (!$component->isSortable()) {
958
                if (isset($this->defaultSort[$column])) {
959 1
                    $component->setSortable();
960 1
                } else {
961
                    $this->__triggerUserNotice("Column with name '$column' is not sortable.");
962
                    break;
963 1
                }
964 1
            }
965
966 1
            if (!in_array($dir, [Column::ORDER_ASC, Column::ORDER_DESC])) {
967 1
                if ($dir == '' && isset($this->defaultSort[$column])) {
968 1
                    unset($this->sort[$column]);
969 1
                    break;
970
                }
971
972
                $this->__triggerUserNotice("Dir '$dir' is not allowed.");
973 1
                break;
974 1
            }
975 1
976
            $sort[$component ? $component->column : $column] = $dir == Column::ORDER_ASC ? 'ASC' : 'DESC';
977 1
        }
978 1
979 1
        if (!empty($sort)) {
980 1
            $this->getModel()->sort($sort);
981
        }
982 1
    }
983 1
984
    protected function applyPaging()
985
    {
986
        $paginator = $this->getPaginator()
987 1
            ->setItemCount($this->getCount())
988 1
            ->setPage($this->page);
989 1
990
        $perPage = $this->getPerPage();
991 1
        if ($perPage !== NULL && !in_array($perPage, $this->perPageList)) {
992 1
            $this->__triggerUserNotice("The number '$perPage' of items per page is out of range.");
993 1
        }
994 1
995 1
        $this->getModel()->limit($paginator->getOffset(), $paginator->getLength());
996 1
    }
997 1
998
    protected function createComponentForm($name)
999 1
    {
1000 1
        $form = new \Nette\Application\UI\Form($this, $name);
1001 1
        $form->setTranslator($this->getTranslator());
1002 1
        $form->setMethod($form::GET);
1003
1004
        $buttons = $form->addContainer(self::BUTTONS);
1005
        $buttons->addSubmit('search', 'Grido.Search')
1006
            ->onClick[] = [$this, 'handleFilter'];
1007
        $buttons->addSubmit('reset', 'Grido.Reset')
1008
            ->onClick[] = [$this, 'handleReset'];
1009 1
        $buttons->addSubmit('perPage', 'Grido.ItemsPerPage')
1010
            ->onClick[] = [$this, 'handlePerPage'];
1011
1012
        $form->addSelect('count', 'Count', $this->getItemsForCountSelect())
1013
            ->setTranslator(NULL)
1014
            ->controlPrototype->attrs['title'] = $this->getTranslator()->translate('Grido.ItemsPerPage');
1015
    }
1016
1017
    /**
1018 1
     * @return array
1019 1
     */
1020 1
    protected function getItemsForCountSelect()
1021
    {
1022 1
        return array_combine($this->perPageList, $this->perPageList);
1023 1
    }
1024
1025 1
    /**
1026
     * @internal
1027
     * @param string $message
1028
     */
1029
    public function __triggerUserNotice($message)
1030
    {
1031
        if ($this->lookup(Presenter::class, FALSE) && $session = $this->getRememberSession()) {
1032
            $session->remove();
1033
        }
1034
1035
        $this->strictMode && trigger_error($message, E_USER_NOTICE);
1036
    }
1037
}
1038