Completed
Push — master ( dd028c...2aa1b8 )
by Song
03:14
created

Grid::disablePagination()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Encore\Admin;
4
5
use Closure;
6
use Encore\Admin\Exception\Handler;
7
use Encore\Admin\Grid\Column;
8
use Encore\Admin\Grid\Displayers;
9
use Encore\Admin\Grid\Exporter;
10
use Encore\Admin\Grid\Filter;
11
use Encore\Admin\Grid\HasElementNames;
12
use Encore\Admin\Grid\Model;
13
use Encore\Admin\Grid\Row;
14
use Encore\Admin\Grid\Tools;
15
use Illuminate\Database\Eloquent\Model as Eloquent;
16
use Illuminate\Database\Eloquent\Relations;
17
use Illuminate\Support\Collection;
18
use Illuminate\Support\Facades\Input;
19
use Jenssegers\Mongodb\Eloquent\Model as MongodbModel;
20
21
class Grid
22
{
23
    use HasElementNames;
24
25
    /**
26
     * The grid data model instance.
27
     *
28
     * @var \Encore\Admin\Grid\Model
29
     */
30
    protected $model;
31
32
    /**
33
     * Collection of all grid columns.
34
     *
35
     * @var \Illuminate\Support\Collection
36
     */
37
    protected $columns;
38
39
    /**
40
     * Collection of all data rows.
41
     *
42
     * @var \Illuminate\Support\Collection
43
     */
44
    protected $rows;
45
46
    /**
47
     * Rows callable fucntion.
48
     *
49
     * @var \Closure
50
     */
51
    protected $rowsCallback;
52
53
    /**
54
     * All column names of the grid.
55
     *
56
     * @var array
57
     */
58
    public $columnNames = [];
59
60
    /**
61
     * Grid builder.
62
     *
63
     * @var \Closure
64
     */
65
    protected $builder;
66
67
    /**
68
     * Mark if the grid is builded.
69
     *
70
     * @var bool
71
     */
72
    protected $builded = false;
73
74
    /**
75
     * All variables in grid view.
76
     *
77
     * @var array
78
     */
79
    protected $variables = [];
80
81
    /**
82
     * The grid Filter.
83
     *
84
     * @var \Encore\Admin\Grid\Filter
85
     */
86
    protected $filter;
87
88
    /**
89
     * Resource path of the grid.
90
     *
91
     * @var
92
     */
93
    protected $resourcePath;
94
95
    /**
96
     * Default primary key name.
97
     *
98
     * @var string
99
     */
100
    protected $keyName = 'id';
101
102
    /**
103
     * Export driver.
104
     *
105
     * @var string
106
     */
107
    protected $exporter;
108
109
    /**
110
     * View for grid to render.
111
     *
112
     * @var string
113
     */
114
    protected $view = 'admin::grid.table';
115
116
    /**
117
     * Per-page options.
118
     *
119
     * @var array
120
     */
121
    public $perPages = [10, 20, 30, 50, 100];
122
123
    /**
124
     * Default items count per-page.
125
     *
126
     * @var int
127
     */
128
    public $perPage = 20;
129
130
    /**
131
     * Header tools.
132
     *
133
     * @var Tools
134
     */
135
    public $tools;
136
137
    /**
138
     * Callback for grid actions.
139
     *
140
     * @var Closure
141
     */
142
    protected $actionsCallback;
143
144
    /**
145
     * Options for grid.
146
     *
147
     * @var array
148
     */
149
    protected $options = [
150
        'usePagination'  => true,
151
        'useFilter'      => true,
152
        'useExporter'    => true,
153
        'useActions'     => true,
154
        'useRowSelector' => true,
155
        'allowCreate'    => true,
156
    ];
157
158
    /**
159
     * @var Closure
160
     */
161
    protected $footer;
162
163
    /**
164
     * Create a new grid instance.
165
     *
166
     * @param Eloquent $model
167
     * @param Closure  $builder
168
     */
169
    public function __construct(Eloquent $model, Closure $builder = null)
170
    {
171
        $this->keyName = $model->getKeyName();
172
        $this->model = new Model($model);
173
        $this->columns = new Collection();
174
        $this->rows = new Collection();
175
        $this->builder = $builder;
176
177
        $this->model()->setGrid($this);
178
179
        $this->setupTools();
180
        $this->setupFilter();
181
182
        $this->handleExportRequest();
183
    }
184
185
    /**
186
     * Setup grid tools.
187
     */
188
    public function setupTools()
189
    {
190
        $this->tools = new Tools($this);
191
    }
192
193
    /**
194
     * Setup grid filter.
195
     *
196
     * @return void
197
     */
198
    protected function setupFilter()
199
    {
200
        $this->filter = new Filter($this->model());
201
    }
202
203
    /**
204
     * Handle export request.
205
     *
206
     * @param bool $forceExport
207
     */
208
    protected function handleExportRequest($forceExport = false)
209
    {
210
        if (!$scope = request(Exporter::$queryName)) {
211
            return;
212
        }
213
214
        $this->model()->usePaginate(false);
215
216
        $exporter = (new Exporter($this))->resolve($this->exporter)->withScope($scope);
217
218
        if ($forceExport) {
219
            $exporter->export();
220
        }
221
222
        if ($this->builder) {
223
            call_user_func($this->builder, $this);
224
225
            $exporter->export();
226
        }
227
    }
228
229
    /**
230
     * Get or set option for grid.
231
     *
232
     * @param string $key
233
     * @param mixed  $value
234
     *
235
     * @return $this|mixed
236
     */
237
    public function option($key, $value = null)
238
    {
239
        if (is_null($value)) {
240
            return $this->options[$key];
241
        }
242
243
        $this->options[$key] = $value;
244
245
        return $this;
246
    }
247
248
    /**
249
     * Get primary key name of model.
250
     *
251
     * @return string
252
     */
253
    public function getKeyName()
254
    {
255
        return $this->keyName ?: 'id';
256
    }
257
258
    /**
259
     * Add column to Grid.
260
     *
261
     * @param string $name
262
     * @param string $label
263
     *
264
     * @return Column
265
     */
266
    public function column($name, $label = '')
267
    {
268
        $relationName = $relationColumn = '';
269
270
        if (strpos($name, '.') !== false) {
271
            list($relationName, $relationColumn) = explode('.', $name);
272
273
            $relation = $this->model()->eloquent()->$relationName();
274
275
            $label = empty($label) ? ucfirst($relationColumn) : $label;
276
277
            $name = snake_case($relationName).'.'.$relationColumn;
278
        }
279
280
        $column = $this->addColumn($name, $label);
281
282
        if (isset($relation) && $relation instanceof Relations\Relation) {
283
            $this->model()->with($relationName);
284
            $column->setRelation($relationName, $relationColumn);
285
        }
286
287
        return $column;
288
    }
289
290
    /**
291
     * Batch add column to grid.
292
     *
293
     * @example
294
     * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
295
     * 2.$grid->columns('name', 'email' ...)
296
     *
297
     * @param array $columns
298
     *
299
     * @return Collection|null
300
     */
301
    public function columns($columns = [])
302
    {
303
        if (func_num_args() == 0) {
304
            return $this->columns;
305
        }
306
307
        if (func_num_args() == 1 && is_array($columns)) {
308
            foreach ($columns as $column => $label) {
309
                $this->column($column, $label);
310
            }
311
312
            return;
313
        }
314
315
        foreach (func_get_args() as $column) {
316
            $this->column($column);
317
        }
318
    }
319
320
    /**
321
     * Add column to grid.
322
     *
323
     * @param string $column
324
     * @param string $label
325
     *
326
     * @return Column
327
     */
328
    protected function addColumn($column = '', $label = '')
329
    {
330
        $column = new Column($column, $label);
331
        $column->setGrid($this);
332
333
        return $this->columns[] = $column;
334
    }
335
336
    /**
337
     * Get Grid model.
338
     *
339
     * @return Model
340
     */
341
    public function model()
342
    {
343
        return $this->model;
344
    }
345
346
    /**
347
     * Paginate the grid.
348
     *
349
     * @param int $perPage
350
     *
351
     * @return void
352
     */
353
    public function paginate($perPage = 20)
354
    {
355
        $this->perPage = $perPage;
356
357
        $this->model()->paginate($perPage);
0 ignored issues
show
Bug introduced by
The method paginate() does not exist on Encore\Admin\Grid\Model. Did you maybe mean usePaginate()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
358
    }
359
360
    /**
361
     * Get the grid paginator.
362
     *
363
     * @return mixed
364
     */
365
    public function paginator()
366
    {
367
        return new Tools\Paginator($this);
368
    }
369
370
    /**
371
     * Disable grid pagination.
372
     *
373
     * @return $this
374
     */
375
    public function disablePagination()
376
    {
377
        $this->model->usePaginate(false);
378
379
        $this->option('usePagination', false);
380
381
        return $this;
382
    }
383
384
    /**
385
     * If this grid use pagination.
386
     *
387
     * @return bool
388
     */
389
    public function usePagination()
390
    {
391
        return $this->option('usePagination');
392
    }
393
394
    /**
395
     * Set per-page options.
396
     *
397
     * @param array $perPages
398
     */
399
    public function perPages(array $perPages)
400
    {
401
        $this->perPages = $perPages;
402
    }
403
404
    /**
405
     * Disable all actions.
406
     *
407
     * @return $this
408
     */
409
    public function disableActions()
410
    {
411
        return $this->option('useActions', false);
412
    }
413
414
    /**
415
     * Set grid action callback.
416
     *
417
     * @param Closure $callback
418
     *
419
     * @return $this
420
     */
421
    public function actions(Closure $callback)
422
    {
423
        $this->actionsCallback = $callback;
424
425
        return $this;
426
    }
427
428
    /**
429
     * Add `actions` column for grid.
430
     *
431
     * @return void
432
     */
433
    protected function appendActionsColumn()
434
    {
435
        if (!$this->option('useActions')) {
436
            return;
437
        }
438
439
        $grid = $this;
440
        $callback = $this->actionsCallback;
441
        $column = $this->addColumn('__actions__', trans('admin.action'));
442
443
        $column->display(function ($value) use ($grid, $column, $callback) {
444
            $actions = new Displayers\Actions($value, $grid, $column, $this);
0 ignored issues
show
Documentation introduced by
$this is of type this<Encore\Admin\Grid>, but the function expects a object<stdClass>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
445
446
            return $actions->display($callback);
447
        });
448
    }
449
450
    /**
451
     * Disable row selector.
452
     *
453
     * @return Grid|mixed
454
     */
455
    public function disableRowSelector()
456
    {
457
        $this->tools(function ($tools) {
458
            /* @var Grid\Tools $tools */
459
            $tools->disableBatchActions();
460
        });
461
462
        return $this->option('useRowSelector', false);
463
    }
464
465
    /**
466
     * Prepend checkbox column for grid.
467
     *
468
     * @return void
469
     */
470
    protected function prependRowSelectorColumn()
471
    {
472
        if (!$this->option('useRowSelector')) {
473
            return;
474
        }
475
476
        $grid = $this;
477
478
        $column = new Column(Column::SELECT_COLUMN_NAME, ' ');
479
        $column->setGrid($this);
480
481
        $column->display(function ($value) use ($grid, $column) {
482
            $actions = new Displayers\RowSelector($value, $grid, $column, $this);
0 ignored issues
show
Documentation introduced by
$this is of type this<Encore\Admin\Grid>, but the function expects a object<stdClass>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
483
484
            return $actions->display();
485
        });
486
487
        $this->columns->prepend($column);
488
    }
489
490
    /**
491
     * Build the grid.
492
     *
493
     * @return void
494
     */
495
    public function build()
496
    {
497
        if ($this->builded) {
498
            return;
499
        }
500
501
        $collection = $this->processFilter(false);
502
503
        $data = $collection->toArray();
504
505
        $this->prependRowSelectorColumn();
506
        $this->appendActionsColumn();
507
508
        Column::setOriginalGridModels($collection);
509
510
        $this->columns->map(function (Column $column) use (&$data) {
511
            $data = $column->fill($data);
512
513
            $this->columnNames[] = $column->getName();
514
        });
515
516
        $this->buildRows($data);
517
518
        $this->builded = true;
519
    }
520
521
    /**
522
     * Disable grid filter.
523
     *
524
     * @return $this
525
     */
526
    public function disableFilter()
527
    {
528
        $this->option('useFilter', false);
529
530
        $this->tools->disableFilterButton();
531
532
        return $this;
533
    }
534
535
    /**
536
     * Get filter of Grid.
537
     *
538
     * @return Filter
539
     */
540
    public function getFilter()
541
    {
542
        return $this->filter;
543
    }
544
545
    /**
546
     * Process the grid filter.
547
     *
548
     * @param bool $toArray
549
     * @return array|Collection|mixed
550
     */
551
    public function processFilter($toArray = true)
552
    {
553
        if ($this->builder) {
554
            call_user_func($this->builder, $this);
555
        }
556
557
        return $this->filter->execute($toArray);
558
    }
559
560
    /**
561
     * Set the grid filter.
562
     *
563
     * @param Closure $callback
564
     */
565
    public function filter(Closure $callback)
566
    {
567
        call_user_func($callback, $this->filter);
568
    }
569
570
    /**
571
     * Render the grid filter.
572
     *
573
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string
574
     */
575
    public function renderFilter()
576
    {
577
        if (!$this->option('useFilter')) {
578
            return '';
579
        }
580
581
        return $this->filter->render();
582
    }
583
584
    /**
585
     * Expand filter.
586
     *
587
     * @return $this
588
     */
589
    public function expandFilter()
590
    {
591
        $this->filter->expand();
592
593
        return $this;
594
    }
595
596
    /**
597
     * Build the grid rows.
598
     *
599
     * @param array $data
600
     *
601
     * @return void
602
     */
603
    protected function buildRows(array $data)
604
    {
605
        $this->rows = collect($data)->map(function ($model, $number) {
606
            return new Row($number, $model);
607
        });
608
609
        if ($this->rowsCallback) {
610
            $this->rows->map($this->rowsCallback);
611
        }
612
    }
613
614
    /**
615
     * Set grid row callback function.
616
     *
617
     * @param Closure $callable
618
     *
619
     * @return Collection|null
620
     */
621
    public function rows(Closure $callable = null)
622
    {
623
        if (is_null($callable)) {
624
            return $this->rows;
625
        }
626
627
        $this->rowsCallback = $callable;
628
    }
629
630
    /**
631
     * Setup grid tools.
632
     *
633
     * @param Closure $callback
634
     *
635
     * @return void
636
     */
637
    public function tools(Closure $callback)
638
    {
639
        call_user_func($callback, $this->tools);
640
    }
641
642
    /**
643
     * Render custom tools.
644
     *
645
     * @return string
646
     */
647
    public function renderHeaderTools()
648
    {
649
        return $this->tools->render();
650
    }
651
652
    /**
653
     * Set exporter driver for Grid to export.
654
     *
655
     * @param $exporter
656
     *
657
     * @return $this
658
     */
659
    public function exporter($exporter)
660
    {
661
        $this->exporter = $exporter;
662
663
        return $this;
664
    }
665
666
    /**
667
     * Get the export url.
668
     *
669
     * @param int  $scope
670
     * @param null $args
671
     *
672
     * @return string
673
     */
674
    public function getExportUrl($scope = 1, $args = null)
675
    {
676
        $input = array_merge(Input::all(), Exporter::formatExportQuery($scope, $args));
677
678
        if ($constraints = $this->model()->getConstraints()) {
679
            $input = array_merge($input, $constraints);
680
        }
681
682
        return $this->resource().'?'.http_build_query($input);
683
    }
684
685
    /**
686
     * Get create url.
687
     *
688
     * @return string
689
     */
690
    public function getCreateUrl()
691
    {
692
        $queryString = '';
693
694
        if ($constraints = $this->model()->getConstraints()) {
695
            $queryString = http_build_query($constraints);
696
        }
697
698
        return sprintf('%s/create%s',
699
            $this->resource(),
700
            $queryString ? ('?'.$queryString) : ''
701
        );
702
    }
703
704
    /**
705
     * If grid allows export.s.
706
     *
707
     * @return bool
708
     */
709
    public function allowExport()
710
    {
711
        return $this->option('useExporter');
712
    }
713
714
    /**
715
     * Disable export.
716
     *
717
     * @return $this
718
     */
719
    public function disableExport()
720
    {
721
        return $this->option('useExporter', false);
722
    }
723
724
    /**
725
     * Render export button.
726
     *
727
     * @return string
728
     */
729
    public function renderExportButton()
730
    {
731
        return (new Tools\ExportButton($this))->render();
732
    }
733
734
    /**
735
     * Alias for method `disableCreateButton`.
736
     *
737
     * @return $this
738
     *
739
     * @deprecated
740
     */
741
    public function disableCreation()
742
    {
743
        return $this->disableCreateButton();
744
    }
745
746
    /**
747
     * Remove create button on grid.
748
     *
749
     * @return $this
750
     */
751
    public function disableCreateButton()
752
    {
753
        return $this->option('allowCreate', false);
754
    }
755
756
    /**
757
     * If allow creation.
758
     *
759
     * @return bool
760
     */
761
    public function allowCreation()
762
    {
763
        return $this->option('allowCreate');
764
    }
765
766
    /**
767
     * Render create button for grid.
768
     *
769
     * @return string
770
     */
771
    public function renderCreateButton()
772
    {
773
        return (new Tools\CreateButton($this))->render();
774
    }
775
776
    /**
777
     * Set grid footer.
778
     *
779
     * @param Closure|null $closure
780
     *
781
     * @return Closure
782
     */
783
    public function footer(Closure $closure = null)
784
    {
785
        if (!$closure) {
786
            return $this->footer;
787
        }
788
789
        $this->footer = $closure;
790
791
        return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Encore\Admin\Grid) is incompatible with the return type documented by Encore\Admin\Grid::footer of type Closure.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
792
    }
