Completed
Pull Request — master (#2447)
by jxlwqq
02:26
created

Field::original()   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\Form;
4
5
use Encore\Admin\Admin;
6
use Encore\Admin\Form;
7
use Illuminate\Contracts\Support\Arrayable;
8
use Illuminate\Contracts\Support\Renderable;
9
use Illuminate\Support\Arr;
10
use Illuminate\Support\Facades\Validator;
11
use Illuminate\Support\Traits\Macroable;
12
13
/**
14
 * Class Field.
15
 */
16
class Field implements Renderable
17
{
18
    use Macroable;
19
20
    const FILE_DELETE_FLAG = '_file_del_';
21
22
    /**
23
     * Element id.
24
     *
25
     * @var array|string
26
     */
27
    protected $id;
28
29
    /**
30
     * Element value.
31
     *
32
     * @var mixed
33
     */
34
    protected $value;
35
36
    /**
37
     * Field original value.
38
     *
39
     * @var mixed
40
     */
41
    protected $original;
42
43
    /**
44
     * Field default value.
45
     *
46
     * @var mixed
47
     */
48
    protected $default;
49
50
    /**
51
     * Element label.
52
     *
53
     * @var string
54
     */
55
    protected $label = '';
56
57
    /**
58
     * Column name.
59
     *
60
     * @var string|array
61
     */
62
    protected $column = '';
63
64
    /**
65
     * Form element name.
66
     *
67
     * @var string
68
     */
69
    protected $elementName = [];
70
71
    /**
72
     * Form element classes.
73
     *
74
     * @var array
75
     */
76
    protected $elementClass = [];
77
78
    /**
79
     * Variables of elements.
80
     *
81
     * @var array
82
     */
83
    protected $variables = [];
84
85
    /**
86
     * Options for specify elements.
87
     *
88
     * @var array
89
     */
90
    protected $options = [];
91
92
    /**
93
     * Checked for specify elements.
94
     *
95
     * @var array
96
     */
97
    protected $checked = [];
98
99
    /**
100
     * Validation rules.
101
     *
102
     * @var string|\Closure
103
     */
104
    protected $rules = '';
105
106
    /**
107
     * @var callable
108
     */
109
    protected $validator;
110
111
    /**
112
     * Validation messages.
113
     *
114
     * @var array
115
     */
116
    protected $validationMessages = [];
117
118
    /**
119
     * Css required by this field.
120
     *
121
     * @var array
122
     */
123
    protected static $css = [];
124
125
    /**
126
     * Js required by this field.
127
     *
128
     * @var array
129
     */
130
    protected static $js = [];
131
132
    /**
133
     * Script for field.
134
     *
135
     * @var string
136
     */
137
    protected $script = '';
138
139
    /**
140
     * Element attributes.
141
     *
142
     * @var array
143
     */
144
    protected $attributes = [];
145
146
    /**
147
     * Parent form.
148
     *
149
     * @var Form
150
     */
151
    protected $form = null;
152
153
    /**
154
     * View for field to render.
155
     *
156
     * @var string
157
     */
158
    protected $view = '';
159
160
    /**
161
     * Help block.
162
     *
163
     * @var array
164
     */
165
    protected $help = [];
166
167
    /**
168
     * Key for errors.
169
     *
170
     * @var mixed
171
     */
172
    protected $errorKey;
173
174
    /**
175
     * Placeholder for this field.
176
     *
177
     * @var string|array
178
     */
179
    protected $placeholder;
180
181
    /**
182
     * Width for label and field.
183
     *
184
     * @var array
185
     */
186
    protected $width = [
187
        'label' => 2,
188
        'field' => 8,
189
    ];
190
191
    /**
192
     * If the form horizontal layout.
193
     *
194
     * @var bool
195
     */
196
    protected $horizontal = true;
197
198
    /**
199
     * column data format.
200
     *
201
     * @var Closure
202
     */
203
    protected $customFormat = null;
204
205
    /**
206
     * @var bool
207
     */
208
    protected $display = true;
209
210
    /**
211
     * @var array
212
     */
213
    protected $labelClass = [];
214
215
    /**
216
     * Field constructor.
217
     *
218
     * @param       $column
219
     * @param array $arguments
220
     */
221
    public function __construct($column, $arguments = [])
222
    {
223
        $this->column = $column;
224
        $this->label = $this->formatLabel($arguments);
225
        $this->id = $this->formatId($column);
226
    }
227
228
    /**
229
     * Get assets required by this field.
230
     *
231
     * @return array
232
     */
233
    public static function getAssets()
234
    {
235
        return [
236
            'css' => static::$css,
237
            'js'  => static::$js,
238
        ];
239
    }
240
241
    /**
242
     * Format the field element id.
243
     *
244
     * @param string|array $column
245
     *
246
     * @return string|array
247
     */
248
    protected function formatId($column)
249
    {
250
        return str_replace('.', '_', $column);
251
    }
252
253
    /**
254
     * Format the label value.
255
     *
256
     * @param array $arguments
257
     *
258
     * @return string
259
     */
260
    protected function formatLabel($arguments = [])
261
    {
262
        $column = is_array($this->column) ? current($this->column) : $this->column;
263
264
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($column);
265
266
        return str_replace(['.', '_'], ' ', $label);
267
    }
268
269
    /**
270
     * Format the name of the field.
271
     *
272
     * @param string $column
273
     *
274
     * @return array|mixed|string
275
     */
276
    protected function formatName($column)
277
    {
278
        if (is_string($column)) {
279
            $name = explode('.', $column);
280
281
            if (count($name) == 1) {
282
                return $name[0];
283
            }
284
285
            $html = array_shift($name);
286
            foreach ($name as $piece) {
287
                $html .= "[$piece]";
288
            }
289
290
            return $html;
291
        }
292
293
        if (is_array($this->column)) {
294
            $names = [];
295
            foreach ($this->column as $key => $name) {
296
                $names[$key] = $this->formatName($name);
297
            }
298
299
            return $names;
300
        }
301
302
        return '';
303
    }
304
305
    /**
306
     * Set form element name.
307
     *
308
     * @param string $name
309
     *
310
     * @return $this
311
     *
312
     * @author Edwin Hui
313
     */
314
    public function setElementName($name)
315
    {
316
        $this->elementName = $name;
317
318
        return $this;
319
    }
320
321
    /**
322
     * Fill data to the field.
323
     *
324
     * @param array $data
325
     *
326
     * @return void
327
     */
328
    public function fill($data)
329
    {
330
        // Field value is already setted.
331
//        if (!is_null($this->value)) {
332
//            return;
333
//        }
334
335
        if (is_array($this->column)) {
336
            foreach ($this->column as $key => $column) {
337
                $this->value[$key] = array_get($data, $column);
338
            }
339
340
            return;
341
        }
342
343
        $this->value = array_get($data, $this->column);
344
        if (isset($this->customFormat) && $this->customFormat instanceof \Closure) {
345
            $this->value = call_user_func($this->customFormat, $this->value);
346
        }
347
    }
348
349
    /**
350
     * custom format form column data when edit.
351
     *
352
     * @param Closure $call
353
     *
354
     * @return [null]
0 ignored issues
show
Documentation introduced by
The doc-type [null] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
355
     */
356
    public function customFormat(\Closure $call)
357
    {
358
        $this->customFormat = $call;
0 ignored issues
show
Documentation Bug introduced by
It seems like $call of type object<Closure> is incompatible with the declared type object<Encore\Admin\Form\Closure> of property $customFormat.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
359
    }
360
361
    /**
362
     * Set original value to the field.
363
     *
364
     * @param array $data
365
     *
366
     * @return void
367
     */
368
    public function setOriginal($data)
369
    {
370
        if (is_array($this->column)) {
371
            foreach ($this->column as $key => $column) {
372
                $this->original[$key] = array_get($data, $column);
373
            }
374
375
            return;
376
        }
377
378
        $this->original = array_get($data, $this->column);
379
    }
380
381
    /**
382
     * @param Form $form
383
     *
384
     * @return $this
385
     */
386
    public function setForm(Form $form = null)
387
    {
388
        $this->form = $form;
389
390
        return $this;
391
    }
392
393
    /**
394
     * Set width for field and label.
395
     *
396
     * @param int $field
397
     * @param int $label
398
     *
399
     * @return $this
400
     */
401
    public function setWidth($field = 8, $label = 2)
402
    {
403
        $this->width = [
404
            'label' => $label,
405
            'field' => $field,
406
        ];
407
408
        return $this;
409
    }
410
411
    /**
412
     * Set the field options.
413
     *
414
     * @param array $options
415
     *
416
     * @return $this
417
     */
418 View Code Duplication
    public function options($options = [])
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...
419
    {
420
        if ($options instanceof Arrayable) {
421
            $options = $options->toArray();
422
        }
423
424
        $this->options = array_merge($this->options, $options);
425
426
        return $this;
427
    }
428
429
    /**
430
     * Set the field option checked.
431
     *
432
     * @param array $checked
433
     *
434
     * @return $this
435
     */
436 View Code Duplication
    public function checked($checked = [])
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...
437
    {
438
        if ($checked instanceof Arrayable) {
439
            $checked = $checked->toArray();
440
        }
441
442
        $this->checked = array_merge($this->checked, $checked);
443
444
        return $this;
445
    }
446
447
    /**
448
     * Get or set rules.
449
     *
450
     * @param null  $rules
451
     * @param array $messages
452
     *
453
     * @return $this
454
     */
455
    public function rules($rules = null, $messages = [])
456
    {
457
        if ($rules instanceof \Closure) {
458
            $this->rules = $rules;
459
        }
460
461
        if (is_array($rules)) {
462
            $thisRuleArr = array_filter(explode('|', $this->rules));
463
464
            $this->rules = array_merge($thisRuleArr, $rules);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($thisRuleArr, $rules) of type array is incompatible with the declared type string|object<Closure> of property $rules.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
465
        } elseif (is_string($rules)) {
466
            $rules = array_filter(explode('|', "{$this->rules}|$rules"));
467
468
            $this->rules = implode('|', $rules);
469
        }
470
471
        $this->validationMessages = $messages;
472
473
        return $this;
474
    }
475
476
    /**
477
     * Get field validation rules.
478
     *
479
     * @return string
480
     */
481
    protected function getRules()
482
    {
483
        if ($this->rules instanceof \Closure) {
484
            return $this->rules->call($this, $this->form);
485
        }
486
487
        return $this->rules;
488
    }
489
490
    /**
491
     * Remove a specific rule by keyword.
492
     *
493
     * @param string $rule
494
     *
495
     * @return void
496
     */
497
    protected function removeRule($rule)
498
    {
499
        if (!is_string($this->rules)) {
500
            return;
501
        }
502
503
        $pattern = "/{$rule}[^\|]?(\||$)/";
504
        $this->rules = preg_replace($pattern, '', $this->rules, -1);
505
    }
506
507
    /**
508
     * Set field validator.
509
     *
510
     * @param callable $validator
511
     *
512
     * @return $this
513
     */
514
    public function validator(callable $validator)
515
    {
516
        $this->validator = $validator;
517
518
        return $this;
519
    }
520
521
    /**
522
     * Get key for error message.
523
     *
524
     * @return string
525
     */
526
    public function getErrorKey()
527
    {
528
        return $this->errorKey ?: $this->column;
529
    }
530
531
    /**
532
     * Set key for error message.
533
     *
534
     * @param string $key
535
     *
536
     * @return $this
537
     */
538
    public function setErrorKey($key)
539
    {
540
        $this->errorKey = $key;
541
542
        return $this;
543
    }
544
545
    /**
546
     * Set or get value of the field.
547
     *
548
     * @param null $value
549
     *
550
     * @return mixed
551
     */
552 View Code Duplication
    public function value($value = null)
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...
553
    {
554
        if (is_null($value)) {
555
            return is_null($this->value) ? $this->getDefault() : $this->value;
556
        }
557
558
        $this->value = $value;
559
560
        return $this;
561
    }
562
563
    /**
564
     * Set default value for field.
565
     *
566
     * @param $default
567
     *
568
     * @return $this
569
     */
570
    public function default($default)
571
    {
572
        $this->default = $default;
573
574
        return $this;
575
    }
576
577
    /**
578
     * Get default value.
579
     *
580
     * @return mixed
581
     */
582
    public function getDefault()
583
    {
584
        if ($this->default instanceof \Closure) {
585
            return call_user_func($this->default, $this->form);
586
        }
587
588
        return $this->default;
589
    }
590
591
    /**
592
     * Set help block for current field.
593
     *
594
     * @param string $text
595
     * @param string $icon
596
     *
597
     * @return $this
598
     */
599
    public function help($text = '', $icon = 'fa-info-circle')
600
    {
601
        $this->help = compact('text', 'icon');
602
603
        return $this;
604
    }
605
606
    /**
607
     * Get column of the field.
608
     *
609
     * @return string|array
610
     */
611
    public function column()
612
    {
613
        return $this->column;
614
    }
615
616
    /**
617
     * Get label of the field.
618
     *
619
     * @return string
620
     */
621
    public function label()
622
    {
623
        return $this->label;
624
    }
625
626
    /**
627
     * Get original value of the field.
628
     *
629
     * @return mixed
630
     */
631
    public function original()
632
    {
633
        return $this->original;
634
    }
635
636
    /**
637
     * Get validator for this field.
638
     *
639
     * @param array $input
640
     *
641
     * @return bool|Validator
642
     */
643
    public function getValidator(array $input)
644
    {
645
        if ($this->validator) {
646
            return $this->validator->call($this, $input);
647
        }
648
649
        $rules = $attributes = [];
650
651
        if (!$fieldRules = $this->getRules()) {
652
            return false;
653
        }
654
655
        if (is_string($this->column)) {
656
            if (!array_has($input, $this->column)) {
657
                return false;
658
            }
659
660
            $input = $this->sanitizeInput($input, $this->column);
661
662
            $rules[$this->column] = $fieldRules;
663
            $attributes[$this->column] = $this->label;
664
        }
665
666
        if (is_array($this->column)) {
667
            foreach ($this->column as $key => $column) {
668
                if (!array_key_exists($column, $input)) {
669
                    continue;
670
                }
671
                $input[$column.$key] = array_get($input, $column);
672
                $rules[$column.$key] = $fieldRules;
673
                $attributes[$column.$key] = $this->label."[$column]";
674
            }
675
        }
676
677
        return Validator::make($input, $rules, $this->validationMessages, $attributes);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Illuminate\Suppo...Messages, $attributes); (Illuminate\Contracts\Validation\Validator) is incompatible with the return type documented by Encore\Admin\Form\Field::getValidator of type boolean|Illuminate\Support\Facades\Validator.

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...
678
    }
679
680
    /**
681
     * Sanitize input data.
682
     *
683
     * @param array  $input
684
     * @param string $column
685
     *
686
     * @return array
687
     */
688
    protected function sanitizeInput($input, $column)
689
    {
690
        if ($this instanceof Field\MultipleSelect) {
691
            $value = array_get($input, $column);
692
            array_set($input, $column, array_filter($value));
693
        }
694
695
        return $input;
696
    }
697
698
    /**
699
     * Add html attributes to elements.
700
     *
701
     * @param array|string $attribute
702
     * @param mixed        $value
703
     *
704
     * @return $this
705
     */
706
    public function attribute($attribute, $value = null)
707
    {
708
        if (is_array($attribute)) {
709
            $this->attributes = array_merge($this->attributes, $attribute);
710
        } else {
711
            $this->attributes[$attribute] = (string) $value;
712
        }
713
714
        return $this;
715
    }
716
717
    /**
718
     * Set the field as readonly mode.
719
     *
720
     * @return Field
721
     */
722
    public function readOnly()
723
    {
724
        return $this->attribute('readonly', true);
725
    }
726
727
    /**
728
     * Set field as disabled.
729
     *
730
     * @return Field
731
     */
732
    public function disable()
733
    {
734
        return $this->attribute('disabled', true);
735
    }
736
737
    /**
738
     * Set field placeholder.
739
     *
740
     * @param string $placeholder
741
     *
742
     * @return Field
743
     */
744
    public function placeholder($placeholder = '')
745
    {
746
        $this->placeholder = $placeholder;
747
748
        return $this;
749
    }
750
751
    /**
752
     * Get placeholder.
753
     *
754
     * @return string
755
     */
756
    public function getPlaceholder()
757
    {
758
        return $this->placeholder ?: trans('admin.input').' '.$this->label;
759
    }
760
761
    /**
762
     * Prepare for a field value before update or insert.
763
     *
764
     * @param $value
765
     *
766
     * @return mixed
767
     */
768
    public function prepare($value)
769
    {
770
        return $value;
771
    }
772
773
    /**
774
     * Format the field attributes.
775
     *
776
     * @return string
777
     */
778
    protected function formatAttributes()
779
    {
780
        $html = [];
781
782
        foreach ($this->attributes as $name => $value) {
783
            $html[] = $name.'="'.e($value).'"';
784
        }
785
786
        return implode(' ', $html);
787
    }
788
789
    /**
790
     * @return $this
791
     */
792
    public function disableHorizontal()
793
    {
794
        $this->horizontal = false;
795
796
        return $this;
797
    }
798
799
    /**
800
     * @return array
801
     */
802
    public function getViewElementClasses()
803
    {
804
        if ($this->horizontal) {
805
            return [
806
                'label'      => "col-sm-{$this->width['label']} {$this->getLabelClass()}",
807
                'field'      => "col-sm-{$this->width['field']}",
808
                'form-group' => 'form-group ',
809
            ];
810
        }
811
812
        return ['label' => "{$this->getLabelClass()}", 'field' => '', 'form-group' => ''];
813
    }
814
815
    /**
816
     * Set form element class.
817
     *
818
     * @param string|array $class
819
     *
820
     * @return $this
821
     */
822
    public function setElementClass($class)
823
    {
824
        $this->elementClass = (array) $class;
825
826
        return $this;
827
    }
828
829
    /**
830
     * Get element class.
831
     *
832
     * @return array
833
     */
834
    protected function getElementClass()
835
    {
836
        if (!$this->elementClass) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->elementClass of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
837
            $name = $this->elementName ?: $this->formatName($this->column);
0 ignored issues
show
Bug introduced by
It seems like $this->column can also be of type array; however, Encore\Admin\Form\Field::formatName() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
838
839
            $this->elementClass = (array) str_replace(['[', ']'], '_', $name);
840
        }
841
842
        return $this->elementClass;
843
    }
