Completed
Push — master ( a2dd34...253c8c )
by Song
03:46
created

Grid::__call()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
nc 8
nop 2
dl 0
loc 18
rs 9.3554
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 Tools\Footer
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
        $this->setupExporter();
182
    }
183
184
    /**
185
     * Setup grid tools.
186
     */
187
    public function setupTools()
188
    {
189
        $this->tools = new Tools($this);
190
    }
191
192
    /**
193
     * Setup grid filter.
194
     *
195
     * @return void
196
     */
197
    protected function setupFilter()
198
    {
199
        $this->filter = new Filter($this->model());
200
    }
201
202
    /**
203
     * Setup grid exporter.
204
     *
205
     * @return void
206
     */
207
    protected function setupExporter()
208
    {
209
        if ($scope = Input::get(Exporter::$queryName)) {
210
            $this->model()->usePaginate(false);
211
212
            if ($this->builder) {
213
                call_user_func($this->builder, $this);
214
            }
215
216
            (new Exporter($this))->resolve($this->exporter)->withScope($scope)->export();
217
        }
218
    }
219
220
    /**
221
     * Get or set option for grid.
222
     *
223
     * @param string $key
224
     * @param mixed  $value
225
     *
226
     * @return $this|mixed
227
     */
228
    public function option($key, $value = null)
229
    {
230
        if (is_null($value)) {
231
            return $this->options[$key];
232
        }
233
234
        $this->options[$key] = $value;
235
236
        return $this;
237
    }
238
239
    /**
240
     * Get primary key name of model.
241
     *
242
     * @return string
243
     */
244
    public function getKeyName()
245
    {
246
        return $this->keyName ?: 'id';
247
    }
248
249
    /**
250
     * Add column to Grid.
251
     *
252
     * @param string $name
253
     * @param string $label
254
     *
255
     * @return Column
256
     */
257
    public function column($name, $label = '')
258
    {
259
        $relationName = $relationColumn = '';
260
261
        if (strpos($name, '.') !== false) {
262
            list($relationName, $relationColumn) = explode('.', $name);
263
264
            $relation = $this->model()->eloquent()->$relationName();
265
266
            $label = empty($label) ? ucfirst($relationColumn) : $label;
267
268
            $name = snake_case($relationName).'.'.$relationColumn;
269
        }
270
271
        $column = $this->addColumn($name, $label);
272
273
        if (isset($relation) && $relation instanceof Relations\Relation) {
274
            $this->model()->with($relationName);
275
            $column->setRelation($relationName, $relationColumn);
276
        }
277
278
        return $column;
279
    }
280
281
    /**
282
     * Batch add column to grid.
283
     *
284
     * @example
285
     * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
286
     * 2.$grid->columns('name', 'email' ...)
287
     *
288
     * @param array $columns
289
     *
290
     * @return Collection|null
291
     */
292
    public function columns($columns = [])
293
    {
294
        if (func_num_args() == 0) {
295
            return $this->columns;
296
        }
297
298
        if (func_num_args() == 1 && is_array($columns)) {
299
            foreach ($columns as $column => $label) {
300
                $this->column($column, $label);
301
            }
302
303
            return;
304
        }
305
306
        foreach (func_get_args() as $column) {
307
            $this->column($column);
308
        }
309
    }
310
311
    /**
312
     * Add column to grid.
313
     *
314
     * @param string $column
315
     * @param string $label
316
     *
317
     * @return Column
318
     */
319
    protected function addColumn($column = '', $label = '')
320
    {
321
        $column = new Column($column, $label);
322
        $column->setGrid($this);
323
324
        return $this->columns[] = $column;
325
    }
326
327
    /**
328
     * Get Grid model.
329
     *
330
     * @return Model
331
     */
332
    public function model()
333
    {
334
        return $this->model;
335
    }
336
337
    /**
338
     * Paginate the grid.
339
     *
340
     * @param int $perPage
341
     *
342
     * @return void
343
     */
