Completed
Push — master ( c6a049...7f7ede )
by Song
03:29
created

Grid::footer()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 10
rs 9.9332
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\Concerns;
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 Illuminate\Support\Str;
20
use Jenssegers\Mongodb\Eloquent\Model as MongodbModel;
21
22
class Grid
23
{
24
    use Concerns\HasElementNames,
25
        Concerns\HasHeader,
26
        Concerns\HasFooter,
27
        Concerns\HasFilter,
28
        Concerns\HasTools,
29
        Concerns\HasTotalRow;
30
31
    /**
32
     * The grid data model instance.
33
     *
34
     * @var \Encore\Admin\Grid\Model
35
     */
36
    protected $model;
37
38
    /**
39
     * Collection of all grid columns.
40
     *
41
     * @var \Illuminate\Support\Collection
42
     */
43
    protected $columns;
44
45
    /**
46
     * Collection of all data rows.
47
     *
48
     * @var \Illuminate\Support\Collection
49
     */
50
    protected $rows;
51
52
    /**
53
     * Rows callable fucntion.
54
     *
55
     * @var \Closure
56
     */
57
    protected $rowsCallback;
58
59
    /**
60
     * All column names of the grid.
61
     *
62
     * @var array
63
     */
64
    public $columnNames = [];
65
66
    /**
67
     * Grid builder.
68
     *
69
     * @var \Closure
70
     */
71
    protected $builder;
72
73
    /**
74
     * Mark if the grid is builded.
75
     *
76
     * @var bool
77
     */
78
    protected $builded = false;
79
80
    /**
81
     * All variables in grid view.
82
     *
83
     * @var array
84
     */
85
    protected $variables = [];
86
87
    /**
88
     * Resource path of the grid.
89
     *
90
     * @var
91
     */
92
    protected $resourcePath;
93
94
    /**
95
     * Default primary key name.
96
     *
97
     * @var string
98
     */
99
    protected $keyName = 'id';
100
101
    /**
102
     * Export driver.
103
     *
104
     * @var string
105
     */
106
    protected $exporter;
107
108
    /**
109
     * View for grid to render.
110
     *
111
     * @var string
112
     */
113
    protected $view = 'admin::grid.table';
114
115
    /**
116
     * Per-page options.
117
     *
118
     * @var array
119
     */
120
    public $perPages = [10, 20, 30, 50, 100];
121
122
    /**
123
     * Default items count per-page.
124
     *
125
     * @var int
126
     */
127
    public $perPage = 20;
128
129
    /**
130
     * Callback for grid actions.
131
     *
132
     * @var Closure
133
     */
134
    protected $actionsCallback;
135
136
    /**
137
     * Actions column display class.
138
     *
139
     * @var string
140
     */
141
    protected $actionsClass = Displayers\Actions::class;
142
143
    /**
144
     * Options for grid.
145
     *
146
     * @var array
147
     */
148
    protected $options = [
149
        'show_pagination'        => true,
150
        'show_tools'             => true,
151
        'show_filter'            => true,
152
        'show_exporter'          => true,
153
        'show_actions'           => true,
154
        'show_row_selector'      => true,
155
        'show_create_btn'        => true,
156
        'show_column_selector'   => true,
157
    ];
158
159
    /**
160
     * @var string
161
     */
162
    public $tableID;
163
164
    /**
165
     * Initialization closure array.
166
     *
167
     * @var []Closure
168
     */
169
    protected static $initCallbacks = [];
170
171
    /**
172
     * Create a new grid instance.
173
     *
174
     * @param Eloquent $model
175
     * @param Closure  $builder
176
     */
177
    public function __construct(Eloquent $model, Closure $builder = null)
178
    {
179
        $this->keyName = $model->getKeyName();
180
        $this->model = new Model($model);
181
        $this->columns = new Collection();
182
        $this->rows = new Collection();
183
        $this->builder = $builder;
184
        $this->tableID = uniqid('grid-table');
185
186
        $this->model()->setGrid($this);
187
188
        $this->setupTools();
189
        $this->setupFilter();
190
191
        $this->handleExportRequest();
192
193
        $this->callInitCallbacks();
194
    }
195
196
    /**
197
     * Initialize with user pre-defined default disables and exporter, etc.
198
     *
199
     * @param Closure $callback
200
     */
201
    public static function init(Closure $callback = null)
202
    {
203
        static::$initCallbacks[] = $callback;
204
    }
205
206
    /**
207
     * Call the initialization closure array in sequence.
208
     */
209
    protected function callInitCallbacks()
210
    {
211
        if (empty(static::$initCallbacks)) {
212
            return;
213
        }
214
215
        foreach (static::$initCallbacks as $callback) {
216
            call_user_func($callback, $this);
217
        }
218
    }
219
220
    /**
221
     * Handle export request.
222
     *
223
     * @param bool $forceExport
224
     */
225
    protected function handleExportRequest($forceExport = false)
226
    {
227
        if (!$scope = request(Exporter::$queryName)) {
228
            return;
229
        }
230
231
        // clear output buffer.
232
        if (ob_get_length()) {
233
            ob_end_clean();
234
        }
235
236
        $this->model()->usePaginate(false);
237
238
        if ($this->builder) {
239
            call_user_func($this->builder, $this);
240
241
            $this->getExporter($scope)->export();
242
        }
243
244
        if ($forceExport) {
245
            $this->getExporter($scope)->export();
246
        }
247
    }
248
249
    /**
250
     * @param string $scope
251
     *
252
     * @return AbstractExporter
253
     */
254
    protected function getExporter($scope)
255
    {
256
        return (new Exporter($this))->resolve($this->exporter)->withScope($scope);
257
    }
258
259
    /**
260
     * Get or set option for grid.
261
     *
262
     * @param string $key
263
     * @param mixed  $value
264
     *
265
     * @return $this|mixed
266
     */
267
    public function option($key, $value = null)
268
    {
269
        if (is_null($value)) {
270
            return $this->options[$key];
271
        }
272
273
        $this->options[$key] = $value;
274
275
        return $this;
276
    }
277
278
    /**
279
     * Get primary key name of model.
280
     *
281
     * @return string
282
     */
283
    public function getKeyName()
284
    {
285
        return $this->keyName ?: 'id';
286
    }
287
288
    /**
289
     * Add column to Grid.
290
     *
291
     * @param string $name
292
     * @param string $label
293
     *
294
     * @return Column
295
     */
296
    public function column($name, $label = '')
297
    {
298
        $relationName = $relationColumn = '';
299
300
        if (strpos($name, '.') !== false) {
301
            list($relationName, $relationColumn) = explode('.', $name);
302
303
            $relation = $this->model()->eloquent()->$relationName();
304
305
            $label = empty($label) ? ucfirst($relationColumn) : $label;
306
307
            $name = Str::snake($relationName).'.'.$relationColumn;
308
        }
309
310
        $column = $this->addColumn($name, $label);
311
312
        if (isset($relation) && $relation instanceof Relations\Relation) {
313
            $this->model()->with($relationName);
314
            $column->setRelation($relationName, $relationColumn);
315
        }
316
317
        return $column;
318
    }
319
320
    /**
321
     * Batch add column to grid.
322
     *
323
     * @example
324
     * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
325
     * 2.$grid->columns('name', 'email' ...)
326
     *
327
     * @param array $columns
328
     *
329
     * @return Collection|null
330
     */
331
    public function columns($columns = [])
332
    {
333
        if (func_num_args() == 0) {
334
            return $this->columns;
335
        }
336
337
        if (func_num_args() == 1 && is_array($columns)) {
338
            foreach ($columns as $column => $label) {
339
                $this->column($column, $label);
340
            }
341
342
            return;
343
        }
344
345
        foreach (func_get_args() as $column) {
346
            $this->column($column);
347
        }
348
    }
349
350
    /**
351
     * Get all visible column instances.
352
     *
353
     * @return Collection|static
354
     */
355 View Code Duplication
    public function visibleColumns()
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...
356
    {
357
        $visible = array_filter(explode(',', request(Tools\ColumnSelector::SELECT_COLUMN_NAME)));
358
359
        if (empty($visible)) {
360
            return $this->columns;
361
        }
362
363
        array_push($visible, '__row_selector__', '__actions__');
364
365
        return $this->columns->filter(function (Column $column) use ($visible) {
366
            return in_array($column->getName(), $visible);
367
        });
368
    }
369
370
    /**
371
     * Get all visible column names.
372
     *
373
     * @return array|static
374
     */
375 View Code Duplication
    public function visibleColumnNames()
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...
376
    {
377
        $visible = array_filter(explode(',', request(Tools\ColumnSelector::SELECT_COLUMN_NAME)));
378
379
        if (empty($visible)) {
380
            return $this->columnNames;
381
        }
382
383
        array_push($visible, '__row_selector__', '__actions__');
384
385
        return collect($this->columnNames)->filter(function ($column) use ($visible) {
386
            return in_array($column, $visible);
387
        });
388
    }
389
390
    /**
391
     * Add column to grid.
392
     *
393
     * @param string $column
394
     * @param string $label
395
     *
396
     * @return Column
397
     */
398 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...
399
    {
400
        $column = new Column($column, $label);
401
        $column->setGrid($this);
402
403
        return tap($column, function ($value) {
404
            $this->columns->push($value);
405
        });
406
    }
407
408
    /**
409
     * Prepend column to grid.
410
     *
411
     * @param string $column
412
     * @param string $label
413
     *
414
     * @return Column
415
     */
416 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...
417
    {
418
        $column = new Column($column, $label);
419
        $column->setGrid($this);
420
421
        return tap($column, function ($value) {
422
            $this->columns->prepend($value);
423
        });
424
    }
425
426
    /**
427
     * Get Grid model.
428
     *
429
     * @return Model
430
     */
431
    public function model()
432
    {
433
        return $this->model;
434
    }
435
436
    /**
437
     * Paginate the grid.
438
     *
439
     * @param int $perPage
440
     *
441
     * @return void
442
     */
443
    public function paginate($perPage = 20)
444
    {
445
        $this->perPage = $perPage;
446
447
        $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...
448
    }
449
450
    /**
451
     * Get the grid paginator.
452
     *
453
     * @return mixed
454
     */
455
    public function paginator()
456
    {
457
        return new Tools\Paginator($this);
458
    }
459
460
    /**
461
     * Disable grid pagination.
462
     *
463
     * @return $this
464
     */
465
    public function disablePagination(bool $disable = true)
466
    {
467
        $this->model->usePaginate(!$disable);
468
469
        return $this->option('show_pagination', !$disable);
470
    }
471
472
    /**
473
     * If this grid use pagination.
474
     *
475
     * @return bool
476
     */
477
    public function showPagination()
478
    {
479
        return $this->option('show_pagination');
480
    }
481
482
    /**
483
     * Set per-page options.
484
     *
485
     * @param array $perPages
486
     */
487
    public function perPages(array $perPages)
488
    {
489
        $this->perPages = $perPages;
490
    }
491
492
    /**
493
     * Disable all actions.
494
     *
495
     * @return $this
496
     */
497
    public function disableActions(bool $disable = true)
498
    {
499
        return $this->option('show_actions', !$disable);
500
    }
501
502
    /**
503
     * Set grid action callback.
504
     *
505
     * @param Closure|string $actions
506
     *
507
     * @return $this
508
     */
509
    public function actions($actions)
510
    {
511
        if ($actions instanceof Closure) {
512
            $this->actionsCallback = $actions;
513
        }
514
515
        if (is_string($actions) && is_subclass_of($actions, Displayers\Actions::class)) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if \Encore\Admin\Grid\Displayers\Actions::class can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
516
            $this->actionsClass = $actions;
517
        }
518
519
        return $this;
520
    }
