Completed
Push — master ( f06f95...cfadd2 )
by Song
03:17
created

Grid   F

Complexity

Total Complexity 81

Size/Duplication

Total Lines 932
Duplicated Lines 0 %

Coupling/Cohesion

Components 7
Dependencies 11

Importance

Changes 0
Metric Value
dl 0
loc 932
rs 1.263
c 0
b 0
f 0
wmc 81
lcom 7
cbo 11

46 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 1
A getKeyName() 0 4 2
B column() 0 21 5
B columns() 0 18 6
A addColumn() 0 7 1
A blank() 0 4 1
A model() 0 4 1
A paginate() 0 6 1
A paginator() 0 12 2
A build() 0 18 2
A processFilter() 0 6 1
A buildRows() 0 15 2
A rows() 0 8 2
A setupFilter() 0 4 1
A setupExporter() 0 8 2
A exportUrl() 0 7 1
A allowBatchDeletion() 0 4 1
A disableBatchDeletion() 0 6 1
A disableCreation() 0 6 1
A allowCreation() 0 4 1
A allowActions() 0 4 1
A disableActions() 0 6 1
A allowExport() 0 4 1
A disableExport() 0 6 1
A disableFilter() 0 6 1
A disablePagination() 0 8 1
A usePagination() 0 4 1
A disablePerPageSelector() 0 6 1
A usePerPageSelector() 0 4 1
A orderable() 0 6 1
A isOrderable() 0 4 1
A filter() 0 4 1
A renderFilter() 0 8 2
A perPages() 0 4 1
A perPageOptions() 0 19 2
A resource() 0 14 3
A handleTableColumn() 0 10 2
A handleGetMutatorColumn() 0 8 2
C handleRelationColumn() 0 26 8
B __call() 0 22 6
A with() 0 6 1
A variables() 0 6 1
A view() 0 8 2
A render() 0 12 2
B script() 0 77 1
A __toString() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like Grid often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Grid, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Encore\Admin;
4
5
use Closure;
6
use Encore\Admin\Exception\Handle;
7
use Encore\Admin\Facades\Admin as AdminManager;
8
use Encore\Admin\Grid\Column;
9
use Encore\Admin\Grid\Exporter;
10
use Encore\Admin\Grid\Filter;
11
use Encore\Admin\Grid\Model;
12
use Encore\Admin\Grid\Row;
13
use Encore\Admin\Pagination\AdminThreePresenter;
14
use Illuminate\Database\Eloquent\Model as Eloquent;
15
use Illuminate\Database\Eloquent\Relations\BelongsTo;
16
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
17
use Illuminate\Database\Eloquent\Relations\HasMany;
18
use Illuminate\Database\Eloquent\Relations\HasOne;
19
use Illuminate\Database\Eloquent\Relations\MorphToMany;
20
use Illuminate\Database\Eloquent\Relations\Relation;
21
use Illuminate\Support\Collection;
22
use Illuminate\Support\Facades\Input;
23
use Illuminate\Support\Facades\Schema;
24
use Jenssegers\Mongodb\Eloquent\Model as MongodbModel;
25
26
class Grid
27
{
28
    /**
29
     * The grid data model instance.
30
     *
31
     * @var \Encore\Admin\Grid\Model
32
     */
33
    protected $model;
34
35
    /**
36
     * Collection of all grid columns.
37
     *
38
     * @var \Illuminate\Support\Collection
39
     */
40
    protected $columns;
41
42
    /**
43
     * Collection of all data rows.
44
     *
45
     * @var \Illuminate\Support\Collection
46
     */
47
    protected $rows;
48
49
    /**
50
     * Rows callable fucntion.
51
     *
52
     * @var \Closure
53
     */
54
    protected $rowsCallback;
55
56
    /**
57
     * All column names of the grid.
58
     *
59
     * @var array
60
     */
61
    public $columnNames = [];
62
63
    /**
64
     * Grid builder.
65
     *
66
     * @var \Closure
67
     */
68
    protected $builder;
69
70
    /**
71
     * Mark if the grid is builded.
72
     *
73
     * @var bool
74
     */
75
    protected $builded = false;
76
77
    /**
78
     * All variables in grid view.
79
     *
80
     * @var array
81
     */
82
    protected $variables = [];
83
84
    /**
85
     * The grid Filter.
86
     *
87
     * @var \Encore\Admin\Grid\Filter
88
     */
89
    protected $filter;
90
91
    /**
92
     * Resource path of the grid.
93
     *
94
     * @var
95
     */
96
    protected $resourcePath;
97
98
    /**
99
     * Default primary key name.
100
     *
101
     * @var string
102
     */
103
    protected $keyName = 'id';
104
105
    /**
106
     * Allow batch deletion.
107
     *
108
     * @var bool
109
     */
110
    protected $allowBatchDeletion = true;
111
112
    /**
113
     * Allow creation.
114
     *
115
     * @var bool
116
     */
117
    protected $allowCreation = true;
118
119
    /**
120
     * Allow actions.
121
     *
122
     * @var bool
123
     */
124
    protected $allowActions = true;
125
126
    /**
127
     * Allow export data.
128
     *
129
     * @var bool
130
     */
131
    protected $allowExport = true;
132
133
    /**
134
     * If use grid filter.
135
     *
136
     * @var bool
137
     */
138
    protected $useFilter = true;
139
140
    /**
141
     * If grid use pagination.
142
     *
143
     * @var bool
144
     */
145
    protected $usePagination = true;
146
147
    /**
148
     * If grid use per-page selector.
149
     *
150
     * @var bool
151
     */
152
    protected $usePerPageSelector = true;
153
154
    /**
155
     * Is grid rows orderable.
156
     *
157
     * @var bool
158
     */
159
    protected $orderable = false;
160
161
    /**
162
     * @var Exporter
163
     */
164
    protected $exporter;
165
166
    /**
167
     * View for grid to render.
168
     *
169
     * @var string
170
     */
171
    protected $view = 'admin::grid.table';
172
173
    /**
174
     * Per-page options.
175
     *
176
     * @var array
177
     */
178
    protected $perPages = [10, 20, 30, 50, 100];
179
180
    /**
181
     * Default items count per-page.
182
     *
183
     * @var int
184
     */
185
    protected $perPage = 20;
186
187
    /**
188
     * Create a new grid instance.
189
     *
190
     * @param Eloquent $model
191
     * @param callable $builder
192
     */
193
    public function __construct(Eloquent $model, Closure $builder)
194
    {
195
        $this->keyName = $model->getKeyName();
196
        $this->model = new Model($model);
197
        $this->columns = new Collection();
198
        $this->rows = new Collection();
199
        $this->builder = $builder;
200
201
        $this->setupFilter();
202
        $this->setupExporter();
203
    }
204
205
    /**
206
     * Get primary key name of model.
207
     *
208
     * @return string
209
     */
210
    public function getKeyName()
211
    {
212
        return $this->keyName ?: 'id';
213
    }
214
215
    /**
216
     * Add column to Grid.
217
     *
218
     * @param string $name
219
     * @param string $label
220
     *
221
     * @return Column
222
     */
223
    public function column($name, $label = '')
224
    {
225
        $relationName = $relationColumn = '';
226
227
        if (strpos($name, '.') !== false) {
228
            list($relationName, $relationColumn) = explode('.', $name);
229
230
            $relation = $this->model()->eloquent()->$relationName();
231
232
            $label = empty($label) ? ucfirst($relationColumn) : $label;
233
        }
234
235
        $column = $this->addColumn($name, $label);
236
237
        if (isset($relation) && $relation instanceof Relation) {
238
            $this->model()->with($relationName);
0 ignored issues
show
Documentation Bug introduced by
The method with does not exist on object<Encore\Admin\Grid\Model>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
239
            $column->setRelation($relation, $relationColumn);
0 ignored issues
show
Unused Code introduced by
The call to Column::setRelation() has too many arguments starting with $relationColumn.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
240
        }
241
242
        return $column;
243
    }
244
245
    /**
246
     * Batch add column to grid.
247
     *
248
     * @example
249
     * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);
250
     * 2.$grid->columns('name', 'email' ...)
251
     *
252
     * @param array $columns
253
     *
254
     * @return Collection|void
255
     */
256
    public function columns($columns = [])
257
    {
258
        if (func_num_args() == 0) {
259
            return $this->columns;
260
        }
261
262
        if (func_num_args() == 1 && is_array($columns)) {
263
            foreach ($columns as $column => $label) {
264
                $this->column($column, $label);
265
            }
266
267
            return;
268
        }
269
270
        foreach (func_get_args() as $column) {
271
            $this->column($column);
272
        }
273
    }
274
275
    /**
276
     * Add column to grid.
277
     *
278
     * @param string $column
279
     * @param string $label
280
     *
281
     * @return Column
282
     */
283
    protected function addColumn($column = '', $label = '')
284
    {
285
        $column = new Column($column, $label);
286
        $column->setGrid($this);
287
288
        return $this->columns[] = $column;
289
    }
290
291
    /**
292
     * Add a blank column.
293
     *
294
     * @param $label
295
     *
296
     * @return Column
297
     */
298
    public function blank($label)
299
    {
300
        return $this->addColumn('blank', $label);
301
    }
302
303
    /**
304
     * Get Grid model.
305
     *
306
     * @return Model
307
     */
308
    public function model()
309
    {
310
        return $this->model;
311
    }
312
313
    /**
314
     * Paginate the grid.
315
     *
316
     * @param int $perPage
317
     *
318
     * @return void
319
     */
320
    public function paginate($perPage = 20)
321
    {
322
        $this->perPage = $perPage;
323
324
        $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...
325
    }
326
327
    /**
328
     * Get the grid paginator.
329
     *
330
     * @return mixed
331
     */
332
    public function paginator()
333
    {
334
        if (!$this->usePagination) {
335
            return '';
336
        }
337
338
        $query = Input::all();
339
340
        return $this->model()->eloquent()->appends($query)->render(
341
            new AdminThreePresenter($this->model()->eloquent())
0 ignored issues
show
Documentation introduced by
$this->model()->eloquent() is of type object<Illuminate\Database\Eloquent\Model>, but the function expects a object<Illuminate\Contracts\Pagination\Paginator>.

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...
342
        );
343
    }
344
345
    /**
346
     * Build the grid.
347
     *
348
     * @return void
349
     */
350
    public function build()
351
    {
352
        if ($this->builded) {
353
            return;
354
        }
355
356
        $data = $this->processFilter();
357
358
        $this->columns->map(function (Column $column) use (&$data) {
359
            $data = $column->fill($data);
360
361
            $this->columnNames[] = $column->getName();
362
        });
363
364
        $this->buildRows($data);
365
366
        $this->builded = true;
367
    }
368
369
    /**
370
     * Process the grid filter.
371
     *
372
     * @return array
373
     */
374
    public function processFilter()
375
    {
376
        call_user_func($this->builder, $this);
377
378
        return $this->filter->execute();
379
    }
380
381
    /**
382
     * Build the grid rows.
383
     *
384
     * @param array $data
385
     *
386
     * @return void
387
     */
388
    protected function buildRows(array $data)
389
    {
390
        $this->rows = collect($data)->map(function ($val, $key) {
391
            $row = new Row($key, $val);
392
393
            $row->setKeyName($this->keyName);
394
            $row->setPath($this->resource());
395
396
            return $row;
397
        });
398
399
        if ($this->rowsCallback) {
400
            $this->rows->map($this->rowsCallback);
401
        }
402
    }
403
404
    /**
405
     * Set grid row callback function.
406
     *
407
     * @param callable $callable
408
     *
409
     * @return Collection|void
410
     */
411
    public function rows(Closure $callable = null)
412
    {
413
        if (is_null($callable)) {
414
            return $this->rows;
415
        }
416
417
        $this->rowsCallback = $callable;
418
    }
419
420
    /**
421
     * Setup grid filter.
422
     *
423
     * @return void
424
     */
425
    protected function setupFilter()
426
    {
427
        $this->filter = new Filter($this, $this->model());
428
    }
429
430
    /**
431
     * Setup grid exporter.
432
     *
433
     * @return void
434
     */
435
    protected function setupExporter()
436
    {
437
        if (Input::has('_export')) {
438
            $exporter = new Exporter($this);
439
440
            $exporter->export();
441
        }
442
    }
443
444
    /**
445
     * Export url.
446
     *
447
     * @return string
448
     */
449
    public function exportUrl()
450
    {
451
        $query = $query = Input::all();
452
        $query['_export'] = true;
453
454
        return $this->resource().'?'.http_build_query($query);
455
    }
456
457
    /**
458
     * If allow batch delete.
459
     *
460
     * @return bool
461
     */
462
    public function allowBatchDeletion()
463
    {
464
        return $this->allowBatchDeletion;
465
    }
466
467
    /**
468
     * Disable batch deletion.
469
     *
470
     * @return $this
471
     */
472
    public function disableBatchDeletion()
473
    {
474
        $this->allowBatchDeletion = false;
475
476
        return $this;
477
    }
478
479
    /**
480
     * Disable creation.
481
     *
482
     * @return $this
483
     */
484
    public function disableCreation()
485
    {
486
        $this->allowCreation = false;
487
488
        return $this;
489
    }
490
491
    /**
492
     * If allow creation.
493
     *
494
     * @return bool
495
     */
496
    public function allowCreation()
497
    {
498
        return $this->allowCreation;
499
    }
500
501
    /**
502
     * If allow actions.
503
     *
504
     * @return bool
505
     */
506
    public function allowActions()
507
    {
508
        return $this->allowActions;
509
    }
510
511
    /**
512
     * Disable all actions.
513
     *
514
     * @return $this
515
     */
516
    public function disableActions()
517
    {
518
        $this->allowActions = false;
519
520
        return $this;
521
    }
522
523
    /**
524
     * If grid allows export.s.
525
     *
526
     * @return bool
527
     */
528
    public function allowExport()
529
    {
530
        return $this->allowExport;
531
    }
532
533
    /**
534
     * Disable export.
535
     *
536
     * @return $this
537
     */
538
    public function disableExport()
539
    {
540
        $this->allowExport = false;
541
542
        return $this;
543
    }
544
545
    /**
546
     * Disable grid filter.
547
     *
548
     * @return $this
549
     */
550
    public function disableFilter()
551
    {
552
        $this->useFilter = false;
553
554
        return $this;
555
    }
556
557
    /**
558
     * Disable grid pagination.
559
     *
560
     * @return $this
561
     */
562
    public function disablePagination()
563
    {
564
        $this->model->usePaginate(false);
565
566
        $this->usePagination = false;
567
568
        return $this;
569
    }
570
571
    /**
572
     * If this grid use pagination.
573
     *
574
     * @return bool
575
     */
576
    public function usePagination()
577
    {
578
        return $this->usePagination;
579
    }
580
581
    /**
582
     * Disable grid per-page selector.
583
     */
584
    public function disablePerPageSelector()
585
    {
586
        $this->usePerPageSelector = false;
587
588
        return $this;
589
    }
590
591
    /**
592
     * If this grid use per-page selector.
593
     *
594
     * @return bool
595
     */
596
    public function usePerPageSelector()
597
    {
598
        return $this->usePerPageSelector;
599
    }
600
601
    /**
602
     * Set grid as orderable.
603
     *
604
     * @return $this
605
     */
606
    public function orderable()
607
    {
608
        $this->orderable = true;
609
610
        return $this;
611
    }
612
613
    /**
614
     * Is the grid orderable.
615
     *
616
     * @return bool
617
     */
618
    public function isOrderable()
619
    {
620
        return $this->orderable;
621
    }
622
623
    /**
624
     * Set the grid filter.
625
     *
626
     * @param callable $callback
627
     */
628
    public function filter(Closure $callback)
629
    {
630
        call_user_func($callback, $this->filter);
631
    }
632
633
    /**
634
     * Render the grid filter.
635
     *
636
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
637
     */
638
    public function renderFilter()
639
    {
640
        if (!$this->useFilter) {
641
            return '';
642
        }
643
644
        return $this->filter->render();
645
    }
646
647
    /**
648
     * Set per-page options.
649
     *
650
     * @param array $perPages
651
     */
652
    public function perPages(array $perPages)
653
    {
654
        $this->perPages = $perPages;
655
    }
656
657
    /**
658
     * Generate per-page options.
659
     *
660
     * @return string
661
     */
662
    public function perPageOptions()
663
    {
664
        $perPage = (int) app('request')->input(
665
            $this->model->getPerPageName(),
666
            $this->perPage
667
        );
668
669
        return collect($this->perPages)
670
            ->push($this->perPage)
671
            ->push($perPage)
672
            ->unique()
673
            ->sort()
674
            ->map(function ($option) use ($perPage) {
675
                $selected = ($option == $perPage) ? 'selected' : '';
676
                $url = app('request')->fullUrlWithQuery([$this->model->getPerPageName() => $option]);
677
678
                return "<option value=\"$url\" $selected>$option</option>";
679
            })->implode("\r\n");
680
    }
681
682
    /**
683
     * Get current resource uri.
684
     *
685
     * @param string $path
686
     *
687
     * @return string
688
     */
689
    public function resource($path = null)
690
    {
691
        if (!empty($path)) {
692
            $this->resourcePath = $path;
693
694
            return $this;
695
        }
696
697
        if (!empty($this->resourcePath)) {
698
            return $this->resourcePath;
699
        }
700
701
        return app('router')->current()->getPath();
702
    }
703
704
    /**
705
     * Handle table column for grid.
706
     *
707
     * @param string $method
708
     * @param string $label
709
     *
710
     * @return bool|Column
711
     */
712
    protected function handleTableColumn($method, $label)
713
    {
714
        $connection = $this->model()->eloquent()->getConnectionName();
715
716
        if (Schema::connection($connection)->hasColumn($this->model()->getTable(), $method)) {
717
            return $this->addColumn($method, $label);
718
        }
719
720
        return false;
721
    }
722
723
    /**
724
     * Handle get mutator column for grid.
725
     *
726
     * @param string $method
727
     * @param string $label
728
     *
729
     * @return bool|Column
730
     */
731
    protected function handleGetMutatorColumn($method, $label)
732
    {
733
        if ($this->model()->eloquent()->hasGetMutator($method)) {
734
            return $this->addColumn($method, $label);
735
        }
736
737
        return false;
738
    }
739
740
    /**
741
     * Handle relation column for grid.
742
     *
743
     * @param string $method
744
     * @param string $label
745
     *
746
     * @return bool|Column
747
     */
748
    protected function handleRelationColumn($method, $label)
749
    {
750
        $model = $this->model()->eloquent();
751
752
        if (! method_exists($model, $method)) {
753
            return false;
754
        }
755
756
        if (! ($relation = $model->$method()) instanceof Relation) {
757
            return false;
758
        }
759
760
        if ($relation instanceof HasOne || $relation instanceof BelongsTo) {
761
            $this->model()->with($method);
0 ignored issues
show
Documentation Bug introduced by
The method with does not exist on object<Encore\Admin\Grid\Model>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
762
763
            return $this->addColumn($method, $label)->setRelation($method);
764
        }
765
766
        if ($relation instanceof HasMany || $relation instanceof BelongsToMany || $relation instanceof MorphToMany) {
767
            $this->model()->with($method);
0 ignored issues
show
Documentation Bug introduced by
The method with does not exist on object<Encore\Admin\Grid\Model>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
768
769
            return $this->addColumn($method, $label);
770
        }
771
772
        return false;
773
    }
774
775
    /**
776
     * Dynamically add columns to the grid view.
777
     *
778
     * @param $method
779
     * @param $arguments
780
     *
781
     * @return $this|Column
782
     */
783
    public function __call($method, $arguments)
784
    {
785
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);
786
787
        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...
788
            return $this->addColumn($method, $label);
789
        }
