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\Form\Field; |
||
4 | |||
5 | use Encore\Admin\Admin; |
||
6 | use Encore\Admin\Form; |
||
7 | use Encore\Admin\Form\Field; |
||
8 | use Encore\Admin\Form\NestedForm; |
||
9 | use Illuminate\Database\Eloquent\Relations\HasMany as Relation; |
||
10 | use Illuminate\Database\Eloquent\Relations\MorphMany; |
||
11 | use Illuminate\Support\Arr; |
||
12 | use Illuminate\Support\Str; |
||
13 | |||
14 | /** |
||
15 | * Class HasMany. |
||
16 | */ |
||
17 | class HasMany extends Field |
||
18 | { |
||
19 | /** |
||
20 | * Relation name. |
||
21 | * |
||
22 | * @var string |
||
23 | */ |
||
24 | protected $relationName = ''; |
||
25 | |||
26 | /** |
||
27 | * Form builder. |
||
28 | * |
||
29 | * @var \Closure |
||
30 | */ |
||
31 | protected $builder = null; |
||
32 | |||
33 | /** |
||
34 | * Form data. |
||
35 | * |
||
36 | * @var array |
||
37 | */ |
||
38 | protected $value = []; |
||
39 | |||
40 | /** |
||
41 | * View Mode. |
||
42 | * |
||
43 | * Supports `default` and `tab` currently. |
||
44 | * |
||
45 | * @var string |
||
46 | */ |
||
47 | protected $viewMode = 'default'; |
||
48 | |||
49 | /** |
||
50 | * Available views for HasMany field. |
||
51 | * |
||
52 | * @var array |
||
53 | */ |
||
54 | protected $views = [ |
||
55 | 'default' => 'admin::form.hasmany', |
||
56 | 'tab' => 'admin::form.hasmanytab', |
||
57 | 'table' => 'admin::form.hasmanytable', |
||
58 | ]; |
||
59 | |||
60 | /** |
||
61 | * Options for template. |
||
62 | * |
||
63 | * @var array |
||
64 | */ |
||
65 | protected $options = [ |
||
66 | 'allowCreate' => true, |
||
67 | 'allowDelete' => true, |
||
68 | ]; |
||
69 | |||
70 | /** |
||
71 | * Distinct fields. |
||
72 | * |
||
73 | * @var array |
||
74 | */ |
||
75 | protected $distinctFields = []; |
||
76 | |||
77 | /** |
||
78 | * Create a new HasMany field instance. |
||
79 | * |
||
80 | * @param $relationName |
||
81 | * @param array $arguments |
||
82 | */ |
||
83 | View Code Duplication | public function __construct($relationName, $arguments = []) |
|
84 | { |
||
85 | $this->relationName = $relationName; |
||
86 | |||
87 | $this->column = $relationName; |
||
88 | |||
89 | if (count($arguments) == 1) { |
||
90 | $this->label = $this->formatLabel(); |
||
91 | $this->builder = $arguments[0]; |
||
92 | } |
||
93 | |||
94 | if (count($arguments) == 2) { |
||
95 | list($this->label, $this->builder) = $arguments; |
||
96 | } |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Get validator for this field. |
||
101 | * |
||
102 | * @param array $input |
||
103 | * |
||
104 | * @return bool|\Illuminate\Contracts\Validation\Validator |
||
105 | */ |
||
106 | public function getValidator(array $input) |
||
107 | { |
||
108 | if (!array_key_exists($this->column, $input)) { |
||
109 | return false; |
||
110 | } |
||
111 | |||
112 | $input = Arr::only($input, $this->column); |
||
113 | |||
114 | /** unset item that contains remove flag */ |
||
115 | foreach ($input[$this->column] as $key => $value) { |
||
116 | if ($value[NestedForm::REMOVE_FLAG_NAME]) { |
||
117 | unset($input[$this->column][$key]); |
||
118 | } |
||
119 | } |
||
120 | |||
121 | $form = $this->buildNestedForm($this->column, $this->builder); |
||
122 | |||
123 | $rules = $attributes = []; |
||
124 | |||
125 | /* @var Field $field */ |
||
126 | foreach ($form->fields() as $field) { |
||
127 | if (!$fieldRules = $field->getRules()) { |
||
128 | continue; |
||
129 | } |
||
130 | |||
131 | $column = $field->column(); |
||
132 | |||
133 | if (is_array($column)) { |
||
134 | foreach ($column as $key => $name) { |
||
135 | $rules[$name.$key] = $fieldRules; |
||
136 | } |
||
137 | |||
138 | $this->resetInputKey($input, $column); |
||
139 | } else { |
||
140 | $rules[$column] = $fieldRules; |
||
141 | } |
||
142 | |||
143 | $attributes = array_merge( |
||
144 | $attributes, |
||
145 | $this->formatValidationAttribute($input, $field->label(), $column) |
||
146 | ); |
||
147 | } |
||
148 | |||
149 | Arr::forget($rules, NestedForm::REMOVE_FLAG_NAME); |
||
150 | |||
151 | if (empty($rules)) { |
||
152 | return false; |
||
153 | } |
||
154 | |||
155 | $newRules = []; |
||
156 | $newInput = []; |
||
157 | |||
158 | foreach ($rules as $column => $rule) { |
||
159 | foreach (array_keys($input[$this->column]) as $key) { |
||
160 | $newRules["{$this->column}.$key.$column"] = $rule; |
||
161 | if (isset($input[$this->column][$key][$column]) && |
||
162 | is_array($input[$this->column][$key][$column])) { |
||
163 | foreach ($input[$this->column][$key][$column] as $vkey => $value) { |
||
164 | $newInput["{$this->column}.$key.{$column}$vkey"] = $value; |
||
165 | } |
||
166 | } |
||
167 | } |
||
168 | } |
||
169 | |||
170 | if (empty($newInput)) { |
||
171 | $newInput = $input; |
||
172 | } |
||
173 | |||
174 | $this->appendDistinctRules($newRules); |
||
175 | |||
176 | return \validator($newInput, $newRules, $this->getValidationMessages(), $attributes); |
||
177 | } |
||
178 | |||
179 | /** |
||
180 | * Set distinct fields. |
||
181 | * |
||
182 | * @param array $fields |
||
183 | * |
||
184 | * @return $this |
||
185 | */ |
||
186 | public function distinctFields(array $fields) |
||
187 | { |
||
188 | $this->distinctFields = $fields; |
||
189 | |||
190 | return $this; |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Append distinct rules. |
||
195 | * |
||
196 | * @param array $rules |
||
197 | */ |
||
198 | protected function appendDistinctRules(array &$rules) |
||
199 | { |
||
200 | foreach ($this->distinctFields as $field) { |
||
201 | $rules["{$this->column}.*.$field"] = 'distinct'; |
||
202 | } |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Format validation attributes. |
||
207 | * |
||
208 | * @param array $input |
||
209 | * @param string $label |
||
210 | * @param string $column |
||
211 | * |
||
212 | * @return array |
||
213 | */ |
||
214 | View Code Duplication | protected function formatValidationAttribute($input, $label, $column) |
|
215 | { |
||
216 | $new = $attributes = []; |
||
217 | |||
218 | if (is_array($column)) { |
||
219 | foreach ($column as $index => $col) { |
||
220 | $new[$col.$index] = $col; |
||
221 | } |
||
222 | } |
||
223 | |||
224 | foreach (array_keys(Arr::dot($input)) as $key) { |
||
225 | if (is_string($column)) { |
||
226 | if (Str::endsWith($key, ".$column")) { |
||
227 | $attributes[$key] = $label; |
||
228 | } |
||
229 | } else { |
||
230 | foreach ($new as $k => $val) { |
||
231 | if (Str::endsWith($key, ".$k")) { |
||
232 | $attributes[$key] = $label."[$val]"; |
||
233 | } |
||
234 | } |
||
235 | } |
||
236 | } |
||
237 | |||
238 | return $attributes; |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * Reset input key for validation. |
||
243 | * |
||
244 | * @param array $input |
||
245 | * @param array $column $column is the column name array set |
||
246 | * |
||
247 | * @return void. |
||
248 | */ |
||
249 | protected function resetInputKey(array &$input, array $column) |
||
250 | { |
||
251 | /** |
||
252 | * flip the column name array set. |
||
253 | * |
||
254 | * for example, for the DateRange, the column like as below |
||
255 | * |
||
256 | * ["start" => "created_at", "end" => "updated_at"] |
||
257 | * |
||
258 | * to: |
||
259 | * |
||
260 | * [ "created_at" => "start", "updated_at" => "end" ] |
||
261 | */ |
||
262 | $column = array_flip($column); |
||
263 | |||
264 | /** |
||
265 | * $this->column is the inputs array's node name, default is the relation name. |
||
266 | * |
||
267 | * So... $input[$this->column] is the data of this column's inputs data |
||
268 | * |
||
269 | * in the HasMany relation, has many data/field set, $set is field set in the below |
||
270 | */ |
||
271 | foreach ($input[$this->column] as $index => $set) { |
||
272 | |||
273 | /* |
||
274 | * foreach the field set to find the corresponding $column |
||
275 | */ |
||
276 | View Code Duplication | foreach ($set as $name => $value) { |
|
277 | /* |
||
278 | * if doesn't have column name, continue to the next loop |
||
279 | */ |
||
280 | if (!array_key_exists($name, $column)) { |
||
281 | continue; |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * example: $newKey = created_atstart. |
||
286 | * |
||
287 | * Σ( ° △ °|||)︴ |
||
288 | * |
||
289 | * I don't know why a form need range input? Only can imagine is for range search.... |
||
290 | */ |
||
291 | $newKey = $name.$column[$name]; |
||
292 | |||
293 | /* |
||
294 | * set new key |
||
295 | */ |
||
296 | Arr::set($input, "{$this->column}.$index.$newKey", $value); |
||
297 | /* |
||
298 | * forget the old key and value |
||
299 | */ |
||
300 | Arr::forget($input, "{$this->column}.$index.$name"); |
||
301 | } |
||
302 | } |
||
303 | } |
||
304 | |||
305 | /** |
||
306 | * Prepare input data for insert or update. |
||
307 | * |
||
308 | * @param array $input |
||
309 | * |
||
310 | * @return array |
||
311 | */ |
||
312 | public function prepare($input) |
||
313 | { |
||
314 | $form = $this->buildNestedForm($this->column, $this->builder); |
||
315 | |||
316 | return $form->setOriginal($this->original, $this->getKeyName())->prepare($input); |
||
317 | } |
||
318 | |||
319 | /** |
||
320 | * Build a Nested form. |
||
321 | * |
||
322 | * @param string $column |
||
323 | * @param \Closure $builder |
||
324 | * @param null $model |
||
325 | * |
||
326 | * @return NestedForm |
||
327 | */ |
||
328 | View Code Duplication | protected function buildNestedForm($column, \Closure $builder, $model = null) |
|
329 | { |
||
330 | $form = new Form\NestedForm($column, $model); |
||
331 | |||
332 | $form->setForm($this->form); |
||
333 | |||
334 | call_user_func($builder, $form); |
||
335 | |||
336 | $form->hidden($this->getKeyName()); |
||
337 | |||
338 | $form->hidden(NestedForm::REMOVE_FLAG_NAME)->default(0)->addElementClass(NestedForm::REMOVE_FLAG_CLASS); |
||
339 | |||
340 | return $form; |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * Get the HasMany relation key name. |
||
345 | * |
||
346 | * @return string |
||
347 | */ |
||
348 | protected function getKeyName() |
||
349 | { |
||
350 | if (is_null($this->form)) { |
||
351 | return; |
||
352 | } |
||
353 | |||
354 | return $this->form->model()->{$this->relationName}()->getRelated()->getKeyName(); |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * Set view mode. |
||
359 | * |
||
360 | * @param string $mode currently support `tab` mode. |
||
361 | * |
||
362 | * @return $this |
||
363 | * |
||
364 | * @author Edwin Hui |
||
365 | */ |
||
366 | public function mode($mode) |
||
367 | { |
||
368 | $this->viewMode = $mode; |
||
369 | |||
370 | return $this; |
||
371 | } |
||
372 | |||
373 | /** |
||
374 | * Use tab mode to showing hasmany field. |
||
375 | * |
||
376 | * @return HasMany |
||
377 | */ |
||
378 | public function useTab() |
||
379 | { |
||
380 | return $this->mode('tab'); |
||
381 | } |
||
382 | |||
383 | /** |
||
384 | * Use table mode to showing hasmany field. |
||
385 | * |
||
386 | * @return HasMany |
||
387 | */ |
||
388 | public function useTable() |
||
389 | { |
||
390 | return $this->mode('table'); |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * Build Nested form for related data. |
||
395 | * |
||
396 | * @throws \Exception |
||
397 | * |
||
398 | * @return array |
||
399 | */ |
||
400 | protected function buildRelatedForms() |
||
401 | { |
||
402 | if (is_null($this->form)) { |
||
403 | return []; |
||
404 | } |
||
405 | |||
406 | $model = $this->form->model(); |
||
407 | |||
408 | $relation = call_user_func([$model, $this->relationName]); |
||
409 | |||
410 | if (!$relation instanceof Relation && !$relation instanceof MorphMany) { |
||
411 | throw new \Exception('hasMany field must be a HasMany or MorphMany relation.'); |
||
412 | } |
||
413 | |||
414 | $forms = []; |
||
415 | |||
416 | /* |
||
417 | * If redirect from `exception` or `validation error` page. |
||
418 | * |
||
419 | * Then get form data from session flash. |
||
420 | * |
||
421 | * Else get data from database. |
||
422 | */ |
||
423 | if ($values = old($this->column)) { |
||
424 | foreach ($values as $key => $data) { |
||
425 | if ($data[NestedForm::REMOVE_FLAG_NAME] == 1) { |
||
426 | continue; |
||
427 | } |
||
428 | |||
429 | $model = $relation->getRelated()->replicate()->forceFill($data); |
||
430 | |||
431 | $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $model) |
||
432 | ->fill($data); |
||
433 | } |
||
434 | } else { |
||
435 | if (empty($this->value)) { |
||
436 | return []; |
||
437 | } |
||
438 | |||
439 | foreach ($this->value as $data) { |
||
440 | $key = Arr::get($data, $relation->getRelated()->getKeyName()); |
||
441 | |||
442 | $model = $relation->getRelated()->replicate()->forceFill($data); |
||
443 | |||
444 | $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $model) |
||
445 | ->fill($data); |
||
446 | } |
||
447 | } |
||
448 | |||
449 | return $forms; |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * Setup script for this field in different view mode. |
||
454 | * |
||
455 | * @param string $script |
||
456 | * |
||
457 | * @return void |
||
458 | */ |
||
459 | protected function setupScript($script) |
||
460 | { |
||
461 | $method = 'setupScriptFor'.ucfirst($this->viewMode).'View'; |
||
462 | |||
463 | call_user_func([$this, $method], $script); |
||
464 | } |
||
465 | |||
466 | /** |
||
467 | * Setup default template script. |
||
468 | * |
||
469 | * @param string $templateScript |
||
470 | * |
||
471 | * @return void |
||
472 | */ |
||
473 | protected function setupScriptForDefaultView($templateScript) |
||
474 | { |
||
475 | $removeClass = NestedForm::REMOVE_FLAG_CLASS; |
||
476 | $defaultKey = NestedForm::DEFAULT_KEY_NAME; |
||
477 | |||
478 | /** |
||
479 | * When add a new sub form, replace all element key in new sub form. |
||
480 | * |
||
481 | * @example comments[new___key__][title] => comments[new_{index}][title] |
||
482 | * |
||
483 | * {count} is increment number of current sub form count. |
||
484 | */ |
||
485 | $script = <<<EOT |
||
486 | var index = 0; |
||
487 | $('#has-many-{$this->column}').off('click', '.add').on('click', '.add', function () { |
||
488 | |||
489 | var tpl = $('template.{$this->column}-tpl'); |
||
490 | |||
491 | index++; |
||
492 | |||
493 | var template = tpl.html().replace(/{$defaultKey}/g, index); |
||
494 | $('.has-many-{$this->column}-forms').append(template); |
||
495 | {$templateScript} |
||
496 | return false; |
||
497 | }); |
||
498 | |||
499 | $('#has-many-{$this->column}').off('click', '.remove').on('click', '.remove', function () { |
||
500 | $(this).closest('.has-many-{$this->column}-form').find('input').removeAttr('required'); |
||
501 | $(this).closest('.has-many-{$this->column}-form').hide(); |
||
502 | $(this).closest('.has-many-{$this->column}-form').find('.$removeClass').val(1); |
||
503 | return false; |
||
504 | }); |
||
505 | |||
506 | EOT; |
||
507 | |||
508 | Admin::script($script); |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * Setup tab template script. |
||
513 | * |
||
514 | * @param string $templateScript |
||
515 | * |
||
516 | * @return void |
||
517 | */ |
||
518 | View Code Duplication | protected function setupScriptForTabView($templateScript) |
|
519 | { |
||
520 | $removeClass = NestedForm::REMOVE_FLAG_CLASS; |
||
521 | $defaultKey = NestedForm::DEFAULT_KEY_NAME; |
||
522 | |||
523 | $script = <<<EOT |
||
524 | |||
525 | $('#has-many-{$this->column} > .nav').off('click', 'i.close-tab').on('click', 'i.close-tab', function(){ |
||
526 | var \$navTab = $(this).siblings('a'); |
||
527 | var \$pane = $(\$navTab.attr('href')); |
||
528 | if( \$pane.hasClass('new') ){ |
||
529 | \$pane.remove(); |
||
530 | }else{ |
||
531 | \$pane.removeClass('active').find('.$removeClass').val(1); |
||
532 | } |
||
533 | if(\$navTab.closest('li').hasClass('active')){ |
||
534 | \$navTab.closest('li').remove(); |
||
535 | $('#has-many-{$this->column} > .nav > li:nth-child(1) > a').tab('show'); |
||
536 | }else{ |
||
537 | \$navTab.closest('li').remove(); |
||
538 | } |
||
539 | }); |
||
540 | |||
541 | var index = 0; |
||
542 | $('#has-many-{$this->column} > .header').off('click', '.add').on('click', '.add', function(){ |
||
543 | index++; |
||
544 | var navTabHtml = $('#has-many-{$this->column} > template.nav-tab-tpl').html().replace(/{$defaultKey}/g, index); |
||
545 | var paneHtml = $('#has-many-{$this->column} > template.pane-tpl').html().replace(/{$defaultKey}/g, index); |
||
546 | $('#has-many-{$this->column} > .nav').append(navTabHtml); |
||
547 | $('#has-many-{$this->column} > .tab-content').append(paneHtml); |
||
548 | $('#has-many-{$this->column} > .nav > li:last-child a').tab('show'); |
||
549 | {$templateScript} |
||
550 | }); |
||
551 | |||
552 | if ($('.has-error').length) { |
||
553 | $('.has-error').parent('.tab-pane').each(function () { |
||
554 | var tabId = '#'+$(this).attr('id'); |
||
555 | $('li a[href="'+tabId+'"] i').removeClass('hide'); |
||
556 | }); |
||
557 | |||
558 | var first = $('.has-error:first').parent().attr('id'); |
||
559 | $('li a[href="#'+first+'"]').tab('show'); |
||
560 | } |
||
561 | EOT; |
||
562 | |||
563 | Admin::script($script); |
||
564 | } |
||
565 | |||
566 | /** |
||
567 | * Setup default template script. |
||
568 | * |
||
569 | * @param string $templateScript |
||
570 | * |
||
571 | * @return void |
||
572 | */ |
||
573 | View Code Duplication | protected function setupScriptForTableView($templateScript) |
|
574 | { |
||
575 | $removeClass = NestedForm::REMOVE_FLAG_CLASS; |
||
576 | $defaultKey = NestedForm::DEFAULT_KEY_NAME; |
||
577 | |||
578 | /** |
||
579 | * When add a new sub form, replace all element key in new sub form. |
||
580 | * |
||
581 | * @example comments[new___key__][title] => comments[new_{index}][title] |
||
582 | * |
||
583 | * {count} is increment number of current sub form count. |
||
584 | */ |
||
585 | $script = <<<EOT |
||
586 | var index = 0; |
||
587 | $('#has-many-{$this->column}').on('click', '.add', function () { |
||
588 | |||
589 | var tpl = $('template.{$this->column}-tpl'); |
||
590 | |||
591 | index++; |
||
592 | |||
593 | var template = tpl.html().replace(/{$defaultKey}/g, index); |
||
594 | $('.has-many-{$this->column}-forms').append(template); |
||
595 | {$templateScript} |
||
596 | return false; |
||
597 | }); |
||
598 | |||
599 | $('#has-many-{$this->column}').on('click', '.remove', function () { |
||
600 | var first_input_name = $(this).closest('.has-many-{$this->column}-form').find('input[name]:first').attr('name'); |
||
601 | if (first_input_name.match('{$this->column}\\\[new_')) { |
||
602 | $(this).closest('.has-many-{$this->column}-form').remove(); |
||
603 | } else { |
||
604 | $(this).closest('.has-many-{$this->column}-form').hide(); |
||
605 | $(this).closest('.has-many-{$this->column}-form').find('.$removeClass').val(1); |
||
606 | $(this).closest('.has-many-{$this->column}-form').find('input').removeAttr('required'); |
||
607 | } |
||
608 | return false; |
||
609 | }); |
||
610 | |||
611 | EOT; |
||
612 | |||
613 | Admin::script($script); |
||
614 | } |
||
615 | |||
616 | /** |
||
617 | * Disable create button. |
||
618 | * |
||
619 | * @return $this |
||
620 | */ |
||
621 | public function disableCreate() |
||
622 | { |
||
623 | $this->options['allowCreate'] = false; |
||
624 | |||
625 | return $this; |
||
626 | } |
||
627 | |||
628 | /** |
||
629 | * Disable delete button. |
||
630 | * |
||
631 | * @return $this |
||
632 | */ |
||
633 | public function disableDelete() |
||
634 | { |
||
635 | $this->options['allowDelete'] = false; |
||
636 | |||
637 | return $this; |
||
638 | } |
||
639 | |||
640 | /** |
||
641 | * Render the `HasMany` field. |
||
642 | * |
||
643 | * @throws \Exception |
||
644 | * |
||
645 | * @return \Illuminate\View\View |
||
646 | */ |
||
647 | public function render() |
||
648 | { |
||
649 | if (!$this->shouldRender()) { |
||
650 | return ''; |
||
651 | } |
||
652 | |||
653 | if ($this->viewMode == 'table') { |
||
654 | return $this->renderTable(); |
||
655 | } |
||
656 | |||
657 | // specify a view to render. |
||
658 | $this->view = $this->views[$this->viewMode]; |
||
659 | |||
660 | list($template, $script) = $this->buildNestedForm($this->column, $this->builder) |
||
661 | ->getTemplateHtmlAndScript(); |
||
662 | |||
663 | $this->setupScript($script); |
||
664 | |||
665 | return parent::render()->with([ |
||
666 | 'forms' => $this->buildRelatedForms(), |
||
667 | 'template' => $template, |
||
668 | 'relationName' => $this->relationName, |
||
669 | 'options' => $this->options, |
||
670 | ]); |
||
671 | } |
||
672 | |||
673 | /** |
||
674 | * Render the `HasMany` field for table style. |
||
675 | * |
||
676 | * @throws \Exception |
||
677 | * |
||
678 | * @return mixed |
||
679 | */ |
||
680 | protected function renderTable() |
||
681 | { |
||
682 | $headers = []; |
||
683 | $fields = []; |
||
684 | $hidden = []; |
||
685 | $scripts = []; |
||
686 | |||
687 | /* @var Field $field */ |
||
688 | foreach ($this->buildNestedForm($this->column, $this->builder)->fields() as $field) { |
||
689 | if (is_a($field, Hidden::class)) { |
||
690 | $hidden[] = $field->render(); |
||
691 | } else { |
||
692 | /* Hide label and set field width 100% */ |
||
693 | $field->setLabelClass(['hidden']); |
||
694 | $field->setWidth(12, 0); |
||
695 | $fields[] = $field->render(); |
||
696 | $headers[] = $field->label(); |
||
697 | } |
||
698 | |||
699 | /* |
||
700 | * Get and remove the last script of Admin::$script stack. |
||
701 | */ |
||
702 | if ($field->getScript()) { |
||
703 | $scripts[] = array_pop(Admin::$script); |
||
704 | } |
||
705 | } |
||
706 | |||
707 | /* Build row elements */ |
||
708 | $template = array_reduce($fields, function ($all, $field) { |
||
709 | $all .= "<td>{$field}</td>"; |
||
710 | |||
711 | return $all; |
||
712 | }, ''); |
||
713 | |||
714 | /* Build cell with hidden elements */ |
||
715 | $template .= '<td class="hidden">'.implode('', $hidden).'</td>'; |
||
716 | |||
717 | $this->setupScript(implode("\r\n", $scripts)); |
||
718 | |||
719 | // specify a view to render. |
||
720 | $this->view = $this->views[$this->viewMode]; |
||
721 | |||
722 | return parent::render()->with([ |
||
0 ignored issues
–
show
|
|||
723 | 'headers' => $headers, |
||
724 | 'forms' => $this->buildRelatedForms(), |
||
725 | 'template' => $template, |
||
726 | 'relationName' => $this->relationName, |
||
727 | 'options' => $this->options, |
||
728 | ]); |
||
729 | } |
||
730 | } |
||
731 |
This check looks for a call to a parent method whose name is different than the method from which it is called.
Consider the following code:
The
getFirstName()
method in theSon
calls the wrong method in the parent class.