844
845
    /**
846
     * Get element class string.
847
     *
848
     * @return mixed
849
     */
850 View Code Duplication
    protected function getElementClassString()
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...
851
    {
852
        $elementClass = $this->getElementClass();
853
854
        if (Arr::isAssoc($elementClass)) {
855
            $classes = [];
856
857
            foreach ($elementClass as $index => $class) {
858
                $classes[$index] = is_array($class) ? implode(' ', $class) : $class;
859
            }
860
861
            return $classes;
862
        }
863
864
        return implode(' ', $elementClass);
865
    }
866
867
    /**
868
     * Get element class selector.
869
     *
870
     * @return string
871
     */
872 View Code Duplication
    protected function getElementClassSelector()
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...
873
    {
874
        $elementClass = $this->getElementClass();
875
876
        if (Arr::isAssoc($elementClass)) {
877
            $classes = [];
878
879
            foreach ($elementClass as $index => $class) {
880
                $classes[$index] = '.'.(is_array($class) ? implode('.', $class) : $class);
881
            }
882
883
            return $classes;
884
        }
885
886
        return '.'.implode('.', $elementClass);
887
    }
888
889
    /**
890
     * Add the element class.
891
     *
892
     * @param $class
893
     *
894
     * @return $this
895
     */
896
    public function addElementClass($class)
