Completed
Push — master ( 10aeea...fac0f4 )
by Song
11s
created

Field::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 15 and the first side effect is on line 925.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

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

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
304
//        if (!is_null($this->value)) {
305
//            return;
306
//        }
307
308
        if (is_array($this->column)) {
309
            foreach ($this->column as $key => $column) {
310
                $this->value[$key] = array_get($data, $column);
311
            }
312
313
            return;
314
        }
315
316
        $this->value = array_get($data, $this->column);
317
    }
318
319
    /**
320
     * Set original value to the field.
321
     *
322
     * @param array $data
323
     *
324
     * @return void
325
     */
326 View Code Duplication
    public function setOriginal($data)
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...
327
    {
328
        if (is_array($this->column)) {
329
            foreach ($this->column as $key => $column) {
330
                $this->original[$key] = array_get($data, $column);
331
            }
332
333
            return;
334
        }
335
336
        $this->original = array_get($data, $this->column);
337
    }
338
339
    /**
340
     * @param Form $form
341
     *
342
     * @return $this
343
     */
344
    public function setForm(Form $form = null)
345
    {
346
        $this->form = $form;
347
348
        return $this;
349
    }
350
351
    /**
352
     * Set width for field and label.
353
     *
354
     * @param int $field
355
     * @param int $label
356
     *
357
     * @return $this
358
     */
359
    public function setWidth($field = 8, $label = 2)
360
    {
361
        $this->width = [
362
            'label' => $label,
363
            'field' => $field,
364
        ];
365
366
        return $this;
367
    }
368
369
    /**
370
     * Set the field options.
371
     *
372
     * @param array $options
373
     *
374
     * @return $this
375
     */
376 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...
377
    {
378
        if ($options instanceof Arrayable) {
379
            $options = $options->toArray();
380
        }
381
382
        $this->options = array_merge($this->options, $options);
383
384
        return $this;
385
    }
386
387
    /**
388
     * Get or set rules.
389
     *
390
     * @param null  $rules
391
     * @param array $messages
392
     *
393
     * @return $this
394
     */
395
    public function rules($rules = null, $messages = [])
