Completed
Pull Request — master (#2693)
by
unknown
29:21 queued 12:55
created

Grid::disableCreation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

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

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
344
    {
345
        $column = new Column($column, $label);
346
        $column->setGrid($this);
347
348
        return tap($column, function ($value) {
349
            $this->columns->push($value);
350
        });
351
    }
352
353
    /**
354
     * Prepend column to grid.
355
     *
356
     * @param string $column
357
     * @param string $label
358
     *
359
     * @return Column
360
     */
361 View Code Duplication
    protected function prependColumn($column = '', $label = '')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
362
    {
363
        $column = new Column($column, $label);
364
        $column->setGrid($this);
365
366
        return tap($column, function ($value) {
367
            $this->columns->prepend($value);
368
        });
369
    }
370
371
    /**
372
     * Get Grid model.
373
     *
374
     * @return Model
375
     */
376
    public function model()
377
    {
378
        return $this->model;
379
    }
380
381
    /**
382
     * Paginate the grid.
383
     *
384
     * @param int $perPage
385
     *
386
     * @return void
387
     */
388
    public function paginate($perPage = 20)
389
    {
390
        $this->perPage = $perPage;
391
392
        $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...
393
    }
394
395
    /**
396
     * Get the grid paginator.
397
     *
398
     * @return mixed
399
     */
400
    public function paginator()
401
    {
402
        return new Tools\Paginator($this);
403
    }
404
405
    /**
406
     * Disable grid pagination.
407
     *
408
     * @return $this
409
     */
410
    public function disablePagination()
411
    {
412
        $this->model->usePaginate(false);
413
414
        $this->option('usePagination', false);
415
416
        return $this;
417
    }
418
419
    /**
420
     * If this grid use pagination.
421
     *
422
     * @return bool
423
     */
424
    public function usePagination()
425
    {
426
        return $this->option('usePagination');
427
    }
428
429
    /**
430
     * Set per-page options.
431
     *
432
     * @param array $perPages
433
     */
434
    public function perPages(array $perPages)
435
    {
436
        $this->perPages = $perPages;
437
    }
438
439
    /**
440
     * Disable all actions.
441
     *
442
     * @return $this
443
     */
444
    public function disableActions()
445
    {
446
        return $this->option('useActions', false);
447
    }
448
449
    /**
450
     * Set grid action callback.
451
     *
452
     * @param Closure $callback
453
     *
454
     * @return $this
455
     */
456
    public function actions(Closure $callback)
457
    {
458
        $this->actionsCallback = $callback;
459
460
        return $this;
461
    }
462
463
    /**
464
     * Add `actions` column for grid.
465
     *
466
     * @return void
467
     */
468
    protected function appendActionsColumn()
469
    {
470
        if (!$this->option('useActions')) {
471
            return;
472
        }
473
474
        $this->addColumn('__actions__', trans('admin.action'))
475
            ->displayUsing(Displayers\Actions::class, [$this->actionsCallback]);
476
    }
477
478
    /**
479
     * Disable row selector.
480
     *
481
     * @return Grid|mixed
482
     */
483
    public function disableRowSelector()
484
    {
485
        $this->tools(function ($tools) {
486
            /* @var Grid\Tools $tools */
487
            $tools->disableBatchActions();
488
        });
489
490
        return $this->option('useRowSelector', false);
491
    }
492
493
    /**
494
     * Prepend checkbox column for grid.
495
     *
496
     * @return void
497
     */
498
    protected function prependRowSelectorColumn()
499
    {
500
        if (!$this->option('useRowSelector')) {
501
            return;
502
        }
503
504
        $this->prependColumn(Column::SELECT_COLUMN_NAME, ' ')
505
            ->displayUsing(Displayers\RowSelector::class);
506
    }
507
508
    /**
509
     * Build the grid.
510
     *
511
     * @return void
512
     */
513
    public function build()
514
    {
515
        if ($this->builded) {
516
            return;
517
        }
518
519
        $collection = $this->processFilter(false);
520
521
        $data = $collection->toArray();
522
523
        $this->prependRowSelectorColumn();
524
        $this->appendActionsColumn();
525
526
        Column::setOriginalGridModels($collection);
527
528
        $this->columns->map(function (Column $column) use (&$data) {
529
            $data = $column->fill($data);
530
531
            $this->columnNames[] = $column->getName();
532
        });
533
534
        $this->buildRows($data);
535
536
        $this->builded = true;
537
    }
538
539
    /**
540
     * Disable header tools.
541
     *
542
     * @return $this
543
     */
544
    public function disableTools()
545
    {
546
        $this->option('useTools', false);
547
        return $this;
548
    }
549
550
    /**
551
     * Disable grid filter.
552
     *
553
     * @return $this
554
     */
555
    public function disableFilter()
556
    {
557
        $this->option('useFilter', false);
558
559
        $this->tools->disableFilterButton();
560
561
        return $this;
562
    }
563
564
    /**
565
     * Get filter of Grid.
566
     *
567
     * @return Filter
568
     */
569
    public function getFilter()
570
    {
571
        return $this->filter;
572
    }
573
574
    /**
575
     * Process the grid filter.
576
     *
577
     * @param bool $toArray
578
     *
579
     * @return array|Collection|mixed
580
     */
581
    public function processFilter($toArray = true)
582
    {
583
        if ($this->builder) {
584
            call_user_func($this->builder, $this);
585
        }
586
587
        return $this->filter->execute($toArray);
588
    }
589
590
    /**
591
     * Set the grid filter.
592
     *
593
     * @param Closure $callback
594
     */
595
    public function filter(Closure $callback)
596
    {
597
        call_user_func($callback, $this->filter);
598
    }
599
600
    /**
601
     * Render the grid filter.
602
     *
603
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string
604
     */
605
    public function renderFilter()
606
    {
607
        if (!$this->option('useFilter')) {
608
            return '';
609
        }
610
611
        return $this->filter->render();
612
    }
613
614
    /**
615
     * Expand filter.
616
     *
617
     * @return $this
618
     */
619
    public function expandFilter()
620
    {
621
        $this->filter->expand();
622
623
        return $this;
624
    }
625
626
    /**
627
     * Build the grid rows.
628
     *
629
     * @param array $data
630
     *
631
     * @return void
632
     */
633
    protected function buildRows(array $data)
634
    {
635
        $this->rows = collect($data)->map(function ($model, $number) {
636
            return new Row($number, $model);
637
        });
638
639
        if ($this->rowsCallback) {
640
            $this->rows->map($this->rowsCallback);
641
        }
642
    }
643
644
    /**
645
     * Set grid row callback function.
646
     *
647
     * @param Closure $callable
648
     *
649
     * @return Collection|null
650
     */
651
    public function rows(Closure $callable = null)
652
    {
653
        if (is_null($callable)) {
654
            return $this->rows;
655
        }
656
657
        $this->rowsCallback = $callable;
658
    }
659
660
    /**
661
     * Setup grid tools.
662
     *
663
     * @param Closure $callback
664
     *
665
     * @return void
666
     */
667
    public function tools(Closure $callback)
668
    {
669
        call_user_func($callback, $this->tools);
670
    }
671
672
    /**
673
     * Render custom tools.
674
     *
675
     * @return string
676
     */
677
    public function renderHeaderTools()
678
    {
679
        return $this->tools->render();
680
    }
681
682
    /**
683
     * Set exporter driver for Grid to export.
684
     *
685
     * @param $exporter
686
     *
687
     * @return $this
688
     */
689
    public function exporter($exporter)
690
    {
691
        $this->exporter = $exporter;
692
693
        return $this;
694
    }
695
696
    /**
697
     * Get the export url.
698
     *
699
     * @param int  $scope
700
     * @param null $args
701
     *
702
     * @return string
703
     */
704
    public function getExportUrl($scope = 1, $args = null)
705
    {
706
        $input = array_merge(Input::all(), Exporter::formatExportQuery($scope, $args));
707
708
        if ($constraints = $this->model()->getConstraints()) {
709
            $input = array_merge($input, $constraints);
710
        }
711
712
        return $this->resource().'?'.http_build_query($input);
713
    }
714
715
    /**
716
     * Get create url.
717
     *
718
     * @return string
719
     */
720
    public function getCreateUrl()
721
    {
722
        $queryString = '';
723
724
        if ($constraints = $this->model()->getConstraints()) {
725
            $queryString = http_build_query($constraints);
726
        }
727
728
        return sprintf('%s/create%s',
729
            $this->resource(),
730
            $queryString ? ('?'.$queryString) : ''
731
        );
732
    }
733
734
    /**
735
     * If grid allows to use header tools
736
     *
737
     * @return bool
738
     */
739
    public function allowTools()
740
    {
741
        return $this->option('useTools');
742
    }
743
744
    /**
745
     * If grid allows export.s.
746
     *
747
     * @return bool
748
     */
749
    public function allowExport()
750
    {
751
        return $this->option('useExporter');
752
    }
753
754
    /**
755
     * Disable export.
756
     *
757
     * @return $this
758
     */
759
    public function disableExport()
760
    {
761
        return $this->option('useExporter', false);
762
    }
763
764
    /**
765
     * Render export button.
766
     *
767
     * @return string
768
     */
769
    public function renderExportButton()
770
    {
771
        return (new Tools\ExportButton($this))->render();
772
    }
773
774
    /**
775
     * Alias for method `disableCreateButton`.
776
     *
777
     * @return $this
778
     *
779
     * @deprecated
780
     */
781
    public function disableCreation()
782
    {
783
        return $this->disableCreateButton();
784
    }
785
786
    /**
787
     * Remove create button on grid.
788
     *
789
     * @return $this
790
     */
791
    public function disableCreateButton()
792
    {
793
        return $this->option('allowCreate', false);
794
    }
795
796
    /**
797
     * If allow creation.
798
     *
799
     * @return bool
800
     */
801
    public function allowCreation()
802
    {
803
        return $this->option('allowCreate');
804
    }
805
806
    /**
807
     * Render create button for grid.
808
     *
809
     * @return string
810
     */
811
    public function renderCreateButton()
812
    {
813
        return (new Tools\CreateButton($this))->render();
814
    }
815
816
    /**
817
     * Set grid footer.
818
     *
819
     * @param Closure|null $closure
820
     *
821
     * @return Closure
822
     */
823
    public function footer(Closure $closure = null)
824
    {
825
        if (!$closure) {
826
            return $this->footer;
827
        }
828
829
        $this->footer = $closure;
830
831
        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...
832
    }
833
834
    /**
835
     * Render grid footer.
836
     *
837
     * @return Tools\Footer|string
838
     */
839
    public function renderFooter()
840
    {
841
        if (!$this->footer) {
842
            return '';
843
        }
844
845
        return (new Tools\Footer($this))->render();
846
    }
847
848
    /**
849
     * Get current resource uri.
850
     *
851
     * @param string $path
852
     *
853
     * @return string
854
     */
855
    public function resource($path = null)
856
    {
857
        if (!empty($path)) {
858
            $this->resourcePath = $path;
859
860
            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...
861
        }
862
863
        if (!empty($this->resourcePath)) {
864
            return $this->resourcePath;
865
        }
866
867
        return app('request')->getPathInfo();
868
    }
869
870
    /**
871
     * Handle get mutator column for grid.
872
     *
873
     * @param string $method
874
     * @param string $label
875
     *
876
     * @return bool|Column
877
     */
878
    protected function handleGetMutatorColumn($method, $label)
879
    {
880
        if ($this->model()->eloquent()->hasGetMutator($method)) {
881
            return $this->addColumn($method, $label);
882
        }
883
884
        return false;
885
    }
886
887
    /**
888
     * Handle relation column for grid.
889
     *
890
     * @param string $method
891
     * @param string $label
892
     *
893
     * @return bool|Column
894
     */
895
    protected function handleRelationColumn($method, $label)
896
    {
897
        $model = $this->model()->eloquent();
898
899
        if (!method_exists($model, $method)) {
900
            return false;
901
        }
902
903
        if (!($relation = $model->$method()) instanceof Relations\Relation) {
904
            return false;
905
        }
906
907
        if ($relation instanceof Relations\HasOne || $relation instanceof Relations\BelongsTo) {
908
            $this->model()->with($method);
909
910
            return $this->addColumn($method, $label)->setRelation(snake_case($method));
911
        }
912
913
        if ($relation instanceof Relations\HasMany
914
            || $relation instanceof Relations\BelongsToMany
915
            || $relation instanceof Relations\MorphToMany
916
        ) {
917
            $this->model()->with($method);
918
919
            return $this->addColumn(snake_case($method), $label);
920
        }
921
922
        return false;
923
    }
924
925
    /**
926
     * Dynamically add columns to the grid view.
927
     *
928
     * @param $method
929
     * @param $arguments
930
     *
931
     * @return Column
932
     */
933
    public function __call($method, $arguments)
934
    {
935
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
936
937
        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...
938
            return $this->addColumn($method, $label);
939
        }
940
941
        if ($column = $this->handleGetMutatorColumn($method, $label)) {
942
            return $column;
943
        }
944
945
        if ($column = $this->handleRelationColumn($method, $label)) {
946
            return $column;
947
        }
948
949
        return $this->addColumn($method, $label);
950
    }