793
794
    /**
795
     * Render grid footer.
796
     *
797
     * @return Tools\Footer|string
798
     */
799
    public function renderFooter()
800
    {
801
        if (!$this->footer) {
802
            return '';
803
        }
804
805
        return (new Tools\Footer($this))->render();
806
    }
807
808
    /**
809
     * Get current resource uri.
810
     *
811
     * @param string $path
812
     *
813
     * @return string
814
     */
815
    public function resource($path = null)
816
    {
817
        if (!empty($path)) {
818
            $this->resourcePath = $path;
819
820
            return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (Encore\Admin\Grid) is incompatible with the return type documented by Encore\Admin\Grid::resource of type string.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
821
        }
822
823
        if (!empty($this->resourcePath)) {
824
            return $this->resourcePath;
825
        }
826
827
        return app('request')->getPathInfo();
828
    }
829
830
    /**
831
     * Handle get mutator column for grid.
832
     *
833
     * @param string $method
834
     * @param string $label
835
     *
836
     * @return bool|Column
837
     */
838
    protected function handleGetMutatorColumn($method, $label)
839
    {
840
        if ($this->model()->eloquent()->hasGetMutator($method)) {
841
            return $this->addColumn($method, $label);
842
        }
843
844
        return false;
845
    }
846
847
    /**
848
     * Handle relation column for grid.
849
     *
850
     * @param string $method
851
     * @param string $label
852
     *
853
     * @return bool|Column
854
     */
