Completed
Pull Request — master (#2175)
by m
07:23 queued 01:22
created

Field::setLabelClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 7
rs 10
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 16 and the first side effect is on line 979.

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
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
     * Validation rules.
94
     *
95
     * @var string|\Closure
96
     */
97
    protected $rules = '';
98
99
    /**
100
     * @var callable
101
     */
102
    protected $validator;
103
104
    /**
105
     * Validation messages.
106
     *
107
     * @var array
108
     */
109
    protected $validationMessages = [];
110
111
    /**
112
     * Css required by this field.
113
     *
114
     * @var array
115
     */
116
    protected static $css = [];
117
118
    /**
119
     * Js required by this field.
120
     *
121
     * @var array
122
     */
123
    protected static $js = [];
124
125
    /**
126
     * Script for field.
127
     *
128
     * @var string
129
     */
130
    protected $script = '';
131
132
    /**
133
     * Element attributes.
134
     *
135
     * @var array
136
     */
137
    protected $attributes = [];
138
139
    /**
140
     * Parent form.
141
     *
142
     * @var Form
143
     */
144
    protected $form = null;
145
146
    /**
147
     * View for field to render.
148
     *
149
     * @var string
150
     */
151
    protected $view = '';
152
153
    /**
154
     * Help block.
155
     *
156
     * @var array
157
     */
158
    protected $help = [];
159
160
    /**
161
     * Key for errors.
162
     *
163
     * @var mixed
164
     */
165
    protected $errorKey;
166
167
    /**
168
     * Placeholder for this field.
169
     *
170
     * @var string|array
171
     */
172
    protected $placeholder;
173
174
    /**
175
     * Width for label and field.
176
     *
177
     * @var array
178
     */
179
    protected $width
180
        = [
181
            'label' => 2,
182
            'field' => 8,
183
        ];
184
185
    /**
186
     * If the form horizontal layout.
187
     *
188
     * @var bool
189
     */
190
    protected $horizontal = true;
191
192
    /**
193
     * @var bool
194
     */
195
    protected $display = true;
196
197
    /**
198
     * @var array
199
     */
200
    protected $labelClass = [];
201
202
    /**
203
     * Field constructor.
204
     *
205
     * @param       $column
206
     * @param array $arguments
207
     */
208
    public function __construct($column, $arguments = [])
209
    {
210
        $this->column = $column;
211
        $this->label = $this->formatLabel($arguments);
212
        $this->id = $this->formatId($column);
213
    }
214
215
    /**
216
     * Get assets required by this field.
217
     *
218
     * @return array
219
     */
220
    public static function getAssets()
221
    {
222
        return [
223
            'css' => static::$css,
224
            'js'  => static::$js,
225
        ];
226
    }
227
228
    /**
229
     * Format the field element id.
230
     *
231
     * @param string|array $column
232
     *
233
     * @return string|array
234
     */
235
    protected function formatId($column)
236
    {
237
        return str_replace('.', '_', $column);
238
    }
239
240
    /**
241
     * Format the label value.
242
     *
243
     * @param array $arguments
244
     *
245
     * @return string
246
     */
247
    protected function formatLabel($arguments = [])
248
    {
249
        $column = is_array($this->column) ? current($this->column) : $this->column;
250
251
        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($column);
252
253
        return str_replace(['.', '_'], ' ', $label);
254
    }
255
256
    /**
257
     * Format the name of the field.
258
     *
259
     * @param string $column
260
     *
261
     * @return array|mixed|string
262
     */
263
    protected function formatName($column)
264
    {
265
        if (is_string($column)) {
266
            $name = explode('.', $column);
267
268
            if (count($name) == 1) {
269
                return $name[0];
270
            }
271
272
            $html = array_shift($name);
273
            foreach ($name as $piece) {
274
                $html .= "[$piece]";
275
            }
276
277
            return $html;
278
        }
279
280
        if (is_array($this->column)) {
281
            $names = [];
282
            foreach ($this->column as $key => $name) {
283
                $names[$key] = $this->formatName($name);
284
            }
285
286
            return $names;
287
        }
288
289
        return '';
290
    }
291
292
    /**
293
     * Set form element name.
294
     *
295
     * @param string $name
296
     *
297
     * @return $this
298
     *
299
     * @author Edwin Hui
300
     */
301
    public function setElementName($name)
302
    {
303
        $this->elementName = $name;
304
305
        return $this;
306
    }
307
308
    /**
309
     * Fill data to the field.
310
     *
311
     * @param array $data
312
     *
313
     * @return void
314
     */
315 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...
316
    {
317
        // 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...
318
//        if (!is_null($this->value)) {
319
//            return;
320
//        }
321
322
        if (is_array($this->column)) {
323
            foreach ($this->column as $key => $column) {
324
                $this->value[$key] = array_get($data, $column);
325
            }
326
327
            return;
328
        }
329
330
        $this->value = array_get($data, $this->column);
331
    }
332
333
    /**
334
     * Set original value to the field.
335
     *
336
     * @param array $data
337
     *
338
     * @return void
339
     */
340 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...
341
    {
342
        if (is_array($this->column)) {
343
            foreach ($this->column as $key => $column) {
344
                $this->original[$key] = array_get($data, $column);
345
            }
346
347
            return;
348
        }
349
350
        $this->original = array_get($data, $this->column);
351
    }
352
353
    /**
354
     * @param Form $form
355
     *
356
     * @return $this
357
     */
358
    public function setForm(Form $form = null)
359
    {
360
        $this->form = $form;
361
362
        return $this;
363
    }
364
365
    /**
366
     * Set width for field and label.
367
     *
368
     * @param int $field
369
     * @param int $label
370
     *
371
     * @return $this
372
     */
373
    public function setWidth($field = 8, $label = 2)
374
    {
375
        $this->width = [
376
            'label' => $label,
377
            'field' => $field,
378
        ];
379
380
        return $this;
381
    }
382
383
    /**
384
     * Set the field options.
385
     *
386
     * @param array $options
387
     *
388
     * @return $this
389
     */
390 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...
391
    {
392
        if ($options instanceof Arrayable) {
393
            $options = $options->toArray();
394
        }
395
396
        $this->options = array_merge($this->options, $options);
397
398
        return $this;
399
    }
400
401
    /**
402
     * Get or set rules.
403
     *
404
     * @param null  $rules
405
     * @param array $messages
406
     *
407
     * @return $this
408
     */
409
    public function rules($rules = null, $messages = [])
410
    {
411
        if ($rules instanceof \Closure) {
412
            $this->rules = $rules;
413
        }
414
415
        if (is_array($rules)) {
416
            $thisRuleArr = array_filter(explode('|', $this->rules));
417
418
            $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...
419
        } elseif (is_string($rules)) {
420
            $rules = array_filter(explode('|', "{$this->rules}|$rules"));
421
422
            $this->rules = implode('|', $rules);
423
        }
424
425
        $this->validationMessages = $messages;
426
427
        return $this;
428
    }
429
430
    /**
431
     * Get field validation rules.
432
     *
433
     * @return string
434
     */
435
    protected function getRules()
436
    {
437
        if ($this->rules instanceof \Closure) {
438
            return $this->rules->call($this, $this->form);
439
        }
440
441
        return $this->rules;
442
    }
443
444
    /**
445
     * Remove a specific rule.
446
     *
447
     * @param string $rule
448
     *
449
     * @return void
450
     */
451
    protected function removeRule($rule)
452
    {
453
        $this->rules = str_replace($rule, '', $this->rules);
454
    }
455
456
    /**
457
     * Set field validator.
458
     *
459
     * @param callable $validator
460
     *
461
     * @return $this
462
     */
463
    public function validator(callable $validator)
464
    {
465
        $this->validator = $validator;
466
467
        return $this;
468
    }
469
470
    /**
471
     * Get key for error message.
472
     *
473
     * @return string
474
     */
475
    public function getErrorKey()
476
    {
477
        return $this->errorKey ?: $this->column;
478
    }
479
480
    /**
481
     * Set key for error message.
482
     *
483
     * @param string $key
484
     *
485
     * @return $this
486
     */
487
    public function setErrorKey($key)
488
    {
489
        $this->errorKey = $key;
490
491
        return $this;
492
    }
493
494
    /**
495
     * Set or get value of the field.
496
     *
497
     * @param null $value
498
     *
499
     * @return mixed
500
     */
501 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...
502
    {
503
        if (is_null($value)) {
504
            return is_null($this->value) ? $this->getDefault() : $this->value;
505
        }
506
507
        $this->value = $value;
508
509
        return $this;
510
    }
511
512
    /**
513
     * Set default value for field.
514
     *
515
     * @param $default
516
     *
517
     * @return $this
518
     */
519
    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...
520
    {
521
        $this->default = $default;
522
523
        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...
524
    }
525
526
    /**
527
     * Get default value.
528
     *
529
     * @return mixed
530
     */
531
    public function getDefault()
532
    {
533
        if ($this->default instanceof \Closure) {
534
            return call_user_func($this->default, $this->form);
535
        }
536
537
        return $this->default;
538
    }
539
540
    /**
541
     * Set help block for current field.
542
     *
543
     * @param string $text
544
     * @param string $icon
545
     *
546
     * @return $this
547
     */
548
    public function help($text = '', $icon = 'fa-info-circle')
549
    {
550
        $this->help = compact('text', 'icon');
551
552
        return $this;
553
    }
554
555
    /**
556
     * Get column of the field.
557
     *
558
     * @return string|array
559
     */
560
    public function column()
561
    {
562
        return $this->column;
563
    }
564
565
    /**
566
     * Get label of the field.
567
     *
568
     * @return string
569
     */
570
    public function label()
571
    {
572
        return $this->label;
573
    }
574
575
    /**
576
     * Get original value of the field.
577
     *
578
     * @return mixed
579
     */
580
    public function original()
581
    {
582
        return $this->original;
583
    }
584
585
    /**
586
     * Get validator for this field.
587
     *
588
     * @param array $input
589
     *
590
     * @return bool|Validator
591
     */
592
    public function getValidator(array $input)
593
    {
594
        if ($this->validator) {
595
            return $this->validator->call($this, $input);
596
        }
597
598
        $rules = $attributes = [];
599
600
        if (!$fieldRules = $this->getRules()) {
601
            return false;
602
        }
603
604
        if (is_string($this->column)) {
605
            if (!array_has($input, $this->column)) {
606
                return false;
607
            }
608
609
            $input = $this->sanitizeInput($input, $this->column);
610
611
            $rules[$this->column] = $fieldRules;
612
            $attributes[$this->column] = $this->label;
613
        }
614
615
        if (is_array($this->column)) {
616
            foreach ($this->column as $key => $column) {
617
                if (!array_key_exists($column, $input)) {
618
                    continue;
619
                }
620
                $input[$column.$key] = array_get($input, $column);
621
                $rules[$column.$key] = $fieldRules;
622
                $attributes[$column.$key] = $this->label."[$column]";
623
            }
624
        }
625
626
        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...
627
    }
628
629
    /**
630
     * Sanitize input data.
631
     *
632
     * @param array  $input
633
     * @param string $column
634
     *
635
     * @return array
636
     */
637
    protected function sanitizeInput($input, $column)
638
    {
639
        if ($this instanceof Field\MultipleSelect) {
640
            $value = array_get($input, $column);
641
            array_set($input, $column, array_filter($value));
642
        }
643
644
        return $input;
645
    }
646
647
    /**
648
     * Add html attributes to elements.
649
     *
650
     * @param array|string $attribute
651
     * @param mixed        $value
652
     *
653
     * @return $this
654
     */
655
    public function attribute($attribute, $value = null)
656
    {
657
        if (is_array($attribute)) {
658
            $this->attributes = array_merge($this->attributes, $attribute);
659
        } else {
660
            $this->attributes[$attribute] = (string) $value;
661
        }
662
663
        return $this;
664
    }
665
666
    /**
667
     * Set the field as readonly mode.
668
     *
669
     * @return Field
670
     */
671
    public function readOnly()
672
    {
673
        return $this->attribute('disabled', true);
674
    }
675
676
    /**
677
     * Set field placeholder.
678
     *
679
     * @param string $placeholder
680
     *
681
     * @return Field
682
     */
683
    public function placeholder($placeholder = '')
684
    {
685
        $this->placeholder = $placeholder;
686
687
        return $this;
688
    }
689
690
    /**
691
     * Get placeholder.
692
     *
693
     * @return string
694
     */
695
    public function getPlaceholder()
696
    {
697
        return $this->placeholder ?: trans('admin.input').' '.$this->label;
698
    }
699
700
    /**
701
     * Prepare for a field value before update or insert.
702
     *
703
     * @param $value
704
     *
705
     * @return mixed
706
     */
707
    public function prepare($value)
708
    {
709
        return $value;
710
    }
711
712
    /**
713
     * Format the field attributes.
714
     *
715
     * @return string
716
     */
717
    protected function formatAttributes()
718
    {
719
        $html = [];
720
721
        foreach ($this->attributes as $name => $value) {
722
            $html[] = $name.'="'.e($value).'"';
723
        }
724
725
        return implode(' ', $html);
726
    }
727
728
    /**
729
     * @return $this
730
     */
731
    public function disableHorizontal()
732
    {
733
        $this->horizontal = false;
734
735
        return $this;
736
    }
737
738
    /**
739
     * @return array
740
     */
741
    public function getViewElementClasses()
742
    {
743
        if ($this->horizontal) {
744
            return [
745
                'label'      => "col-sm-{$this->width['label']} {$this->getLabelClass()}",
746
                'field'      => "col-sm-{$this->width['field']}",
747
                'form-group' => 'form-group ',
748
            ];
749
        }
750
751
        return ['label' => "{$this->getLabelClass()}", 'field' => '', 'form-group' => ''];
752
    }
753
754
    /**
755
     * Set form element class.
756
     *
757
     * @param string|array $class
758
     *
759
     * @return $this
760
     */
761
    public function setElementClass($class)
762
    {
763
        $this->elementClass = (array) $class;
764
765
        return $this;
766
    }
767
768
    /**
769
     * Get element class.
770
     *
771
     * @return array
772
     */
773
    protected function getElementClass()
774
    {
775
        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...
776
            $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...
777
778
            $this->elementClass = (array) str_replace(['[', ']'], '_', $name);
779
        }
780
781
        return $this->elementClass;
782
    }