344
    public function paginate($perPage = 20)
345
    {
346
        $this->perPage = $perPage;
347
348
        $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...
349
    }
350
351
    /**
352
     * Get the grid paginator.
353
     *
354
     * @return mixed
355
     */
356
    public function paginator()
357
    {
358
        return new Tools\Paginator($this);
359
    }
360
361
    /**
362
     * Disable grid pagination.
363
     *
364
     * @return $this
365
     */
366
    public function disablePagination()
367
    {
368
        $this->model->usePaginate(false);
369
370
        $this->option('usePagination', false);
371
372
        return $this;
373
    }
374
375
    /**
376
     * If this grid use pagination.
377
     *
378
     * @return bool
379
     */
380
    public function usePagination()
381
    {
382
        return $this->option('usePagination');
383
    }
384
385
    /**
386
     * Set per-page options.
387
     *
388
     * @param array $perPages
389
     */
390
    public function perPages(array $perPages)
391
    {
392
        $this->perPages = $perPages;
393
    }
394
395
    /**
396
     * Disable all actions.
397
     *
398
     * @return $this
399
     */
400
    public function disableActions()
401
    {
402
        return $this->option('useActions', false);
403
    }
404
405
    /**
406
     * Set grid action callback.
407
     *
408
     * @param Closure $callback
409
     *
410
     * @return $this
411
     */
412
    public function actions(Closure $callback)
413
    {
414
        $this->actionsCallback = $callback;
415
416
        return $this;
417
    }
418
419
    /**
420
     * Add `actions` column for grid.
421
     *
422
     * @return void
423
     */
424
    protected function appendActionsColumn()
425
    {
426
        if (!$this->option('useActions')) {
427
            return;
428
        }
429
430
        $grid = $this;
431
        $callback = $this->actionsCallback;
432
        $column = $this->addColumn('__actions__', trans('admin.action'));
433
434
        $column->display(function ($value) use ($grid, $column, $callback) {
435
            $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...
436
437
            return $actions->display($callback);
438
        });
439
    }
440
441
    /**
442
     * Disable row selector.
443
     *
444
     * @return Grid|mixed
445
     */
446
    public function disableRowSelector()
447
    {
448
        $this->tools(function ($tools) {
449
            /* @var Grid\Tools $tools */
450
            $tools->disableBatchActions();
451
        });
452
453
        return $this->option('useRowSelector', false);
454
    }
455
456
    /**
457
     * Prepend checkbox column for grid.
458
     *
459
     * @return void
460
     */
461
    protected function prependRowSelectorColumn()
462
    {
463
        if (!$this->option('useRowSelector')) {
464
            return;
465
        }
466
467
        $grid = $this;
468
469
        $column = new Column(Column::SELECT_COLUMN_NAME, ' ');
470
        $column->setGrid($this);
471
472
        $column->display(function ($value) use ($grid, $column) {
473
            $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...
474
475
            return $actions->display();
476
        });
477
478
        $this->columns->prepend($column);
479
    }
480
481
    /**
482
     * Build the grid.
483
     *
484
     * @return void
485
     */
486
    public function build()
487
    {
488
        if ($this->builded) {
489
            return;
490
        }
491
492
        $data = $this->processFilter();
493
494
        $this->prependRowSelectorColumn();
495
        $this->appendActionsColumn();
496
497
        Column::setOriginalGridData($data);
498
499
        $this->columns->map(function (Column $column) use (&$data) {
500
            $data = $column->fill($data);
501
502
            $this->columnNames[] = $column->getName();
503
        });
504
505
        $this->buildRows($data);
506
507
        $this->builded = true;
508
    }
509
510
    /**
511
     * Disable grid filter.
512
     *
513
     * @return $this
514
     */
515
    public function disableFilter()
516
    {
517
        $this->option('useFilter', false);
518
519
        return $this;
520
    }
