Completed
Pull Request — master (#299)
by
unknown
02:02
created

Grid::getItemsForCountSelect()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 1
cts 1
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
/**
4
 * This file is part of the Grido (http://grido.bugyik.cz)
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 Symfony\Component\PropertyAccess\PropertyAccessor;
22
23
/**
24
 * Grido - DataGrid for Nette Framework.
25
 *
26
 * @package     Grido
27
 * @author      Petr Bugyík
28
 *
29
 * @property-read int $count
30
 * @property-read mixed $data
31
 * @property-read \Nette\Utils\Html $tablePrototype
32
 * @property-read PropertyAccessor $propertyAccessor
33
 * @property-read Customization $customization
34
 * @property-write string $templateFile
35
 * @property bool $rememberState
36
 * @property array $defaultPerPage
37
 * @property array $defaultFilter
38
 * @property array $defaultSort
39
 * @property array $perPageList
40
 * @property \Nette\Localization\ITranslator $translator
41
 * @property Paginator $paginator
42
 * @property string $primaryKey
43
 * @property string $filterRenderType
44
 * @property DataSources\IDataSource $model
45
 * @property callback $rowCallback
46
 * @property bool $strictMode
47
 * @method void onRegistered(Grid $grid)
48
 * @method void onRender(Grid $grid)
49
 * @method void onFetchData(Grid $grid)
50
 */
51
class Grid extends Components\Container
52 1
{
53
    /***** DEFAULTS ****/
54
    const BUTTONS = 'buttons';
55
56
    const CLIENT_SIDE_OPTIONS = 'grido-options';
57
58
    /** @var int @persistent */
59
    public $page = 1;
60
61
    /** @var int @persistent */
62
    public $perPage;
63
64
    /** @var array @persistent */
65
    public $sort = [];
66
67
    /** @var array @persistent */
68
    public $filter = [];
69
70
    /** @var array event on all grid's components registered */
71
    public $onRegistered;
72
73
    /** @var array event on render */
74
    public $onRender;
75
76
    /** @var array event for modifying data */
77
    public $onFetchData;
78
79
    /** @var callback returns tr html element; function($row, Html $tr) */
80
    protected $rowCallback;
81
82
    /** @var \Nette\Utils\Html */
83
    protected $tablePrototype;
84
85
    /** @var bool */
86
    protected $rememberState = FALSE;
87
88
    /** @var string */
89
    protected $rememberStateSectionName;
90
91
    /** @var string */
92
    protected $primaryKey = 'id';
93
94
    /** @var string */
95
    protected $filterRenderType;
96
97
    /** @var array */
98
    protected $perPageList = [10, 20, 30, 50, 100];
99
100
    /** @var int */
101
    protected $defaultPerPage = 20;
102
103
    /** @var array */
104
    protected $defaultFilter = [];
105
106
    /** @var array */
107
    protected $defaultSort = [];
108
109
    /** @var DataSources\IDataSource */
110
    protected $model;
111
112
    /** @var int total count of items */
113
    protected $count;
114
115
    /** @var mixed */
116
    protected $data;
117
118
    /** @var Paginator */
119
    protected $paginator;
120
121
    /** @var \Nette\Localization\ITranslator */
122
    protected $translator;
123
124
    /** @var PropertyAccessor */
125
    protected $propertyAccessor;
126
127
    /** @var bool */
128
    protected $strictMode = TRUE;
129
130
    /** @var array */
131
    protected $options = [
132
        self::CLIENT_SIDE_OPTIONS => []
133
    ];
134
135
    /** @var Customization */
136
    protected $customization;
137
138
    /**
139
     * Grid constructor.
140
     */
141
    public function __construct()
142
    {
143 1
        parent::__construct();
144 1
        list($parent, $name) = func_get_args() + [null, null];
145 1
        if ($parent !== null) {
146
            $parent->addComponent($this, $name);
147
148 1
        } elseif (is_string($name)) {
149
            $this->name = $name;
150
        }
151 1
    }
152
153
154
    /**
155
     * Sets a model that implements the interface Grido\DataSources\IDataSource or data-source object.
156
     * @param mixed $model
157
     * @param bool $forceWrapper
158
     * @throws Exception
159
     * @return Grid
160
     */
161
    public function setModel($model, $forceWrapper = FALSE)
162
    {
163
        $this->model = $model instanceof DataSources\IDataSource && $forceWrapper === FALSE
164
            ? $model
165
            : new DataSources\Model($model);
166
167
        return $this;
168
    }
169
170
    /**
171
     * Sets the default number of items per page.
172
     * @param int $perPage
173
     * @return Grid
174
     */
175
    public function setDefaultPerPage($perPage)
176
    {
177
        $perPage = (int) $perPage;
178
        $this->defaultPerPage = $perPage;
179
180
        if (!in_array($perPage, $this->perPageList)) {
181
            $this->perPageList[] = $perPage;
182
            sort($this->perPageList);
183
        }
184
185
        return $this;
186
    }
187
188
    /**
189
     * Sets default filtering.
190
     * @param array $filter
191
     * @return Grid
192
     */
193
    public function setDefaultFilter(array $filter)
194
    {
195 1
        $this->defaultFilter = array_merge($this->defaultFilter, $filter);
196 1
        return $this;
197
    }
198
199
    /**
200
     * Sets default sorting.
201
     * @param array $sort
202
     * @return Grid
203
     * @throws Exception
204
     */
205
    public function setDefaultSort(array $sort)
206
    {
207 1
        static $replace = ['asc' => Column::ORDER_ASC, 'desc' => Column::ORDER_DESC];
208
209 1
        foreach ($sort as $column => $dir) {
210 1
            $dir = strtr(strtolower($dir), $replace);
211 1
            if (!in_array($dir, $replace)) {
212
                throw new Exception("Dir '$dir' for column '$column' is not allowed.");
213
            }
214
215 1
            $this->defaultSort[$column] = $dir;
216 1
        }
217
218 1
        return $this;
219
    }
220
221
    /**
222
     * Sets items to per-page select.
223
     * @param array $perPageList
224
     * @return Grid
225
     */
226
    public function setPerPageList(array $perPageList)
227
    {
228
        $this->perPageList = $perPageList;
229
230
        if ($this->hasFilters(FALSE) || $this->hasOperation(FALSE)) {
231
            $this['form']['count']->setItems($this->getItemsForCountSelect());
232
        }
233
234
        return $this;
235
    }
236
237
    /**
238
     * Sets translator.
239
     * @param \Nette\Localization\ITranslator $translator
240
     * @return Grid
241
     */
242
    public function setTranslator(\Nette\Localization\ITranslator $translator)
243
    {
244 1
        $this->translator = $translator;
245 1
        return $this;
246
    }
247
248
    /**
249
     * Sets type of filter rendering.
250
     * Defaults inner (Filter::RENDER_INNER) if column does not exist then outer filter (Filter::RENDER_OUTER).
251
     * @param string $type
252
     * @throws Exception
253
     * @return Grid
254
     */
255
    public function setFilterRenderType($type)
256
    {
257
        $type = strtolower($type);
258
        if (!in_array($type, [Filter::RENDER_INNER, Filter::RENDER_OUTER])) {
259
            throw new Exception('Type must be Filter::RENDER_INNER or Filter::RENDER_OUTER.');
260
        }
261
262
        $this->filterRenderType = $type;
263
        return $this;
264
    }
265
266
    /**
267
     * Sets custom paginator.
268
     * @param Paginator $paginator
269
     * @return Grid
270
     */
271
    public function setPaginator(Paginator $paginator)
272
    {
273
        $this->paginator = $paginator;
274
        return $this;
275
    }
276
277
    /**
278
     * Sets grid primary key.
279
     * Defaults is "id".
280
     * @param string $key
281
     * @return Grid
282
     */
283
    public function setPrimaryKey($key)
284
    {
285
        $this->primaryKey = $key;
286
        return $this;
287
    }
288
289
    /**
290
     * Sets file name of custom template.
291
     * @param string $file
292
     * @return Grid
293
     */
294
    public function setTemplateFile($file)
295
    {
296
        $this->onRender[] = function() use ($file) {
297
            $this->getTemplate()->add('gridoTemplate', $this->getTemplate()->getFile());
298
            $this->getTemplate()->setFile($file);
299
        };
300
301
        return $this;
302
    }
303
304
    /**
305
     * Sets saving state to session.
306
     * @param bool $state
307
     * @param string $sectionName
308
     * @return Grid
309
     */
310
    public function setRememberState($state = TRUE, $sectionName = NULL)
311
    {
312
        $this->getPresenter(); //component must be attached to presenter
313
        $this->getRememberSession(TRUE); //start session if not
314
        $this->rememberState = (bool) $state;
315
        $this->rememberStateSectionName = $sectionName;
316
317
        return $this;
318
    }
319
320
    /**
321
     * Sets callback for customizing tr html object.
322
     * Callback returns tr html element; function($row, Html $tr).
323
     * @param $callback
324
     * @return Grid
325
     */
326
    public function setRowCallback($callback)
327
    {
328
        $this->rowCallback = $callback;
329
        return $this;
330
    }
331
332
    /**
333
     * Sets client-side options.
334
     * @param array $options
335
     * @return Grid
336
     */
337
    public function setClientSideOptions(array $options)
338
    {
339
        $this->options[self::CLIENT_SIDE_OPTIONS] = $options;
340
        return $this;
341
    }
342
343
    /**
344
     * Determines whether any user error will cause a notice.
345
     * @param bool $mode
346
     * @return \Grido\Grid
347
     */
348
    public function setStrictMode($mode)
349
    {
350
        $this->strictMode = (bool) $mode;
351
        return $this;
352
    }
353
354
    /**
355
     * @param \Grido\Customization $customization
356
     */
357
    public function setCustomization(Customization $customization)
358
    {
359
        $this->customization = $customization;
360
    }
361
362
    /**********************************************************************************************/
363
364
    /**
365
     * Returns total count of data.
366
     * @return int
367
     */
368
    public function getCount()
369
    {
370
        if ($this->count === NULL) {
371
            $this->count = $this->getModel()->getCount();
372
        }
373
374
        return $this->count;
375
    }
376
377
    /**
378
     * Returns default per page.
379
     * @return int
380
     */
381
    public function getDefaultPerPage()
382
    {
383
        if (!in_array($this->defaultPerPage, $this->perPageList)) {
384
            $this->defaultPerPage = $this->perPageList[0];
385
        }
386
387
        return $this->defaultPerPage;
388
    }
389
390
    /**
391
     * Returns default filter.
392 1
     * @return array
393
     */
394
    public function getDefaultFilter()
395
    {
396 1
        return $this->defaultFilter;
397
    }
398
399
    /**
400
     * Returns default sort.
401
     * @return array
402
     */
403
    public function getDefaultSort()
404
    {
405 1
        return $this->defaultSort;
406
    }
407
408
    /**
409
     * Returns list of possible items per page.
410
     * @return array
411
     */
412
    public function getPerPageList()
413
    {
414
        return $this->perPageList;
415
    }
416
417
    /**
418
     * Returns primary key.
419
     * @return string
420 1
     */
421
    public function getPrimaryKey()
422
    {
423
        return $this->primaryKey;
424
    }
425
426
    /**
427
     * Returns remember state.
428
     * @return bool
429
     */
430
    public function getRememberState()
431
    {
432
        return $this->rememberState;
433
    }
434
435
    /**
436
     * Returns row callback.
437
     * @return callback
438
     */
439
    public function getRowCallback()
440
    {
441
        return $this->rowCallback;
442
    }
443
444
    /**
445
     * Returns items per page.
446
     * @return int
447
     */
448
    public function getPerPage()
449
    {
450
        return $this->perPage === NULL
451
            ? $this->getDefaultPerPage()
452
            : $this->perPage;
453
    }
454
455
    /**
456
     * Returns actual filter values.
457
     * @param string $key
458
     * @return mixed
459
     */
460
    public function getActualFilter($key = NULL)
461 1
    {
462
        $filter = $this->filter ? $this->filter : $this->defaultFilter;
463
        return $key !== NULL && isset($filter[$key]) ? $filter[$key] : $filter;
464
    }
465
466
    /**
467
     * Returns fetched data.
468
     * @param bool $applyPaging
469
     * @param bool $useCache
470
     * @param bool $fetch
471
     * @throws Exception
472
     * @return array|DataSources\IDataSource|\Nette\Database\Table\Selection
473
     */
474
    public function getData($applyPaging = TRUE, $useCache = TRUE, $fetch = TRUE)
475
    {
476
        if ($this->getModel() === NULL) {
477
            throw new Exception('Model cannot be empty, please use method $grid->setModel().');
478
        }
479
480
        $data = $this->data;
481
        if ($data === NULL || $useCache === FALSE) {
482
            $this->applyFiltering();
483
            $this->applySorting();
484
485
            if ($applyPaging) {
486
                $this->applyPaging();
487
            }
488
489
            if ($fetch === FALSE) {
490
                return $this->getModel();
491
            }
492
493
            $data = $this->getModel()->getData();
494
495
            if ($useCache === TRUE) {
496
                $this->data = $data;
497
            }
498
499
            if ($applyPaging && !empty($data) && !in_array($this->page, range(1, $this->getPaginator()->pageCount))) {
500
                $this->__triggerUserNotice("Page is out of range.");
501
                $this->page = 1;
502
            }
503
504
            if (!empty($this->onFetchData)) {
505
                $this->onFetchData($this);
506
            }
507
        }
508
509
        return $data;
510
    }
511
512
    /**
513
     * Returns translator.
514
     * @return Translations\FileTranslator
515
     */
516
    public function getTranslator()
517
    {
518 1
        if ($this->translator === NULL) {
519 1
            $this->setTranslator(new Translations\FileTranslator);
520 1
        }
521
522 1
        return $this->translator;
523
    }
524
525
    /**
526
     * Returns remember session for set expiration, etc.
527
     * @param bool $forceStart - if TRUE, session will be started if not
528
     * @return \Nette\Http\SessionSection|NULL
529
     */
530
    public function getRememberSession($forceStart = FALSE)
531
    {
532
        $presenter = $this->getPresenter();
533
        $session = $presenter->getSession();
534
535
        if (!$session->isStarted() && $forceStart) {
536
            $session->start();
537
        }
538
539
        return $session->isStarted()
540
            ? ($session->getSection($this->rememberStateSectionName ?: ($presenter->name . ':' . $this->getUniqueId())))
541
            : NULL;
542
    }
543
544
    /**
545
     * Returns table html element of grid.
546
     * @return \Nette\Utils\Html
547
     */
548
    public function getTablePrototype()
549
    {
550
        if ($this->tablePrototype === NULL) {
551
            $this->tablePrototype = \Nette\Utils\Html::el('table');
552
            $this->tablePrototype->id($this->getName());
553
        }
554
555
        return $this->tablePrototype;
556
    }
557
558
    /**
559
     * @return string
560
     * @internal
561
     */
562
    public function getFilterRenderType()
563
    {
564
        if ($this->filterRenderType !== NULL) {
565
            return $this->filterRenderType;
566
        }
567
568
        $this->filterRenderType = Filter::RENDER_OUTER;
569
        if ($this->hasColumns() && $this->hasFilters() && $this->hasActions()) {
570
            $this->filterRenderType = Filter::RENDER_INNER;
571
572
            $filters = $this[Filter::ID]->getComponents();
573
            foreach ($filters as $filter) {
574
                if (!$this[Column::ID]->getComponent($filter->name, FALSE)) {
575
                    $this->filterRenderType = Filter::RENDER_OUTER;
576
                    break;
577
                }
578
            }
579
        }
580
581
        return $this->filterRenderType;
582
    }
583
584
    /**
585
     * @return DataSources\IDataSource
586
     */
587
    public function getModel()
588
    {
589
        return $this->model;
590
    }
591
592
    /**
593
     * @return Paginator
594
     * @internal
595
     */
596
    public function getPaginator()
597
    {
598
        if ($this->paginator === NULL) {
599
            $this->paginator = new Paginator;
600
            $this->paginator->setItemsPerPage($this->getPerPage())
601
                ->setGrid($this);
602
        }
603
604
        return $this->paginator;
605
    }
606
607
    /**
608
     * A simple wrapper around symfony/property-access with Nette Database dot notation support.
609
     * @param array|object $object
610
     * @param string $name
611
     * @return mixed
612
     * @internal
613
     */
614
    public function getProperty($object, $name)
615
    {
616 1
        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...
617
            $parts = explode('.', $name);
618
            foreach ($parts as $item) {
619
                if (is_object($object)) {
620
                    $object = $object->$item;
621
                }
622
            }
623
624
            return $object;
625
        }
626
627 1
        if (is_array($object)) {
628 1
            $name = "[$name]";
629 1
        }
630
631 1
        return $this->getPropertyAccessor()->getValue($object, $name);
632
    }
633
634
    /**
635
     * @return PropertyAccessor
636
     * @internal
637
     */
638
    public function getPropertyAccessor()
639
    {
640 1
        if ($this->propertyAccessor === NULL) {
641 1
            $this->propertyAccessor = new PropertyAccessor(TRUE, TRUE);
642 1
        }
643
644 1
        return $this->propertyAccessor;
645
    }
646
647
    /**
648
     * @param mixed $row item from db
649
     * @return \Nette\Utils\Html
650
     * @internal
651
     */
652
    public function getRowPrototype($row)
653
    {
654
        try {
655
            $primaryValue = $this->getProperty($row, $this->getPrimaryKey());
656
        } catch (\Exception $e) {
657
            $primaryValue = NULL;
658
        }
659
660
        $tr = \Nette\Utils\Html::el('tr');
661
        $primaryValue ? $tr->class[] = "grid-row-$primaryValue" : NULL;
662
663
        if ($this->rowCallback) {
664
            $tr = call_user_func_array($this->rowCallback, [$row, $tr]);
665
        }
666
667
        return $tr;
668
    }
669
670
    /**
671
     * Returns client-side options.
672
     * @return array
673
     */
674
    public function getClientSideOptions()
675
    {
676
        return (array) $this->options[self::CLIENT_SIDE_OPTIONS];
677
    }
678
679
    /**
680
     * @return bool
681
     */
682
    public function isStrictMode()
683
    {
684
        return $this->strictMode;
685
    }
686
687
    /**
688
     * @return Customization
689
     */
690
    public function getCustomization()
691
    {
692
        if ($this->customization === NULL) {
693
            $this->customization = new Customization($this);
694
        }
695
696
        return $this->customization;
697
    }
698
699
    /**********************************************************************************************/
700
701
    /**
702
     * Loads state informations.
703
     * @param array $params
704
     * @internal
705
     */
706
    public function loadState(array $params)
707
    {
708
        //loads state from session
709
        $session = $this->getRememberSession();
710
        if ($session && $this->getPresenter()->isSignalReceiver($this)) {
711
            $session->remove();
712
        } elseif ($session && empty($params) && $session->params) {
713
            $params = (array) $session->params;
714
        }
715
716
        parent::loadState($params);
717
    }
718
719
    /**
720
     * Saves state informations for next request.
721
     * @param array $params
722
     * @param \Nette\Application\UI\PresenterComponentReflection $reflection (internal, used by Presenter)
723
     * @internal
724
     */
725
    public function saveState(array &$params, $reflection = NULL)
726
    {
727
        !empty($this->onRegistered) && $this->onRegistered($this);
728
        return parent::saveState($params, $reflection);
729
    }
730
731
    /**
732
     * Ajax method.
733
     * @internal
734
     */
735
    public function handleRefresh()
736
    {
737
        $this->reload();
738
    }
739
740
    /**
741
     * @param int $page
742
     * @internal
743
     */
744
    public function handlePage($page)
745
    {
746
        $this->reload();
747
    }
748
749
    /**
750
     * @param array $sort
751
     * @internal
752
     */
753
    public function handleSort(array $sort)
754
    {
755
        $this->page = 1;
756
        $this->reload();
757
    }
758
759
    /**
760
     * @param \Nette\Forms\Controls\SubmitButton $button
761
     * @internal
762
     */
763
    public function handleFilter(\Nette\Forms\Controls\SubmitButton $button)
764
    {
765
        $values = $button->form->values[Filter::ID];
766
        $session = $this->rememberState //session filter
767
            ? isset($this->getRememberSession(TRUE)->params['filter'])
768
                ? $this->getRememberSession(TRUE)->params['filter']
769
                : []
770
            : [];
771
772
        foreach ($values as $name => $value) {
773
            if (is_numeric($value) || !empty($value) || isset($this->defaultFilter[$name]) || isset($session[$name])) {
774
                $this->filter[$name] = $this->getFilter($name)->changeValue($value);
775
            } elseif (isset($this->filter[$name])) {
776
                unset($this->filter[$name]);
777
            }
778
        }
779
780
        $this->page = 1;
781
        $this->reload();
782
    }
783
784
    /**
785
     * @param \Nette\Forms\Controls\SubmitButton $button
786
     * @internal
787
     */
788
    public function handleReset(\Nette\Forms\Controls\SubmitButton $button)
789
    {
790
        $this->sort = [];
791
        $this->filter = [];
792
        $this->perPage = NULL;
793
794
        if ($session = $this->getRememberSession()) {
795
            $session->remove();
796
        }
797
798
        $button->form->setValues([Filter::ID => $this->defaultFilter], TRUE);
799
800
        $this->page = 1;
801
        $this->reload();
802
    }
803
804
    /**
805
     * @param \Nette\Forms\Controls\SubmitButton $button
806
     * @internal
807
     */
808
    public function handlePerPage(\Nette\Forms\Controls\SubmitButton $button)
809
    {
810
        $perPage = (int) $button->form['count']->value;
811
        $this->perPage = $perPage == $this->defaultPerPage
812
            ? NULL
813
            : $perPage;
814
815
        $this->page = 1;
816
        $this->reload();
817
    }
818
819
    /**
820
     * Refresh wrapper.
821
     * @return void
822
     * @internal
823
     */
824
    public function reload()
825
    {
826
        if ($this->presenter->isAjax()) {
827
            $this->presenter->payload->grido = TRUE;
828
            $this->redrawControl();
829
        } else {
830
            $this->redirect('this');
831
        }
832
    }
833
834
    /**********************************************************************************************/
835
836
    /**
837
     * @return \Nette\Templating\FileTemplate
838
     * @internal
839
     */
840
    public function createTemplate()
841
    {
842
        $template = parent::createTemplate();
843
        $template->setFile($this->getCustomization()->getTemplateFiles()[Customization::TEMPLATE_DEFAULT]);
844
        $template->getLatte()->addFilter('translate', [$this->getTranslator(), 'translate']);
845
846
        return $template;
847
    }
848
849
    /**
850
     * @internal
851
     * @throws Exception
852
     */
853
    public function render()
854
    {
855
        if (!$this->hasColumns()) {
856
            throw new Exception('Grid must have defined a column, please use method $grid->addColumn*().');
857
        }
858
859
        $this->saveRememberState();
860
        $data = $this->getData();
861
862
        if (!empty($this->onRender)) {
863
            $this->onRender($this);
864
        }
865
866
        $form = $this['form'];
867
868
        $this->getTemplate()->add('data', $data);
869
        $this->getTemplate()->add('form', $form);
870
        $this->getTemplate()->add('paginator', $this->getPaginator());
871
        $this->getTemplate()->add('customization', $this->getCustomization());
872
        $this->getTemplate()->add('columns', $this->getComponent(Column::ID)->getComponents());
873
        $this->getTemplate()->add('actions', $this->hasActions()
874
            ? $this->getComponent(Action::ID)->getComponents()
875
            : []
876
        );
877
878
        $this->getTemplate()->add('buttons', $this->hasButtons()
879
            ? $this->getComponent(Button::ID)->getComponents()
880
            : []
881
        );
882
883
        $this->getTemplate()->add('formFilters', $this->hasFilters()
884
            ? $form->getComponent(Filter::ID)->getComponents()
885
            : []
886
        );
887
888
        $form['count']->setValue($this->getPerPage());
889
890
        if ($options = $this->options[self::CLIENT_SIDE_OPTIONS]) {
891
            $this->getTablePrototype()->setAttribute('data-' . self::CLIENT_SIDE_OPTIONS, json_encode($options));
892
        }
893
894
        $this->getTemplate()->render();
895
    }
896
897
    protected function saveRememberState()
898
    {
899
        if ($this->rememberState) {
900
            $session = $this->getRememberSession(TRUE);
901
            $params = array_keys($this->getReflection()->getPersistentParams());
902
            foreach ($params as $param) {
903
                $session->params[$param] = $this->$param;
904
            }
905
        }
906
    }
907
908
    protected function applyFiltering()
909
    {
910
        $conditions = $this->__getConditions($this->getActualFilter());
911
        $this->getModel()->filter($conditions);
912
    }
913
914
    /**
915
     * @param array $filter
916
     * @return array
917
     * @internal
918
     */
919
    public function __getConditions(array $filter)
920
    {
921
        $conditions = [];
922
        if (!empty($filter)) {
923
            try {
924
                $this['form']->setDefaults([Filter::ID => $filter]);
925
            } 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...
926
                $this->__triggerUserNotice($e->getMessage());
927
                $filter = [];
928
                if ($session = $this->getRememberSession()) {
929
                    $session->remove();
930
                }
931
            }
932
933
            foreach ($filter as $column => $value) {
934
                if ($component = $this->getFilter($column, FALSE)) {
935
                    if ($condition = $component->__getCondition($value)) {
936
                        $conditions[] = $condition;
937
                    }
938
                } else {
939
                    $this->__triggerUserNotice("Filter with name '$column' does not exist.");
940
                }
941
            }
942
        }
943
944
        return $conditions;
945
    }