855
    protected function handleRelationColumn($method, $label)
856
    {
857
        $model = $this->model()->eloquent();
858
859
        if (!method_exists($model, $method)) {
860
            return false;
861
        }
862
863
        if (!($relation = $model->$method()) instanceof Relations\Relation) {
864
            return false;
865
        }
866
867
        if ($relation instanceof Relations\HasOne || $relation instanceof Relations\BelongsTo) {
868
            $this->model()->with($method);
869
870
            return $this->addColumn($method, $label)->setRelation(snake_case($method));
871
        }
872
873
        if ($relation instanceof Relations\HasMany
874
            || $relation instanceof Relations\BelongsToMany
875
            || $relation instanceof Relations\MorphToMany
876
        ) {
877
            $this->model()->with($method);
878
879
            return $this->addColumn(snake_case($method), $label);
880
        }
881
882
        return false;
883
    }
884
885
    /**
886
     * Dynamically add columns to the grid view.
887
     *
888
     * @param $method
889
     * @param $arguments
890
     *
891
     * @return Column
892
     */
893
    public function __call($method, $arguments)
894
    {
895
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
896
897
        if ($this->model()->eloquent() instanceof MongodbModel) {
0 ignored issues
show
Bug introduced by
The class Jenssegers\Mongodb\Eloquent\Model 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...
898
            return $this->addColumn($method, $label);
899
        }
900
901
        if ($column = $this->handleGetMutatorColumn($method, $label)) {
902
            return $column;
903
        }
904
905
        if ($column = $this->handleRelationColumn($method, $label)) {
906
            return $column;
907
        }
908
909
        return $this->addColumn($method, $label);
910
    }