396
    {
397
        if ($rules instanceof \Closure) {
398
            $this->rules = $rules;
399
        }
400
401 View Code Duplication
        if (is_string($rules)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
402
            $rules = array_filter(explode('|', "{$this->rules}|$rules"));
403
404
            $this->rules = implode('|', $rules);
405
        }
406
407 View Code Duplication
        if (is_array($rules)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
408
            $thisRuleArr = array_filter(explode('|', $this->rules));
409
410
            $this->rules = array_merge($thisRuleArr, $this->rules);
0 ignored issues
show
Documentation Bug introduced by
It seems like array_merge($thisRuleArr, $this->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...
411
        }
412
413
        $this->validationMessages = $messages;
414
415
        return $this;
416
    }
417
418
    /**
419
     * Get field validation rules.
420
     *
421
     * @return string
422
     */
423
    protected function getRules()
424
    {
425
        if ($this->rules instanceof \Closure) {
426
            return $this->rules->call($this, $this->form);
427
        }
428
429
        return $this->rules;
430
    }
431
432
    /**
433
     * Remove a specific rule.
434
     *
435
     * @param string $rule
436
     *
437
     * @return void
438
     */
439
    protected function removeRule($rule)
440
    {
441
        $this->rules = str_replace($rule, '', $this->rules);
442
    }
443
444
    /**
445
     * Set field validator.
446
     *
447
     * @param callable $validator
448
     *
449
     * @return $this
450
     */
451
    public function validator(callable $validator)
452
    {
453
        $this->validator = $validator;
454
455
        return $this;
456
    }
457
458
    /**
459
     * Get key for error message.
460
     *
461
     * @return string
462
     */
463
    public function getErrorKey()
464
    {
465
        return $this->errorKey ?: $this->column;
466
    }
467
468
    /**
469
     * Set key for error message.
470
     *
471
     * @param string $key
472
     *
473
     * @return $this
474
     */
475
    public function setErrorKey($key)
476
    {
477
        $this->errorKey = $key;
478
479
        return $this;
480
    }
481
482
    /**
483
     * Set or get value of the field.
484
     *
485
     * @param null $value
486
     *
487
     * @return mixed
488
     */
489 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...
490
    {
491
        if (is_null($value)) {
492
            return is_null($this->value) ? $this->getDefault() : $this->value;
493
        }
494
495
        $this->value = $value;
496
497
        return $this;
498
    }
499
500
    /**
501
     * Set default value for field.
502
     *
503
     * @param $default
504
     *
505
     * @return $this
506
     */
507
    public function default($default)
0 ignored issues
show
Coding Style introduced by
Possible parse error: non-abstract method defined as abstract
Loading history...
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
508
    {
509
        $this->default = $default;
510
511
        return $this;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $this.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
512
    }
513
514
    /**
515
     * Get default value.
516
     *
517
     * @return mixed
518
     */
519
    public function getDefault()
520
    {
521
        if ($this->default instanceof \Closure) {
522
            return call_user_func($this->default, $this->form);
523
        }
524
525
        return $this->default;
526
    }
527
528
    /**
529
     * Set help block for current field.
530
     *
531
     * @param string $text
532
     * @param string $icon
533
     *
534
     * @return $this
535
     */
536
    public function help($text = '', $icon = 'fa-info-circle')
537
    {
538
        $this->help = compact('text', 'icon');
539
540
        return $this;
541
    }
542
543
    /**
544
     * Get column of the field.
545
     *
546
     * @return string|array
547
     */
548
    public function column()
549
    {
550
        return $this->column;
551
    }
552
553
    /**
554
     * Get label of the field.
555
     *
556
     * @return string
557
     */
558
    public function label()
559
    {
560
        return $this->label;
561
    }
562
563
    /**
564
     * Get original value of the field.
565
     *
566
     * @return mixed
567
     */
568
    public function original()
569
    {
570
        return $this->original;
571
    }
572
573
    /**
574
     * Get validator for this field.
575
     *
576
     * @param array $input
577
     *
578
     * @return bool|Validator
579
     */
580
    public function getValidator(array $input)
581
    {
582
        if ($this->validator) {
583
            return $this->validator->call($this, $input);
584
        }
585
586
        $rules = $attributes = [];
587
588
        if (!$fieldRules = $this->getRules()) {
589
            return false;
590
        }
591
592
        if (is_string($this->column)) {
593
            if (!array_has($input, $this->column)) {
594
                return false;
595
            }
596
597
            $input = $this->sanitizeInput($input, $this->column);
598
599
            $rules[$this->column] = $fieldRules;
600
            $attributes[$this->column] = $this->label;
601
        }
602
603
        if (is_array($this->column)) {
604
            foreach ($this->column as $key => $column) {
605
                if (!array_key_exists($column, $input)) {
606
                    continue;
607
                }
608
                $input[$column.$key] = array_get($input, $column);
609
                $rules[$column.$key] = $fieldRules;
610
                $attributes[$column.$key] = $this->label."[$column]";
611
            }
612
        }
613
614
        return Validator::make($input, $rules, $this->validationMessages, $attributes);
615
    }
616
617
    /**
618
     * Sanitize input data.
619
     *
620
     * @param array  $input
621
     * @param string $column
622
     *
623
     * @return array
624
     */
625
    protected function sanitizeInput($input, $column)
626
    {
627
        if ($this instanceof Field\MultipleSelect) {
628
            $value = array_get($input, $column);
629
            array_set($input, $column, array_filter($value));
630
        }
631
632
        return $input;
633
    }
634
635
    /**
636
     * Add html attributes to elements.
637
     *
638
     * @param array|string $attribute
639
     * @param mixed        $value
640
     *
641
     * @return $this
642
     */
643
    public function attribute($attribute, $value = null)
644
    {
645
        if (is_array($attribute)) {
646
            $this->attributes = array_merge($this->attributes, $attribute);
647
        } else {
648
            $this->attributes[$attribute] = (string) $value;
649
        }
650
651
        return $this;
652
    }
653
654
    /**
655
     * Set the field as readonly mode.
656
     *
657
     * @return Field
658
     */
659
    public function readOnly()
660
    {
661
        return $this->attribute('disabled', true);
662
    }
663
664
    /**
665
     * Set field placeholder.
666
     *
667
     * @param string $placeholder
668
     *
669
     * @return Field
670
     */
671
    public function placeholder($placeholder = '')
672
    {
673
        $this->placeholder = $placeholder;
674
675
        return $this;
676
    }
677
678
    /**
679
     * Get placeholder.
680
     *
681
     * @return string
682
     */
683
    public function getPlaceholder()
684
    {
685
        return $this->placeholder ?: trans('admin.input').' '.$this->label;
686
    }
687
688
    /**
689
     * Prepare for a field value before update or insert.
690
     *
691
     * @param $value
692
     *
693
     * @return mixed
694
     */
695
    public function prepare($value)
696
    {
697
        return $value;
698
    }
699
700
    /**
701
     * Format the field attributes.
702
     *
703
     * @return string
704
     */
705
    protected function formatAttributes()
706
    {
707
        $html = [];
708
709
        foreach ($this->attributes as $name => $value) {
710
            $html[] = $name.'="'.e($value).'"';
711
        }
712
713
        return implode(' ', $html);
714
    }
715
716
    /**
717
     * @return $this
718
     */
719
    public function disableHorizontal()
720
    {
721
        $this->horizontal = false;
722
723
        return $this;
724
    }
725
726
    /**
727
     * @return array
728
     */
729
    public function getViewElementClasses()
730
    {
731
        if ($this->horizontal) {
732
            return [
733
                'label'      => "col-sm-{$this->width['label']}",
734
                'field'      => "col-sm-{$this->width['field']}",
735
                'form-group' => 'form-group ',
736
            ];
737
        }
738
739
        return ['label' => '', 'field' => '', 'form-group' => ''];
740
    }
741
742
    /**
743
     * Set form element class.
744
     *
745
     * @param string|array $class
746
     *
747
     * @return $this
748
     */
749
    public function setElementClass($class)
750
    {
751
        $this->elementClass = (array) $class;
752
753
        return $this;
754
    }
755
756
    /**
757
     * Get element class.
758
     *
759
     * @return array
760
     */
761
    protected function getElementClass()
762
    {
763
        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...
764
            $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...
765
766
            $this->elementClass = (array) str_replace(['[', ']'], '_', $name);
767
        }
768
769
        return $this->elementClass;
770
    }