521
522
    /**
523
     * Add `actions` column for grid.
524
     *
525
     * @return void
526
     */
527
    protected function appendActionsColumn()
528
    {
529
        if (!$this->option('show_actions')) {
530
            return;
531
        }
532
533
        $this->addColumn('__actions__', trans('admin.action'))
534
            ->displayUsing($this->actionsClass, [$this->actionsCallback]);
535
    }
536
537
    /**
538
     * Disable row selector.
539
     *
540
     * @return Grid|mixed
541
     */
542
    public function disableRowSelector(bool $disable = true)
543
    {
544
        $this->tools->disableBatchActions($disable);
545
546
        return $this->option('show_row_selector', !$disable);
547
    }
548
549
    /**
550
     * Prepend checkbox column for grid.
551
     *
552
     * @return void
553
     */
554
    protected function prependRowSelectorColumn()
555
    {
556
        if (!$this->option('show_row_selector')) {
557
            return;
558
        }
559
560
        $this->prependColumn(Column::SELECT_COLUMN_NAME, ' ')
561
            ->displayUsing(Displayers\RowSelector::class);
562
    }
563
564
    /**
565
     * Build the grid.
566
     *
567
     * @return void
568
     */
569
    public function build()
570
    {
571
        if ($this->builded) {
572
            return;
573
        }
574
575
        $collection = $this->processFilter(false);
576
577
        $data = $collection->toArray();
578
579
        $this->prependRowSelectorColumn();
580
        $this->appendActionsColumn();
581
582
        Column::setOriginalGridModels($collection);
583
584
        $this->columns->map(function (Column $column) use (&$data) {
585
            $data = $column->fill($data);
586
587
            $this->columnNames[] = $column->getName();
588
        });
589
590
        $this->buildRows($data);
591
592
        $this->builded = true;
593
    }