946
947
    protected function applySorting()
948
    {
949
        $sort = [];
950
        $this->sort = $this->sort ? $this->sort : $this->defaultSort;
951
952
        foreach ($this->sort as $column => $dir) {
953
            $component = $this->getColumn($column, FALSE);
954
            if (!$component) {
955
                if (!isset($this->defaultSort[$column])) {
956
                    $this->__triggerUserNotice("Column with name '$column' does not exist.");
957
                    break;
958
                }
959
960
            } elseif (!$component->isSortable()) {
961
                if (isset($this->defaultSort[$column])) {
962
                    $component->setSortable();
963
                } else {
964
                    $this->__triggerUserNotice("Column with name '$column' is not sortable.");
965
                    break;
966
                }
967
            }
968
969
            if (!in_array($dir, [Column::ORDER_ASC, Column::ORDER_DESC])) {
970
                if ($dir == '' && isset($this->defaultSort[$column])) {
971
                    unset($this->sort[$column]);
972
                    break;
973
                }
974
975
                $this->__triggerUserNotice("Dir '$dir' is not allowed.");
976
                break;
977
            }
978
979
            $sort[$component ? $component->column : $column] = $dir == Column::ORDER_ASC ? 'ASC' : 'DESC';
980
        }
981
982
        if (!empty($sort)) {
983
            $this->getModel()->sort($sort);
984
        }
985
    }