911
912
    /**
913
     * Register column displayers.
914
     *
915
     * @return void.
0 ignored issues
show
Documentation introduced by
The doc-type void. could not be parsed: Unknown type name "void." at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
916
     */
917
    public static function registerColumnDisplayer()
918
    {
919
        $map = [
920
            'editable'    => Displayers\Editable::class,
921
            'switch'      => Displayers\SwitchDisplay::class,
922
            'switchGroup' => Displayers\SwitchGroup::class,
923
            'select'      => Displayers\Select::class,
924
            'image'       => Displayers\Image::class,
925
            'label'       => Displayers\Label::class,
926
            'button'      => Displayers\Button::class,
927
            'link'        => Displayers\Link::class,
928
            'badge'       => Displayers\Badge::class,
929
            'progressBar' => Displayers\ProgressBar::class,
930
            'radio'       => Displayers\Radio::class,
931
            'checkbox'    => Displayers\Checkbox::class,
932
            'orderable'   => Displayers\Orderable::class,
933
            'table'       => Displayers\Table::class,
934
        ];
935
936
        foreach ($map as $abstract => $class) {
937
            Column::extend($abstract, $class);
938
        }
939
    }
940
941
    /**
942
     * Add variables to grid view.
943
     *
944
     * @param array $variables
945
     *
946
     * @return $this
947
     */