594
595
    /**
596
     * Build the grid rows.
597
     *
598
     * @param array $data
599
     *
600
     * @return void
601
     */
602
    protected function buildRows(array $data)
603
    {
604
        $this->rows = collect($data)->map(function ($model, $number) {
605
            return new Row($number, $model);
606
        });
607
608
        if ($this->rowsCallback) {
609
            $this->rows->map($this->rowsCallback);
610
        }
611
    }
612
613
    /**
614
     * Set grid row callback function.
615
     *
616
     * @param Closure $callable
617
     *
618
     * @return Collection|null
619
     */
620
    public function rows(Closure $callable = null)
621
    {
622
        if (is_null($callable)) {
623
            return $this->rows;
624
        }
625
626
        $this->rowsCallback = $callable;
627
    }
628
629
    /**
630
     * Set exporter driver for Grid to export.
631
     *
632
     * @param $exporter
633
     *
634
     * @return $this
635
     */
636
    public function exporter($exporter)
637
    {
638
        $this->exporter = $exporter;
639
640
        return $this;
641
    }
642
643
    /**
644
     * Get the export url.
645
     *
646
     * @param int  $scope
647
     * @param null $args
648
     *
649
     * @return string
650
     */
651
    public function getExportUrl($scope = 1, $args = null)