521
522
    /**
523
     * Get filter of Grid.
524
     *
525
     * @return Filter
526
     */
527
    public function getFilter()
528
    {
529
        return $this->filter;
530
    }
531
532
    /**
533
     * Process the grid filter.
534
     *
535
     * @return array
536
     */
537
    public function processFilter()
538
    {
539
        if ($this->builder) {
540
            call_user_func($this->builder, $this);
541
        }
542
543
        return $this->filter->execute();
544
    }
545
546
    /**
547
     * Set the grid filter.
548
     *
549
     * @param Closure $callback
550
     */
551
    public function filter(Closure $callback)
552
    {
553
        call_user_func($callback, $this->filter);
554
    }
555
556
    /**
557
     * Render the grid filter.
558
     *
559
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string
560
     */
561
    public function renderFilter()
562
    {
563
        if (!$this->option('useFilter')) {
564
            return '';
565
        }
566
567
        return $this->filter->render();
568
    }
569
570
    /**
571
     * Expand filter.
572
     *
573
     * @return $this
574
     */
575
    public function expandFilter()
576
    {
577
        $this->filter->expand();
578
579
        return $this;
580
    }
581
582
    /**
583
     * Build the grid rows.
584
     *
585
     * @param array $data
586
     *
587
     * @return void
588
     */
589
    protected function buildRows(array $data)
590
    {
591
        $this->rows = collect($data)->map(function ($model, $number) {
592
            return new Row($number, $model);
593
        });
594
595
        if ($this->rowsCallback) {
596
            $this->rows->map($this->rowsCallback);
597
        }
598
    }
599
600
    /**
601
     * Set grid row callback function.
602
     *
603
     * @param Closure $callable
604
     *
605
     * @return Collection|null
606
     */
607
    public function rows(Closure $callable = null)
608
    {
609
        if (is_null($callable)) {
610
            return $this->rows;
611
        }
612
613
        $this->rowsCallback = $callable;
614
    }
615
616
    /**
617
     * Setup grid tools.
618
     *
619
     * @param Closure $callback
620
     *
621
     * @return void
622
     */
623
    public function tools(Closure $callback)
624
    {
625
        call_user_func($callback, $this->tools);
626
    }
627
628
    /**
629
     * Render custom tools.
630
     *
631
     * @return string
632
     */
633
    public function renderHeaderTools()
634
    {
635
        return $this->tools->render();
636
    }
637
638
    /**
639
     * Set exporter driver for Grid to export.
640
     *
641
     * @param $exporter
642
     *
643
     * @return $this
644
     */
645
    public function exporter($exporter)
646
    {
647
        $this->exporter = $exporter;
648
649
        return $this;
650
    }
651
652
    /**
653
     * Get the export url.
654
     *
655
     * @param int  $scope
656
     * @param null $args
657
     *
658
     * @return string
659
     */
660
    public function getExportUrl($scope = 1, $args = null)
661
    {
662
        $input = array_merge(Input::all(), Exporter::formatExportQuery($scope, $args));
663
664
        if ($constraints = $this->model()->getConstraints()) {
665
            $input = array_merge($input, $constraints);
666
        }
667
668
        return $this->resource().'?'.http_build_query($input);
669
    }
670
671
    /**
672
     * Get create url.
673
     *
674
     * @return string
675
     */
676
    public function getCreateUrl()
677
    {
678
        $queryString = '';
679
680
        if ($constraints = $this->model()->getConstraints()) {
681
            $queryString = http_build_query($constraints);
682
        }
683
684
        return sprintf('%s/create%s',
685
            $this->resource(),
686
            $queryString ? ('?'.$queryString) : ''
687
        );
688
    }
689
690
    /**
691
     * If grid allows export.s.
692
     *
693
     * @return bool
694
     */
695
    public function allowExport()
696
    {
697
        return $this->option('useExporter');
698
    }