897
    {
898
        if (is_array($class) || is_string($class)) {
899
            $this->elementClass = array_merge($this->elementClass, (array) $class);
900
901
            $this->elementClass = array_unique($this->elementClass);
902
        }
903
904
        return $this;
905
    }
906
907
    /**
908
     * Remove element class.
909
     *
910
     * @param $class
911
     *
912
     * @return $this
913
     */
914
    public function removeElementClass($class)
915
    {
916
        $delClass = [];
917
918
        if (is_string($class) || is_array($class)) {
919
            $delClass = (array) $class;
920
        }
921
922
        foreach ($delClass as $del) {
923
            if (($key = array_search($del, $this->elementClass))) {
924
                unset($this->elementClass[$key]);
925
            }
926
        }
927
928
        return $this;
929
    }
930
931
    /**
932
     * Add variables to field view.
933
     *
934
     * @param array $variables
935
     *
936
     * @return $this
937
     */
938
    protected function addVariables(array $variables = [])
939
    {
940
        $this->variables = array_merge($this->variables, $variables);
941
942
        return $this;
943
    }
944
945
    /**
946
     * @return string
947
     */
948
    public function getLabelClass()
949
    : string
950
    {
951
        return implode(' ', $this->labelClass);
952
    }
953
954
    /**
955
     * @param array $labelClass
956
     *
957
     * @return self
958
     */