948
    public function with($variables = [])
949
    {
950
        $this->variables = $variables;
951
952
        return $this;
953
    }
954
955
    /**
956
     * Get all variables will used in grid view.
957
     *
958
     * @return array
959
     */
960
    protected function variables()
961
    {
962
        $this->variables['grid'] = $this;
963
964
        return $this->variables;
965
    }
966
967
    /**
968
     * Set a view to render.
969
     *
970
     * @param string $view
971
     * @param array  $variables
972
     */
973
    public function setView($view, $variables = [])
974
    {
975
        if (!empty($variables)) {
976
            $this->with($variables);
977
        }
978
979
        $this->view = $view;
980
    }
981
982
    /**
983
     * Set grid title.
984
     *
985
     * @param string $title
986
     *
987
     * @return $this
988
     */
989
    public function setTitle($title)
990
    {
991
        $this->variables['title'] = $title;
992
993
        return $this;
994
    }
995
996
    /**
997
     * Set relation for grid.
998
     *
999
     * @param Relations\Relation $relation
1000
     *
1001
     * @return $this
1002
     */
1003
    public function setRelation(Relations\Relation $relation)
1004
    {
1005
        $this->model()->setRelation($relation);
1006
1007
        return $this;
1008
    }
1009
1010
    /**
1011
     * Set resource path for grid.
1012
     *
1013
     * @param string $path
1014
     *
1015
     * @return $this
1016
     */
1017
    public function setResource($path)
1018
    {
1019
        $this->resourcePath = $path;
1020
1021
        return $this;
1022
    }
1023
1024
    /**
1025
     * Get the string contents of the grid view.
1026
     *
1027
     * @return string
1028
     */
1029
    public function render()
1030
    {
1031
        $this->handleExportRequest(true);
1032
1033
        try {
1034
            $this->build();
1035
        } catch (\Exception $e) {
1036
            return Handler::renderException($e);
1037
        }
1038
1039
        return view($this->view, $this->variables())->render();
0 ignored issues
show
Bug introduced by
The method render does only exist in Illuminate\View\View, but not in Illuminate\Contracts\View\Factory.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
1040
    }
1041
}
1042