Completed
Push — master ( f5a787...4b5e24 )
by Song
02:26
created

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