790
791
        if ($column = $this->handleTableColumn($method, $label)) {
792
            return $column;
793
        }
794
795
        if ($column = $this->handleGetMutatorColumn($method, $label)) {
796
            return $column;
797
        }
798
799
        if ($column = $this->handleRelationColumn($method, $label)) {
800
            return $column;
801
        }
802
803
        return $this->addColumn($method, $label);
804
    }
805
806
    /**
807
     * Add variables to grid view.
808
     *
809
     * @param array $variables
810
     *
811
     * @return $this
812
     */
813
    public function with($variables = [])
814
    {
815
        $this->variables = $variables;
816
817
        return $this;
818
    }
819
820
    /**
821
     * Get all variables will used in grid view.
822
     *
823
     * @return array
824
     */
825
    protected function variables()
826
    {
827
        $this->variables['grid'] = $this;
828
829
        return $this->variables;
830
    }
831
832
    /**
833
     * Set a view to render.
834
     *
835
     * @param string $view
836
     * @param array  $variables
837
     */
838
    public function view($view, $variables = [])
839
    {
840
        if (!empty($variables)) {
841
            $this->with($variables);
842
        }
843
844
        $this->view = $view;
845
    }
846
847
    /**
848
     * Get the string contents of the grid view.
849
     *
850
     * @return string
851
     */