652
    {
653
        $input = array_merge(Input::all(), Exporter::formatExportQuery($scope, $args));
654
655
        if ($constraints = $this->model()->getConstraints()) {
656
            $input = array_merge($input, $constraints);
657
        }
658
659
        return $this->resource().'?'.http_build_query($input);
660
    }
661
662
    /**
663
     * Get create url.
664
     *
665
     * @return string
666
     */
667
    public function getCreateUrl()
668
    {
669
        $queryString = '';
670
671
        if ($constraints = $this->model()->getConstraints()) {
672
            $queryString = http_build_query($constraints);
673
        }
674
675
        return sprintf('%s/create%s',
676
            $this->resource(),
677
            $queryString ? ('?'.$queryString) : ''
678
        );
679
    }
680
681
    /**
682
     * If grid show export btn.
683
     *
684
     * @return bool
685
     */
686
    public function showExportBtn()
687
    {
688
        return $this->option('show_exporter');
689
    }
690
691
    /**
692
     * Disable export.
693
     *
694
     * @return $this
695
     */
696
    public function disableExport(bool $disable = true)
697
    {
698
        return $this->option('show_exporter', !$disable);
699
    }
700
701
    /**
702
     * Render export button.
703
     *
704
     * @return string
705
     */
706
    public function renderExportButton()
