Completed
Pull Request — master (#1281)
by
unknown
02:32
created

Field::getValidator()   C

Complexity

Conditions 8
Paths 7

Size

Total Lines 36
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 20
nc 7
nop 1
dl 0
loc 36
rs 5.3846
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 919.

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