852
    public function render()
853
    {
854
        try {
855
            $this->build();
856
        } catch (\Exception $e) {
857
            return with(new Handle($e))->render();
858
        }
859
860
        AdminManager::script($this->script());
861
862
        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...
863
    }
864
865
    /**
866
     * Js code for grid.
867
     *
868
     * @return string
869
     */
870
    public function script()
871
    {
872
        $path = app('router')->current()->getPath();
873
        $token = csrf_token();
874
        $confirm = trans('admin::lang.delete_confirm');
875
876
        return <<<EOT
877
878
$('.grid-select-all').change(function() {
879
    if (this.checked) {
880
        $('.grid-item').prop("checked", true);
881
    } else {
882
        $('.grid-item').prop("checked", false);
883
    }
884
});
885
886
$('.batch-delete').on('click', function() {
887
    var selected = [];
888
    $('.grid-item:checked').each(function(){
889
        selected.push($(this).data('id'));
890
    });
891
892
    if (selected.length == 0) {
893
        return;
894
    }
895
896
    if(confirm("{$confirm}")) {
897
        $.post('/{$path}/' + selected.join(), {_method:'delete','_token':'{$token}'}, function(data){
898
            $.pjax.reload('#pjax-container');
899
            noty({
900
                text: "<strong>Succeeded!</strong>",
901
                type:'success',
902
                timeout: 1000
903
            });
904
        });
905
    }
906
});
907
908
$('.grid-refresh').on('click', function() {
909
    $.pjax.reload('#pjax-container');
910
911
    noty({
912
        text: "<strong>Succeeded!</strong>",
913
        type:'success',
914
        timeout: 1000
915
    });
916
});
917
918
var grid_order = function(id, direction) {
919
    $.post('/{$path}/' + id, {_method:'PUT', _token:'{$token}', _orderable:direction}, function(data){
920
921
        if (data.status) {
922
            noty({
923
                text: "<strong>Succeeded!</strong>",
924
                type:'success',
925
                timeout: 1000
926
            });
927
928
            $.pjax.reload('#pjax-container');
929
        }
930
    });
931
}
932
933
$('.grid-order-up').on('click', function() {
934
    grid_order($(this).data('id'), 1);
935
});
936
937
$('.grid-order-down').on('click', function() {
938
    grid_order($(this).data('id'), 0);
939
});
940
941
$('.per-page').select2({minimumResultsForSearch: -1}).on("select2:select", function(e) {
942
    $.pjax({url: this.value, container: '#pjax-container'});
943
});
944
945
EOT;
946
    }
947
948
    /**
949
     * Get the string contents of the grid view.
950
     *
951
     * @return string
952
     */
953
    public function __toString()
954
    {
955
        return $this->render();
956
    }
957
}
958