986
987
    protected function applyPaging()
988
    {
989
        $paginator = $this->getPaginator()
990
            ->setItemCount($this->getCount())
991
            ->setPage($this->page);
992
993
        $perPage = $this->getPerPage();
994
        if ($perPage !== NULL && !in_array($perPage, $this->perPageList)) {
995
            $this->__triggerUserNotice("The number '$perPage' of items per page is out of range.");
996
        }
997
998
        $this->getModel()->limit($paginator->getOffset(), $paginator->getLength());
999
    }
1000
1001
    protected function createComponentForm($name)
1002
    {
1003 1
        $form = new \Nette\Application\UI\Form($this, $name);
1004 1
        $form->setTranslator($this->getTranslator());
1005 1
        $form->setMethod($form::GET);
1006
1007 1
        $buttons = $form->addContainer(self::BUTTONS);
1008 1
        $buttons->addSubmit('search', 'Grido.Search')
1009 1
            ->onClick[] = [$this, 'handleFilter'];
1010 1
        $buttons->addSubmit('reset', 'Grido.Reset')
1011 1
            ->onClick[] = [$this, 'handleReset'];
1012 1
        $buttons->addSubmit('perPage', 'Grido.ItemsPerPage')
1013 1
            ->onClick[] = [$this, 'handlePerPage'];
1014
1015 1
        $form->addSelect('count', 'Count', $this->getItemsForCountSelect())
1016 1
            ->setTranslator(NULL)
1017 1
            ->controlPrototype->attrs['title'] = $this->getTranslator()->translate('Grido.ItemsPerPage');
1018 1
    }
1019
1020
    /**
1021
     * @return array
1022
     */
1023
    protected function getItemsForCountSelect()
1024
    {
1025 1
        return array_combine($this->perPageList, $this->perPageList);
1026
    }
1027
1028
    /**
1029
     * @internal
1030
     * @param string $message
1031
     */
1032
    public function __triggerUserNotice($message)
1033
    {
1034
        if ($this->getPresenter(FALSE) && $session = $this->getRememberSession()) {
1035
            $session->remove();
1036
        }
1037
1038
        $this->strictMode && trigger_error($message, E_USER_NOTICE);
1039
    }
1040
}
1041