951
952
    /**
953
     * Register column displayers.
954
     *
955
     * @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...
956
     */
957
    public static function registerColumnDisplayer()
958
    {
959
        $map = [
960
            'editable'    => Displayers\Editable::class,
961
            'switch'      => Displayers\SwitchDisplay::class,
962
            'switchGroup' => Displayers\SwitchGroup::class,
963
            'select'      => Displayers\Select::class,
964
            'image'       => Displayers\Image::class,
965
            'label'       => Displayers\Label::class,
966
            'button'      => Displayers\Button::class,
967
            'link'        => Displayers\Link::class,
968
            'badge'       => Displayers\Badge::class,
969
            'progressBar' => Displayers\ProgressBar::class,
970
            'radio'       => Displayers\Radio::class,
971
            'checkbox'    => Displayers\Checkbox::class,
972
            'orderable'   => Displayers\Orderable::class,
973
            'table'       => Displayers\Table::class,
974
        ];
975
976
        foreach ($map as $abstract => $class) {
977
            Column::extend($abstract, $class);
978
        }
979
    }
980
981
    /**
982
     * Add variables to grid view.
983
     *
984
     * @param array $variables
985
     *
986
     * @return $this
987
     */
988
    public function with($variables = [])
989
    {
990
        $this->variables = $variables;
991
992
        return $this;
993
    }