699
700
    /**
701
     * Disable export.
702
     *
703
     * @return $this
704
     */
705
    public function disableExport()
706
    {
707
        return $this->option('useExporter', false);
708
    }
709
710
    /**
711
     * Render export button.
712
     *
713
     * @return string
714
     */
715
    public function renderExportButton()
716
    {
717
        return (new Tools\ExportButton($this))->render();
718
    }
719
720
    /**
721
     * Alias for method `disableCreateButton`.
722
     *
723
     * @return $this
724
     *
725
     * @deprecated
726
     */
727
    public function disableCreation()
728
    {
729
        return $this->disableCreateButton();
730
    }
731
732
    /**
733
     * Remove create button on grid.
734
     *
735
     * @return $this
736
     */
737
    public function disableCreateButton()
738
    {
739
        return $this->option('allowCreate', false);
740
    }
741
742
    /**
743
     * If allow creation.
744
     *
745
     * @return bool
746
     */
747
    public function allowCreation()
748
    {
749
        return $this->option('allowCreate');
750
    }
751
752
    /**
753
     * Render create button for grid.
754
     *
755
     * @return string
756
     */
757
    public function renderCreateButton()
758
    {
759
        return (new Tools\CreateButton($this))->render();
760
    }
761
762
    /**
763
     * Set grid footer.
764
     *
765
     * @param Closure|null $closure
766
     *
767
     * @return $this|Tools\Footer
768
     */
769
    public function footer(Closure $closure = null)
770
    {
771
        if (!$closure) {
772
            return $this->footer;
773
        }
774
775
        $this->footer = $closure;
0 ignored issues
show
Documentation Bug introduced by
It seems like $closure of type object<Closure> is incompatible with the declared type object<Encore\Admin\Grid\Tools\Footer> of property $footer.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
776
777
        return $this;
778
    }
779
780
    /**
781
     * Render grid footer.
782
     *
783
     * @return Tools\Footer|string
784
     */
785
    public function renderFooter()
786
    {
787
        if (!$this->footer) {
788
            return '';
789
        }
790
791
        return new Tools\Footer($this);
792
    }
793
794
    /**
795
     * Get current resource uri.
796
     *
797
     * @param string $path
798
     *
799
     * @return string
800
     */
801
    public function resource($path = null)
802
    {
803
        if (!empty($path)) {
804
            $this->resourcePath = $path;
805
806
            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...
807
        }
808
809
        if (!empty($this->resourcePath)) {
810
            return $this->resourcePath;
811
        }
812
813
        return app('request')->getPathInfo();
814
    }
815
816
    /**
817
     * Handle get mutator column for grid.
818
     *
819
     * @param string $method
820
     * @param string $label
821
     *
822
     * @return bool|Column
823
     */
824
    protected function handleGetMutatorColumn($method, $label)
825
    {
826
        if ($this->model()->eloquent()->hasGetMutator($method)) {
827
            return $this->addColumn($method, $label);
828
        }
829
830
        return false;
831
    }
832
833
    /**
834
     * Handle relation column for grid.
835
     *
836
     * @param string $method
837
     * @param string $label
838
     *
839
     * @return bool|Column
840
     */
841
    protected function handleRelationColumn($method, $label)
842
    {
843
        $model = $this->model()->eloquent();
844
845
        if (!method_exists($model, $method)) {
846
            return false;
847
        }
848
849
        if (!($relation = $model->$method()) instanceof Relations\Relation) {
850
            return false;
851
        }
852
853
        if ($relation instanceof Relations\HasOne || $relation instanceof Relations\BelongsTo) {
854
            $this->model()->with($method);
855
856
            return $this->addColumn($method, $label)->setRelation(snake_case($method));
857
        }
858
859
        if ($relation instanceof Relations\HasMany
860
            || $relation instanceof Relations\BelongsToMany
861
            || $relation instanceof Relations\MorphToMany
862
        ) {
863
            $this->model()->with($method);
864
865
            return $this->addColumn(snake_case($method), $label);
866
        }
867
868
        return false;
869
    }
