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