707
    {
708
        return (new Tools\ExportButton($this))->render();
709
    }
710
711
    /**
712
     * Alias for method `disableCreateButton`.
713
     *
714
     * @return $this
715
     *
716
     * @deprecated
717
     */
718
    public function disableCreation()
719
    {
720
        return $this->disableCreateButton();
721
    }
722
723
    /**
724
     * Remove create button on grid.
725
     *
726
     * @return $this
727
     */
728
    public function disableCreateButton(bool $disable = true)
729
    {
730
        return $this->option('show_create_btn', !$disable);
731
    }
732
733
    /**
734
     * If allow creation.
735
     *
736
     * @return bool
737
     */
738
    public function showCreateBtn()
739
    {
740
        return $this->option('show_create_btn');
741
    }
742
743
    /**
744
     * Render create button for grid.
745
     *
746
     * @return string
747
     */
748
    public function renderCreateButton()
749
    {
750
        return (new Tools\CreateButton($this))->render();
751
    }
752
753
    /**
754
     * Remove column selector on grid.
755
     *
756
     * @param bool $disable
757
     *
758
     * @return Grid|mixed
759
     */
760
    public function disableColumnSelector(bool $disable = true)
761
    {
762
        return $this->option('show_column_selector', !$disable);
763
    }
764
765
    /**
766
     * @return bool
767
     */
768
    public function showColumnSelector()
769
    {
770
        return $this->option('show_column_selector');
771
    }
772
773
    /**
774
     * @return string
775
     */
776
    public function renderColumnSelector()
777
    {
778
        return (new Grid\Tools\ColumnSelector($this))->render();
779
    }
780
781
    /**
782
     * Get current resource uri.
783
     *
784
     * @param string $path
785
     *
786
     * @return string
787
     */
788
    public function resource($path = null)
789
    {
790
        if (!empty($path)) {
791
            $this->resourcePath = $path;
792
793
            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...
794
        }
795
796
        if (!empty($this->resourcePath)) {
797
            return $this->resourcePath;
798
        }
799
800
        return app('request')->getPathInfo();
801
    }
802
803
    /**
804
     * Handle get mutator column for grid.
805
     *
806
     * @param string $method
807
     * @param string $label
808
     *
809
     * @return bool|Column
810
     */
811
    protected function handleGetMutatorColumn($method, $label)
812
    {
813
        if ($this->model()->eloquent()->hasGetMutator($method)) {
814
            return $this->addColumn($method, $label);
815
        }
816
817
        return false;
818
    }
819
820
    /**
821
     * Handle relation column for grid.
822
     *
823
     * @param string $method
824
     * @param string $label
825
     *
826
     * @return bool|Column
827
     */
828
    protected function handleRelationColumn($method, $label)
829
    {
830
        $model = $this->model()->eloquent();
831
832
        if (!method_exists($model, $method)) {
833
            return false;
834
        }
835
836
        if (!($relation = $model->$method()) instanceof Relations\Relation) {
837
            return false;
838
        }
839
840
        if ($relation instanceof Relations\HasOne ||
841
            $relation instanceof Relations\BelongsTo ||
842
            $relation instanceof Relations\MorphOne
843
        ) {
844
            $this->model()->with($method);
845
846
            return $this->addColumn($method, $label)->setRelation(Str::snake($method));
847
        }
848
849
        if ($relation instanceof Relations\HasMany
850
            || $relation instanceof Relations\BelongsToMany
851
            || $relation instanceof Relations\MorphToMany
852
        ) {
853
            $this->model()->with($method);
854
855
            return $this->addColumn(Str::snake($method), $label);
856
        }
857
858
        return false;
859
    }