870
871
    /**
872
     * Dynamically add columns to the grid view.
873
     *
874
     * @param $method
875
     * @param $arguments
876
     *
877
     * @return Column
878
     */
879
    public function __call($method, $arguments)
880
    {
881
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
882
883
        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...
884
            return $this->addColumn($method, $label);
885
        }
886
887
        if ($column = $this->handleGetMutatorColumn($method, $label)) {
888
            return $column;
889
        }
890
891
        if ($column = $this->handleRelationColumn($method, $label)) {
892
            return $column;
893
        }
894
895
        return $this->addColumn($method, $label);
896
    }
897
898
    /**
899
     * Register column displayers.
900
     *
901
     * @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...
902
     */
903
    public static function registerColumnDisplayer()
904
    {
905
        $map = [
906
            'editable'    => Displayers\Editable::class,
907
            'switch'      => Displayers\SwitchDisplay::class,
908
            'switchGroup' => Displayers\SwitchGroup::class,
909
            'select'      => Displayers\Select::class,
910
            'image'       => Displayers\Image::class,
911
            'label'       => Displayers\Label::class,
912
            'button'      => Displayers\Button::class,
913
            'link'        => Displayers\Link::class,
914
            'badge'       => Displayers\Badge::class,
915
            'progressBar' => Displayers\ProgressBar::class,
916
            'radio'       => Displayers\Radio::class,
917
            'checkbox'    => Displayers\Checkbox::class,
918
            'orderable'   => Displayers\Orderable::class,
919
            'table'       => Displayers\Table::class,
920
        ];
921
922
        foreach ($map as $abstract => $class) {
923
            Column::extend($abstract, $class);
924
        }
925
    }
926
927
    /**
928
     * Add variables to grid view.
929
     *
930
     * @param array $variables
931
     *
932
     * @return $this
933
     */
934
    public function with($variables = [])
935
    {
936
        $this->variables = $variables;
937
938
        return $this;
939
    }
940
941
    /**
942
     * Get all variables will used in grid view.
943
     *
944
     * @return array
945
     */
946
    protected function variables()
947
    {
948
        $this->variables['grid'] = $this;
949
950
        return $this->variables;
951
    }
952
953
    /**
954
     * Set a view to render.
955
     *
956
     * @param string $view
957
     * @param array  $variables
958
     */
959
    public function setView($view, $variables = [])
960
    {
961
        if (!empty($variables)) {
962
            $this->with($variables);
963
        }
964
965
        $this->view = $view;
966
    }
967
968
    /**
969
     * Set grid title.
970
     *
971
     * @param string $title
972
     *
973
     * @return $this
974
     */
975
    public function setTitle($title)
976
    {
977
        $this->variables['title'] = $title;
978
979
        return $this;
980
    }
981
982
    /**
983
     * Set relation for grid.
984
     *
985
     * @param Relations\Relation $relation
986
     *
987
     * @return $this
988
     */
989
    public function setRelation(Relations\Relation $relation)
990
    {
991
        $this->model()->setRelation($relation);
992
993
        return $this;
994
    }
995
996
    /**
997
     * Set resource path for grid.
998
     *
999
     * @param string $path
1000
     * @return $this
1001
     */
1002
    public function setResource($path)
1003
    {
1004
        $this->resourcePath = $path;
1005
1006
        return $this;
1007
    }
1008
1009
    /**
1010
     * Get the string contents of the grid view.
1011
     *
1012
     * @return string
1013
     */
1014
    public function render()
1015
    {
1016
        try {
1017
            $this->build();
1018
        } catch (\Exception $e) {
1019
            return Handler::renderException($e);
1020
        }
1021
1022
        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...
1023
    }
1024
}
1025