959
    public function setLabelClass(array $labelClass)
960
    : self
961
    {
962
        $this->labelClass = $labelClass;
963
964
        return $this;
965
    }
966
967
    /**
968
     * Get the view variables of this field.
969
     *
970
     * @return array
971
     */
972
    public function variables()
973
    {
974
        return array_merge($this->variables, [
975
            'id'          => $this->id,
976
            'name'        => $this->elementName ?: $this->formatName($this->column),
0 ignored issues
show
Bug introduced by
It seems like $this->column can also be of type array; however, Encore\Admin\Form\Field::formatName() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
977
            'help'        => $this->help,
978
            'class'       => $this->getElementClassString(),
979
            'value'       => $this->value(),
980
            'label'       => $this->label,
981
            'viewClass'   => $this->getViewElementClasses(),
982
            'column'      => $this->column,
983
            'errorKey'    => $this->getErrorKey(),
984
            'attributes'  => $this->formatAttributes(),
985
            'placeholder' => $this->getPlaceholder(),
986
        ]);
987
    }
988
989
    /**
990
     * Get view of this field.
991
     *
992
     * @return string
993
     */
994
    public function getView()
995
    {
996
        if (!empty($this->view)) {
997
            return $this->view;
998
        }
999
1000
        $class = explode('\\', get_called_class());
1001
1002
        return 'admin::form.'.strtolower(end($class));
1003
    }
1004
1005
    /**
1006
     * Get script of current field.
1007
     *
1008
     * @return string
1009
     */
1010
    public function getScript()
1011
    {
1012
        return $this->script;
1013
    }
1014
1015
    /**
1016
     * Render this filed.
1017
     *
1018
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
1019
     */
1020
    public function render()
1021
    {
1022
        if (!$this->display) {
1023
            return '';
1024
        }
1025
1026
        Admin::script($this->script);
1027
1028
        return view($this->getView(), $this->variables());
0 ignored issues
show
Bug Compatibility introduced by
The expression view($this->getView(), $this->variables()); of type Illuminate\View\View|Ill...\Contracts\View\Factory adds the type Illuminate\Contracts\View\Factory to the return on line 1028 which is incompatible with the return type declared by the interface Illuminate\Contracts\Support\Renderable::render of type string.
Loading history...
1029
    }
1030
1031
    /**
1032
     * @return string
1033
     */
1034
    public function __toString()
1035
    {
1036
        return $this->render()->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...
1037
    }
1038
}
1039