783
784
    /**
785
     * Get element class string.
786
     *
787
     * @return mixed
788
     */
789 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...
790
    {
791
        $elementClass = $this->getElementClass();
792
793
        if (Arr::isAssoc($elementClass)) {
794
            $classes = [];
795
796
            foreach ($elementClass as $index => $class) {
797
                $classes[$index] = is_array($class) ? implode(' ', $class) : $class;
798
            }
799
800
            return $classes;
801
        }
802
803
        return implode(' ', $elementClass);
804
    }
805
806
    /**
807
     * Get element class selector.
808
     *
809
     * @return string
810
     */
811 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...
812
    {
813
        $elementClass = $this->getElementClass();
814
815
        if (Arr::isAssoc($elementClass)) {
816
            $classes = [];
817
818
            foreach ($elementClass as $index => $class) {
819
                $classes[$index] = '.'.(is_array($class) ? implode('.', $class) : $class);
820
            }
821
822
            return $classes;
823
        }
824
825
        return '.'.implode('.', $elementClass);
826
    }
827
828
    /**
829
     * Add the element class.
830
     *
831
     * @param $class
832
     *
833
     * @return $this
834
     */
835
    public function addElementClass($class)
836
    {
837
        if (is_array($class) || is_string($class)) {
838
            $this->elementClass = array_merge($this->elementClass, (array) $class);
839
840
            $this->elementClass = array_unique($this->elementClass);
841
        }
842
843
844
845
        return $this;
846
    }