860
861
    /**
862
     * Dynamically add columns to the grid view.
863
     *
864
     * @param $method
865
     * @param $arguments
866
     *
867
     * @return Column
868
     */
869
    public function __call($method, $arguments)
870
    {
871
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
872
873
        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...
874
            return $this->addColumn($method, $label);
875
        }
876
877
        if ($column = $this->handleGetMutatorColumn($method, $label)) {
878
            return $column;
879
        }
880
881
        if ($column = $this->handleRelationColumn($method, $label)) {
882
            return $column;
883
        }
884
885
        return $this->addColumn($method, $label);
886
    }
887
888
    /**
889
     * Register column displayers.
890
     *
891
     * @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...
892
     */
893
    public static function registerColumnDisplayer()
894
    {
895
        $map = [
896
            'editable'    => Displayers\Editable::class,
897
            'switch'      => Displayers\SwitchDisplay::class,
898
            'switchGroup' => Displayers\SwitchGroup::class,
899
            'select'      => Displayers\Select::class,
900
            'image'       => Displayers\Image::class,
901
            'label'       => Displayers\Label::class,
902
            'button'      => Displayers\Button::class,
903
            'link'        => Displayers\Link::class,
904
            'badge'       => Displayers\Badge::class,
905
            'progressBar' => Displayers\ProgressBar::class,
906
            'radio'       => Displayers\Radio::class,
907
            'checkbox'    => Displayers\Checkbox::class,
908
            'orderable'   => Displayers\Orderable::class,
909
            'table'       => Displayers\Table::class,
910
            'expand'      => Displayers\Expand::class,
911
            'modal'       => Displayers\Modal::class,
912
        ];
913
914
        foreach ($map as $abstract => $class) {
915
            Column::extend($abstract, $class);
916
        }
917
    }
918
919
    /**
920
     * Add variables to grid view.
921
     *
922
     * @param array $variables
923
     *
924
     * @return $this
925
     */
926
    public function with($variables = [])
927
    {
928
        $this->variables = $variables;
929
930
        return $this;
931
    }
932
933
    /**
934
     * Get all variables will used in grid view.
935
     *
936
     * @return array
937
     */
938
    protected function variables()
939
    {
940
        $this->variables['grid'] = $this;
941
942
        return $this->variables;
943
    }
944
945
    /**
946
     * Set a view to render.
947
     *
948
     * @param string $view
949
     * @param array  $variables
950
     */
951
    public function setView($view, $variables = [])
952
    {
953
        if (!empty($variables)) {
954
            $this->with($variables);
955
        }
956
957
        $this->view = $view;
958
    }
959
960
    /**
961
     * Set grid title.
962
     *
963
     * @param string $title
964
     *
965
     * @return $this
966
     */
967
    public function setTitle($title)
968
    {
969
        $this->variables['title'] = $title;
970
971
        return $this;
972
    }
973
974
    /**
975
     * Set relation for grid.
976
     *
977
     * @param Relations\Relation $relation
978
     *
979
     * @return $this
980
     */
981
    public function setRelation(Relations\Relation $relation)
982
    {
983
        $this->model()->setRelation($relation);
984
985
        return $this;
986
    }
987
988
    /**
989
     * Set resource path for grid.
990
     *
991
     * @param string $path
992
     *
993
     * @return $this
994
     */
995
    public function setResource($path)
996
    {
997
        $this->resourcePath = $path;
998
999
        return $this;
1000
    }
1001
1002
    /**
1003
     * Get the string contents of the grid view.
1004
     *
1005
     * @return string
1006
     */
1007
    public function render()
1008
    {
1009
        $this->handleExportRequest(true);
1010
1011
        try {
1012
            $this->build();
1013
        } catch (\Exception $e) {
1014
            return Handler::renderException($e);
1015
        }
1016
1017
        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...
1018
    }
1019
}
1020