994
995
    /**
996
     * Get all variables will used in grid view.
997
     *
998
     * @return array
999
     */
1000
    protected function variables()
1001
    {
1002
        $this->variables['grid'] = $this;
1003
1004
        return $this->variables;
1005
    }
1006
1007
    /**
1008
     * Set a view to render.
1009
     *
1010
     * @param string $view
1011
     * @param array  $variables
1012
     */
1013
    public function setView($view, $variables = [])
1014
    {
1015
        if (!empty($variables)) {
1016
            $this->with($variables);
1017
        }
1018
1019
        $this->view = $view;
1020
    }
1021
1022
    /**
1023
     * Set grid title.
1024
     *
1025
     * @param string $title
1026
     *
1027
     * @return $this
1028
     */
1029
    public function setTitle($title)
1030
    {
1031
        $this->variables['title'] = $title;
1032
1033
        return $this;
1034
    }
1035
1036
    /**
1037
     * Set relation for grid.
1038
     *
1039
     * @param Relations\Relation $relation
1040
     *
1041
     * @return $this
1042
     */
1043
    public function setRelation(Relations\Relation $relation)
1044
    {
1045
        $this->model()->setRelation($relation);
1046
1047
        return $this;
1048
    }
1049
1050
    /**
1051
     * Set resource path for grid.
1052
     *
1053
     * @param string $path
1054
     *
1055
     * @return $this
1056
     */
1057
    public function setResource($path)
1058
    {
1059
        $this->resourcePath = $path;
1060
1061
        return $this;
1062
    }
1063
1064
    /**
1065
     * Get the string contents of the grid view.
1066
     *
1067
     * @return string
1068
     */
1069
    public function render()
1070
    {
1071
        $this->handleExportRequest(true);
1072
1073
        try {
1074
            $this->build();
1075
        } catch (\Exception $e) {
1076
            return Handler::renderException($e);
1077
        }
1078
1079
        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...
1080
    }
1081
}
1082