847
848
    /**
849
     * Remove element class.
850
     *
851
     * @param $class
852
     *
853
     * @return $this
854
     */
855
    public function removeElementClass($class)
856
    {
857
        $delClass = [];
858
859
        if (is_string($class) || is_array($class)) {
860
            $delClass = (array) $class;
861
        }
862
863
        foreach ($delClass as $del) {
864
            if (($key = array_search($del, $this->elementClass))) {
865
                unset($this->elementClass[$key]);
866
            }
867
        }
868
869
        return $this;
870
    }
871
872
    /**
873
     * Add variables to field view.
874
     *
875
     * @param array $variables
876
     *
877
     * @return $this
878
     */
879
    protected function addVariables(array $variables = [])
880
    {
881
        $this->variables = array_merge($this->variables, $variables);
882
883
        return $this;
884
    }
885
886
    /**
887
     * @return string
888
     */
889
    public function getLabelClass()
890
    : string
891
    {
892
        return implode(' ', $this->labelClass);
893
    }
894
895
    /**
896
     * @param array $labelClass
897
     *
898
     * @return self
899
     */
900
    public function setLabelClass(array $labelClass)
901
    : self
902
    {
903
        $this->labelClass = $labelClass;
904
905
        return $this;
906
    }
907
908
    /**
909
     * Get the view variables of this field.
910
     *
911
     * @return array
912
     */