771
772
    /**
773
     * Get element class string.
774
     *
775
     * @return mixed
776
     */
777 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...
778
    {
779
        $elementClass = $this->getElementClass();
780
781
        if (Arr::isAssoc($elementClass)) {
782
            $classes = [];
783
784
            foreach ($elementClass as $index => $class) {
785
                $classes[$index] = is_array($class) ? implode(' ', $class) : $class;
786
            }
787
788
            return $classes;
789
        }
790
791
        return implode(' ', $elementClass);
792
    }
793
794
    /**
795
     * Get element class selector.
796
     *
797
     * @return string
798
     */
799 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...
800
    {
801
        $elementClass = $this->getElementClass();
802
803
        if (Arr::isAssoc($elementClass)) {
804
            $classes = [];
805
806
            foreach ($elementClass as $index => $class) {
807
                $classes[$index] = '.'.(is_array($class) ? implode('.', $class) : $class);
808
            }
809
810
            return $classes;
811
        }
812
813
        return '.'.implode('.', $elementClass);
814
    }
815
816
    /**
817
     * Add the element class.
818
     *
819
     * @param $class
820
     *
821
     * @return $this
822
     */
823
    public function addElementClass($class)
824
    {
825
        if (is_array($class) || is_string($class)) {
826
            $this->elementClass = array_merge($this->elementClass, (array) $class);
827
828
            $this->elementClass = array_unique($this->elementClass);
829
        }
830
831
        return $this;
832
    }
833
834
    /**
835
     * Remove element class.
836
     *
837
     * @param $class
838
     *
839
     * @return $this
840
     */
841
    public function removeElementClass($class)
842
    {
843
        $delClass = [];
844
845
        if (is_string($class) || is_array($class)) {
846
            $delClass = (array) $class;
847
        }
848
849
        foreach ($delClass as $del) {
850
            if (($key = array_search($del, $this->elementClass))) {
851
                unset($this->elementClass[$key]);
852
            }
853
        }
854
855
        return $this;
856
    }
857
858
    /**
859
     * Get the view variables of this field.
860
     *
861
     * @return array
862
     */
863
    protected function variables()
864
    {
865
        return array_merge($this->variables, [
866
            'id'          => $this->id,
867
            '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...
868
            'help'        => $this->help,
869
            'class'       => $this->getElementClassString(),
870
            'value'       => $this->value(),
871
            'label'       => $this->label,
872
            'viewClass'   => $this->getViewElementClasses(),
873
            'column'      => $this->column,
874
            'errorKey'    => $this->getErrorKey(),
875
            'attributes'  => $this->formatAttributes(),
876
            'placeholder' => $this->getPlaceholder(),
877
        ]);
878
    }
879
880
    /**
881
     * Get view of this field.
882
     *
883
     * @return string
884
     */
885
    public function getView()
886
    {
887
        if (!empty($this->view)) {
888
            return $this->view;
889
        }
890
891
        $class = explode('\\', get_called_class());
892
893
        return 'admin::form.'.strtolower(end($class));
894
    }
895
896
    /**
897
     * Get script of current field.
898
     *
899
     * @return string
900
     */
901
    public function getScript()
902
    {
903
        return $this->script;
904
    }
905
906
    /**
907
     * Render this filed.
908
     *
909
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
910
     */
911
    public function render()
912
    {
913
        Admin::script($this->script);
914
915
        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 915 which is incompatible with the return type declared by the interface Illuminate\Contracts\Support\Renderable::render of type string.
Loading history...
916
    }
917
918
    /**
919
     * @return string
920
     */
921
    public function __toString()
922
    {
923
        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...
924
    }
925
}
926