913
    protected function variables()
914
    {
915
        return array_merge($this->variables, [
916
            'id'          => $this->id,
917
            '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...
918
            'help'        => $this->help,
919
            'class'       => $this->getElementClassString(),
920
            'value'       => $this->value(),
921
            'label'       => $this->label,
922
            'viewClass'   => $this->getViewElementClasses(),
923
            'column'      => $this->column,
924
            'errorKey'    => $this->getErrorKey(),
925
            'attributes'  => $this->formatAttributes(),
926
            'placeholder' => $this->getPlaceholder(),
927
        ]);
928
    }
929
930
    /**
931
     * Get view of this field.
932
     *
933
     * @return string
934
     */
935
    public function getView()
936
    {
937
        if (!empty($this->view)) {
938
            return $this->view;
939
        }
940
941
        $class = explode('\\', get_called_class());
942
943
        return 'admin::form.'.strtolower(end($class));
944
    }
945
946
    /**
947
     * Get script of current field.
948
     *
949
     * @return string
950
     */
951
    public function getScript()
952
    {
953
        return $this->script;
954
    }
955
956
    /**
957
     * Render this filed.
958
     *
959
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
960
     */
961
    public function render()
962
    {
963
        if (!$this->display) {
964
            return '';
965
        }
966
967
        Admin::script($this->script);
968
969
        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 969 which is incompatible with the return type declared by the interface Illuminate\Contracts\Support\Renderable::render of type string.
Loading history...
970
    }
971
972
    /**
973
     * @return string
974
     */
975
    public function __toString()
976
    {
977
        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...
978
    }
979
}
980