Passed
Push — master ( 0f6000...a12786 )
by Alexander
12:49
created

Field::file()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 3
dl 0
loc 7
ccs 6
cts 6
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Definitions\Exception\CircularReferenceException;
9
use Yiisoft\Definitions\Exception\InvalidConfigException;
10
use Yiisoft\Definitions\Exception\NotInstantiableException;
11
use Yiisoft\Factory\NotFoundException;
12
use Yiisoft\Form\FormModelInterface;
13
use Yiisoft\Form\Widget\Attribute\ButtonAttributes;
14
use Yiisoft\Form\Widget\Attribute\FieldAttributes;
15
use Yiisoft\Form\Widget\Attribute\InputAttributes;
16
use Yiisoft\Form\Widget\Attribute\GlobalAttributes;
17
use Yiisoft\Form\Widget\Attribute\PlaceholderInterface;
18
use Yiisoft\Form\Widget\Attribute\WidgetAttributes;
19
use Yiisoft\Form\Widget\FieldPart\Error;
20
use Yiisoft\Form\Widget\FieldPart\Hint;
21
use Yiisoft\Form\Widget\FieldPart\Label;
22
use Yiisoft\Html\Html;
23
use Yiisoft\Html\Tag\Div;
24
25
use function array_key_exists;
26
use function array_merge;
27
use function strtr;
28
29
/**
30
 * Renders the field widget along with label and hint tag (if any) according to template.
31
 *
32
 * @psalm-suppress MissingConstructor
33
 */
34
final class Field extends FieldAttributes
35
{
36
    private ButtonAttributes $button;
37
    private array $parts = [];
38
    private WidgetAttributes $inputWidget;
39
    private GlobalAttributes $widget;
40
41
    /**
42
     * Renders a button group widget.
43
     *
44
     * @param array $buttons List of buttons. Each array element represents a single button which can be specified as a
45
     * string or an array of the following structure:
46
     * - label: string, required, the button label.
47
     * - attributes: array, optional, the HTML attributes of the button.
48
     * - type: string, optional, the button type.
49
     * - visible: bool, optional, whether this button is visible. Defaults to true.
50
     * @param array $config the configuration array for widget factory.
51
     * @param array $attributes the HTML attributes for the widget.
52
     *
53
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
54
     *
55
     * @return self the field object itself.
56
     *
57
     * @psalm-param array<string, array|string> $buttons
58
     */
59 11
    public function buttonGroup(array $buttons, array $config = [], array $attributes = []): self
60
    {
61 11
        $new = clone $this;
62 11
        $new = $new->type('buttonGroup');
63 11
        $config = array_merge($new->getDefinitions(), $config);
64 11
        $new->button = ButtonGroup::widget($config)->attributes($attributes)->buttons($buttons);
65 11
        return $new;
66
    }
67
68
    /**
69
     * Renders a checkbox.
70
     *
71
     * This method will generate the `checked` tag attribute according to the model attribute value.
72
     *
73
     * @param FormModelInterface $formModel The model object.
74
     * @param string $attribute The attribute name or expression.
75
     * @param array $config The configuration array for widget factory.
76
     * Available methods:
77
     * [
78
     *     'enclosedByLabel()' => [false],
79
     *     'label()' => ['test-text-label'],
80
     *     'labelAttributes()' => [['class' => 'test-class']],
81
     *     'uncheckValue()' => ['0'],
82
     * ]
83
     *
84
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
85
     *
86
     * @return self the field widget instance.
87
     */
88 21
    public function checkbox(FormModelInterface $formModel, string $attribute, array $config = []): self
89
    {
90 21
        $new = clone $this;
91 21
        $new = $new->type('checkbox');
92 21
        $config = array_merge($new->getDefinitions(), $config);
93
94
        /** @var array */
95 21
        $enclosedByLabel = $config['enclosedByLabel()'] ?? [true];
96
97 21
        if ($enclosedByLabel === [true]) {
98 20
            $new->parts['{label}'] = '';
99
        }
100
101 21
        $new->inputWidget = Checkbox::widget($config)->for($formModel, $attribute);
0 ignored issues
show
Bug introduced by
The method for() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of Yiisoft\Widget\Widget such as Yiisoft\Form\Widget\FieldPart\Hint or Yiisoft\Form\Widget\FieldPart\Label or Yiisoft\Form\Widget\FieldPart\Error or Yiisoft\Form\Widget\Attribute\WidgetAttributes. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

101
        $new->inputWidget = Checkbox::widget($config)->/** @scrutinizer ignore-call */ for($formModel, $attribute);
Loading history...
102 21
        return $new;
103
    }
104
105
    /**
106
     * Renders a list of checkboxes.
107
     *
108
     * A checkbox list allows multiple selection, As a result, the corresponding submitted value is an array.
109
     *
110
     * The selection of the checkbox list is taken from the value of the model attribute.
111
     *
112
     * @param FormModelInterface $formModel The model object.
113
     * @param string $attribute The attribute name or expression.
114
     * @param array $config the configuration array for widget factory.
115
     * Available methods:
116
     * [
117
     *     'containerAttributes()' => [['class' => 'test-class']],
118
     *     'containerTag()' => ['span'],
119
     *     'individualItemsAttributes()' => [[1 => ['disabled' => true], 2 => ['class' => 'test-class']],
120
     *     'items()' => [[1 => 'Female', 2 => 'Male']],
121
     *     'itemsAttributes()' => [['disabled' => true],
122
     *     'itemsFormatter()' => [
123
     *         static function (CheckboxItem $item) {
124
     *             return $item->checked
125
     *                 ? "<label><input type='checkbox' name='$item->name' value='$item->value' checked> $item->label</label>"
126
     *                 : "<label><input type='checkbox' name='$item->name' value='$item->value'> $item->label</label>";
127
     *         },
128
     *     ],
129
     *     'itemsFromValues()' => [[1 => 'Female', 2 => 'Male']],
130
     *     'separator()' => ['&#9866;'],
131
     * ]
132
     *
133
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
134
     *
135
     * @return self the field widget instance.
136
     */
137 19
    public function checkboxList(FormModelInterface $formModel, string $attribute, array $config = []): self
138
    {
139 19
        $new = clone $this;
140 19
        $new = $new->type('checkboxList');
141 19
        $config = array_merge($new->getDefinitions(), $config);
142 19
        $new->inputWidget = CheckboxList::widget($config)->for($formModel, $attribute);
143 19
        return $new;
144
    }
145
146
    /**
147
     * Renders a date widget.
148
     *
149
     * @param FormModelInterface $formModel The model object.
150
     * @param string $attribute The attribute name or expression.
151
     * @param array $config the configuration array for widget factory.
152
     *
153
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
154
     *
155
     * @return self the field widget instance.
156
     */
157 15
    public function date(FormModelInterface $formModel, string $attribute, array $config = []): self
158
    {
159 15
        $new = clone $this;
160 15
        $new = $new->type('date');
161 15
        $config = array_merge($new->getDefinitions(), $config);
162 15
        $new->inputWidget = Date::widget($config)->for($formModel, $attribute);
163 15
        return $new;
164
    }
165
166
    /**
167
     * Renders a date time widget.
168
     *
169
     * @param FormModelInterface $formModel The model object.
170
     * @param string $attribute The attribute name or expression.
171
     * @param array $config the configuration array for widget factory.
172
     *
173
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
174
     *
175
     * @return self the field widget instance.
176
     */
177 16
    public function dateTime(FormModelInterface $formModel, string $attribute, array $config = []): self
178
    {
179 16
        $new = clone $this;
180 16
        $new = $new->type('dateTime');
181 16
        $config = array_merge($new->getDefinitions(), $config);
182 16
        $new->inputWidget = DateTime::widget($config)->for($formModel, $attribute);
183 16
        return $new;
184
    }
185
186
    /**
187
     * Renders a date time local widget.
188
     *
189
     * @param FormModelInterface $formModel The model object.
190
     * @param string $attribute The attribute name or expression.
191
     * @param array $config the configuration array for widget factory.
192
     *
193
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
194
     *
195
     * @return self the field widget instance.
196
     */
197 17
    public function dateTimeLocal(FormModelInterface $formModel, string $attribute, array $config = []): self
198
    {
199 17
        $new = clone $this;
200 17
        $new = $new->type('dateTimeLocal');
201 17
        $config = array_merge($new->getDefinitions(), $config);
202 17
        $new->inputWidget = DateTimeLocal::widget($config)->for($formModel, $attribute);
203 17
        return $new;
204
    }
205
206
    /**
207
     * Renders a email widget.
208
     *
209
     * @param FormModelInterface $formModel The model object.
210
     * @param string $attribute The attribute name or expression.
211
     * @param array $config the configuration array for widget factory.
212
     *
213
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
214
     *
215
     * @return self the field widget instance.
216
     */
217 23
    public function email(FormModelInterface $formModel, string $attribute, array $config = []): self
218
    {
219 23
        $new = clone $this;
220 23
        $new = $new->type('email');
221 23
        $config = array_merge($new->getDefinitions(), $config);
222 23
        $new->inputWidget = Email::widget($config)->for($formModel, $attribute);
223 23
        return $new;
224
    }
225
226
    /**
227
     * Renders a file widget.
228
     *
229
     * @param FormModelInterface $formModel The model object.
230
     * @param string $attribute The attribute name or expression.
231
     * @param array $config the configuration array for widget factory.
232
     * Available methods:
233
     * [
234
     *     'hiddenAttributes()' => [['id' => 'test-id']],
235
     *     'uncheckValue()' => ['0'],
236
     *
237
     * ]
238
     *
239
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
240
     *
241
     * @return self the field widget instance.
242
     */
243 14
    public function file(FormModelInterface $formModel, string $attribute, array $config = []): self
244
    {
245 14
        $new = clone $this;
246 14
        $new = $new->type('file');
247 14
        $config = array_merge($new->getDefinitions(), $config);
248 14
        $new->inputWidget = File::widget($config)->for($formModel, $attribute);
249 14
        return $new;
250
    }
251
252
    /**
253
     * Renders a hidden widget.
254
     *
255
     * @param FormModelInterface $formModel The model object.
256
     * @param string $attribute The attribute name or expression.
257
     * @param array $config the configuration array for widget factory.
258
     *
259
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
260
     *
261
     * @return self the field widget instance.
262
     */
263 5
    public function hidden(FormModelInterface $formModel, string $attribute, array $config = []): self
264
    {
265 5
        $new = clone $this;
266 5
        $new = $new->type('hidden');
267 5
        $new->parts['{label}'] = '';
268 5
        $new->parts['{hint}'] = '';
269 5
        $new->parts['{error}'] = '';
270 5
        $config = array_merge($new->getDefinitions(), $config);
271 5
        $new->inputWidget = Hidden::widget($config)->for($formModel, $attribute);
272 5
        return $new;
273
    }
274
275
    /**
276
     * Renders an image widget.
277
     *
278
     * @param array $config the configuration array for widget factory.
279
     * @param array $attributes the HTML attributes for the widget.
280
     * Most used attributes:
281
     * [
282
     *     'alt' => 'test-alt',
283
     *     'height' => '100%',
284
     *     'src' => 'test-src',
285
     *     'width' => '100%',
286
     * ]
287
     *
288
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
289
     *
290
     * @return self the field object itself.
291
     */
292 12
    public function image(array $config = [], array $attributes = []): self
293
    {
294 12
        $new = clone $this;
295 12
        $new = $new->type('image');
296 12
        $new->parts['{label}'] = '';
297 12
        $new->parts['{hint}'] = '';
298 12
        $new->parts['{error}'] = '';
299 12
        $config = array_merge($new->getDefinitions(), $config);
300 12
        $new->widget = Image::widget($config)->attributes($attributes);
301 12
        return $new;
302
    }
303
304
    /**
305
     * Renders a number widget.
306
     *
307
     * @param FormModelInterface $formModel The model object.
308
     * @param string $attribute The attribute name or expression.
309
     * @param array $config the configuration array for widget factory.
310
     *
311
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
312
     *
313
     * @return self the field object itself.
314
     */
315 18
    public function number(FormModelInterface $formModel, string $attribute, array $config = []): self
316
    {
317 18
        $new = clone $this;
318 18
        $new = $new->type('number');
319 18
        $config = array_merge($new->getDefinitions(), $config);
320 18
        $new->inputWidget = Number::widget($config)->for($formModel, $attribute);
321 18
        return $new;
322
    }
323
324
    /**
325
     * Renders a password widget.
326
     *
327
     * @param FormModelInterface $formModel The model object.
328
     * @param string $attribute The attribute name or expression.
329
     * @param array $config the configuration array for widget factory.
330
     *
331
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
332
     *
333
     * @return self the field object itself.
334
     */
335 21
    public function password(FormModelInterface $formModel, string $attribute, array $config = []): self
336
    {
337 21
        $new = clone $this;
338 21
        $new = $new->type('password');
339 21
        $config = array_merge($new->getDefinitions(), $config);
340 21
        $new->inputWidget = Password::widget($config)->for($formModel, $attribute);
341 21
        return $new;
342
    }
343
344
    /**
345
     * Renders a radio list widget.
346
     *
347
     * @param FormModelInterface $formModel The model object.
348
     * @param string $attribute The attribute name or expression.
349
     * @param array $config the configuration array for widget factory.
350
     * Available methods:
351
     * [
352
     *     'containerAttributes()' => [['class' => 'test-class']],
353
     *     'containerTag()' => ['span'],
354
     *     'items()' => [[1 => 'Female', 2 => 'Male']],
355
     *     'itemsAttributes()' => [['class' => 'test-class']],
356
     *     'individualItemsAttributes()' => [[1 => ['disabled' => true], 2 => ['class' => 'test-class']]],
357
     *     'itemsFormatter()' => [
358
     *         static function (RadioItem $item) {
359
     *             return $item->checked
360
     *                 ? "<label><input type='checkbox' name='$item->name' value='$item->value' checked> $item->label</label>"
361
     *                 : "<label><input type='checkbox' name='$item->name' value='$item->value'> $item->label</label>";
362
     *         },
363
     *     ],
364
     *     'itemsFromValues()' => [[1 => 'Female', 2 => 'Male']],
365
     *     'separator()' => [PHP_EOL],
366
     *     'uncheckValue()' => ['0'],
367
     * ]
368
     *
369
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
370
     *
371
     * @return self the field object itself.
372
     */
373 21
    public function radioList(FormModelInterface $formModel, string $attribute, array $config = []): self
374
    {
375 21
        $new = clone $this;
376 21
        $new = $new->type('radioList');
377 21
        $config = array_merge($new->getDefinitions(), $config);
378 21
        $new->inputWidget = RadioList::widget($config)->for($formModel, $attribute);
379 21
        return $new;
380
    }
381
382
    /**
383
     * Renders a range widget.
384
     *
385
     * @param FormModelInterface $formModel The model object.
386
     * @param string $attribute The attribute name or expression.
387
     * @param array $config the configuration array for widget factory.
388
     * Available methods:
389
     * [
390
     *     'outputTag()' => ['p'],
391
     *     'outputAttributes()' => [['class' => 'test-class']],
392
     * ]
393
     *
394
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
395
     *
396
     * @return self the field object itself.
397
     */
398 19
    public function range(FormModelInterface $formModel, string $attribute, array $config = []): self
399
    {
400 19
        $new = clone $this;
401 19
        $new = $new->type('range');
402 19
        $config = array_merge($new->getDefinitions(), $config);
403 19
        $new->inputWidget = Range::widget($config)->for($formModel, $attribute);
404 19
        return $new;
405
    }
406
407
    /**
408
     * Renders a reset button widget.
409
     *
410
     * @param array $config the configuration array for widget factory.
411
     * @param array $attributes the HTML attributes for the widget.
412
     *
413
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
414
     *
415
     * @return self the field object itself.
416
     */
417 9
    public function resetButton(array $config = [], array $attributes = []): self
418
    {
419 9
        $new = clone $this;
420 9
        $new = $new->type('reset');
421 9
        $config = array_merge($new->getDefinitions(), $config);
422 9
        $new->button = ResetButton::widget($config)->attributes($attributes);
423 9
        return $new;
424
    }
425
426
    /**
427
     * Renders a select widget.
428
     *
429
     * @param FormModelInterface $formModel The model object.
430
     * @param string $attribute The attribute name or expression.
431
     * @param array $config The configuration array for widget factory.
432
     * Available methods:
433
     * [
434
     *     'encode()' => [true],
435
     *     'groups()' => [['1' => ['2' => 'Moscu', '3' => 'San Petersburg']]],
436
     *     'items()' => [['1' => 'Moscu', '2' => 'San Petersburg']],
437
     *     'itemsAttributes()' => [['2' => ['disabled' => true]],
438
     *     'optionsData()' => [['1' => '<b>Moscu</b>', '2' => 'San Petersburg']],
439
     *     'prompt()' => [['text' => 'Select City Birth', 'attributes' => ['value' => '0', 'selected' => 'selected']]],
440
     *     'unselectValue()' => ['0'],
441
     * ]
442
     *
443
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
444
     *
445
     * @return self the field object itself.
446
     */
447 21
    public function select(FormModelInterface $formModel, string $attribute, array $config = []): self
448
    {
449 21
        $new = clone $this;
450 21
        $new = $new->type('select');
451 21
        $config = array_merge($new->getDefinitions(), $config);
452 21
        $new->inputWidget = Select::widget($config)->for($formModel, $attribute);
453 21
        return $new;
454
    }
455
456
    /**
457
     * Renders a submit button widget.
458
     *
459
     * @param array $config the configuration array for widget factory.
460
     * @param array $attributes the HTML attributes for the widget.
461
     *
462
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
463
     *
464
     * @return self the field object itself.
465
     */
466 19
    public function submitButton(array $config = [], array $attributes = []): self
467
    {
468 19
        $new = clone $this;
469 19
        $new = $new->type('submit');
470 19
        $config = array_merge($new->getDefinitions(), $config);
471 19
        $new->button = SubmitButton::widget($config)->attributes($attributes);
472 19
        return $new;
473
    }
474
475
    /**
476
     * Renders a text widget.
477
     *
478
     * @param FormModelInterface $formModel The model object.
479
     * @param string $attribute The attribute name or expression.
480
     * @param array $config the configuration array for widget factory.
481
     *
482
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
483
     *
484
     * @return self the field widget instance.
485
     */
486 21
    public function telephone(FormModelInterface $formModel, string $attribute, array $config = []): self
487
    {
488 21
        $new = clone $this;
489 21
        $new = $new->type('telephone');
490 21
        $config = array_merge($new->getDefinitions(), $config);
491 21
        $new->inputWidget = Telephone::widget($config)->for($formModel, $attribute);
492 21
        return $new;
493
    }
494
495
    /**
496
     * Renders a text widget.
497
     *
498
     * @param FormModelInterface $formModel The model object.
499
     * @param string $attribute The attribute name or expression.
500
     * @param array $config the configuration array for widget factory.
501
     *
502
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
503
     *
504
     * @return self the field widget instance.
505
     */
506 65
    public function text(FormModelInterface $formModel, string $attribute, array $config = []): self
507
    {
508 65
        $new = clone $this;
509 65
        $new = $new->type('text');
510 65
        $config = array_merge($new->getDefinitions(), $config);
511 65
        $new->inputWidget = Text::widget($config)->for($formModel, $attribute);
512 64
        return $new;
513
    }
514
515
    /**
516
     * Renders a text area widget.
517
     *
518
     * @param FormModelInterface $formModel The model object.
519
     * @param string $attribute The attribute name or expression.
520
     * @param array $config the configuration array for widget factory.
521
     *
522
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
523
     *
524
     * @return self the field widget instance.
525
     */
526 26
    public function textArea(FormModelInterface $formModel, string $attribute, array $config = []): self
527
    {
528 26
        $new = clone $this;
529 26
        $new = $new->type('textArea');
530 26
        $config = array_merge($new->getDefinitions(), $config);
531 26
        $new->inputWidget = TextArea::widget($config)->for($formModel, $attribute);
532 24
        return $new;
533
    }
534
535
    /**
536
     * Renders a url widget.
537
     *
538
     * @param FormModelInterface $formModel The model object.
539
     * @param string $attribute The attribute name or expression.
540
     * @param array $config the configuration array for widget factory.
541
     *
542
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
543
     *
544
     * @return self the field widget instance.
545
     */
546 24
    public function url(FormModelInterface $formModel, string $attribute, array $config = []): self
547
    {
548 24
        $new = clone $this;
549 24
        $new = $new->type('url');
550 24
        $config = array_merge($new->getDefinitions(), $config);
551 24
        $new->inputWidget = Url::widget($config)->for($formModel, $attribute);
552 24
        return $new;
553
    }
554
555
    /**
556
     * Renders the whole field.
557
     *
558
     * This method will generate the label, input tag and hint tag (if any), and assemble them into HTML according to
559
     * {@see template}.
560
     *
561
     * If (not set), the default methods will be called to generate the label and input tag, and use them as the
562
     * content.
563
     *
564
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
565
     *
566
     * @return string the rendering result.
567
     */
568 409
    protected function run(): string
569
    {
570 409
        $content = '';
571
572 409
        $div = Div::tag();
573
574 409
        if (!empty($this->inputWidget)) {
575 359
            $content .= $this->renderInputWidget();
576
        }
577
578 392
        if (!empty($this->widget)) {
579 12
            $content .= $this->widget->attributes($this->getAttributes())->render();
580
        }
581
582 392
        if (!empty($this->button)) {
583 39
            $content .= $this->button->attributes($this->getAttributes())->render();
584
        }
585
586 392
        if ($this->getContainerClass() !== '') {
587 12
            $div = $div->class($this->getContainerClass());
588
        }
589
590 392
        if ($this->getContainerAttributes() !== []) {
591 9
            $div = $div->attributes($this->getContainerAttributes());
592
        }
593
594 392
        return $this->getContainer() ? $div->content(PHP_EOL . $content . PHP_EOL)->encode(false)->render() : $content;
595
    }
596
597 359
    private function buildField(): self
598
    {
599 359
        $new = clone $this;
600
601
        // Set ariadescribedby.
602 359
        if ($new->getAriaDescribedBy() === true && $new->inputWidget instanceof InputAttributes) {
603 4
            $new->inputWidget = $new->inputWidget->ariaDescribedBy($this->inputWidget->getInputId() . '-help');
0 ignored issues
show
Bug introduced by
The method ariaDescribedBy() does not exist on Yiisoft\Form\Widget\Attribute\WidgetAttributes. It seems like you code against a sub-type of Yiisoft\Form\Widget\Attribute\WidgetAttributes such as Yiisoft\Form\Widget\Attribute\InputAttributes or Yiisoft\Form\Widget\Attribute\FieldAttributes. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

603
            /** @scrutinizer ignore-call */ 
604
            $new->inputWidget = $new->inputWidget->ariaDescribedBy($this->inputWidget->getInputId() . '-help');
Loading history...
604
        }
605
606
        // Set encode.
607 359
        $new->inputWidget = $new->inputWidget->encode($new->getEncode());
608
609
        // Set input class.
610 359
        $inputClass = $new->getInputClass();
611
612 359
        if ($inputClass !== '') {
613 6
            $new->inputWidget = $new->inputWidget->class($inputClass);
614
        }
615
616
        // Set placeholder.
617 359
        $placeholder = $new->getPlaceholder() ?? $new->inputWidget->getAttributePlaceHolder();
618
619 359
        if ($new->inputWidget instanceof PlaceholderInterface && $placeholder !== '') {
620 10
            $new->inputWidget = $new->inputWidget->attributes(['placeholder' => $placeholder]);
621
        }
622
623
        // Set valid class and invalid class.
624 359
        $invalidClass = $new->getInvalidClass();
625 359
        $validClass = $new->getValidClass();
626
627 359
        if ($invalidClass !== '' && $new->inputWidget->hasError()) {
628 5
            $new->inputWidget = $new->inputWidget->class($invalidClass);
629 355
        } elseif ($validClass !== '' && $new->inputWidget->isValidated()) {
630 6
            $new->inputWidget = $new->inputWidget->class($validClass);
631
        }
632
633
        // Set attributes.
634 359
        $new->inputWidget = $new->inputWidget->attributes($this->getAttributes());
635
636 359
        return $new;
637
    }
638
639
    /**
640
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
641
     */
642 337
    private function renderError(): string
643
    {
644 337
        $errorAttributes = $this->getErrorAttributes();
645 337
        $errorClass = $this->getErrorClass();
646
647 337
        if ($errorClass !== '') {
648 9
            Html::addCssClass($errorAttributes, $errorClass);
649
        }
650
651 337
        return Error::widget()
652 337
            ->attributes($errorAttributes)
653 337
            ->encode($this->getEncode())
654 337
            ->for($this->inputWidget->getFormModel(), $this->inputWidget->getAttribute())
655 337
            ->message($this->getError() ?? '')
656 337
            ->messageCallback($this->getErrorMessageCallback())
657 337
            ->tag($this->getErrorTag())
658 337
            ->render();
659
    }
660
661
    /**
662
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
663
     */
664 359
    private function renderInputWidget(): string
665
    {
666 359
        $new = clone $this;
667
668 359
        $new = $new->buildField();
669
670 359
        if (!array_key_exists('{input}', $new->parts)) {
671 359
            $new->parts['{input}'] = $new->inputWidget->render();
672
        }
673
674 342
        if (!array_key_exists('{error}', $new->parts)) {
675 338
            $new->parts['{error}'] = $this->getError() !== null ? $new->renderError() : '';
676
        }
677
678 342
        if (!array_key_exists('{hint}', $new->parts)) {
679 338
            $new->parts['{hint}'] = $new->renderHint();
680
        }
681
682 342
        if (!array_key_exists('{label}', $new->parts)) {
683 322
            $new->parts['{label}'] = $new->renderLabel();
684
        }
685
686 342
        if ($new->getDefaultTokens() !== []) {
687 4
            $new->parts = array_merge($new->parts, $new->getDefaultTokens());
688
        }
689
690 342
        return preg_replace('/^\h*\v+/m', '', trim(strtr($new->getTemplate(), $new->parts)));
691
    }
692
693
    /**
694
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
695
     */
696 338
    private function renderHint(): string
697
    {
698 338
        $hintAttributes = $this->getHintAttributes();
699 338
        $hintClass = $this->getHintClass();
700
701 338
        if ($hintClass !== '') {
702 8
            Html::addCssClass($hintAttributes, $hintClass);
703
        }
704
705 338
        if ($this->getAriaDescribedBy() === true) {
706 4
            $hintAttributes['id'] = $this->inputWidget->getInputId() . '-help';
707
        }
708
709 338
        return Hint::widget()
710 338
            ->attributes($hintAttributes)
711 338
            ->encode($this->getEncode())
712 338
            ->for($this->inputWidget->getFormModel(), $this->inputWidget->getAttribute())
713 338
            ->hint($this->getHint())
714 338
            ->tag($this->getHintTag())
715 338
            ->render();
716
    }
717
718
    /**
719
     * @throws CircularReferenceException|InvalidConfigException|NotFoundException|NotInstantiableException
720
     */
721 322
    private function renderLabel(): string
722
    {
723 322
        $labelAttributes = $this->getLabelAttributes();
724 322
        $labelClass = $this->getLabelClass();
725
726 322
        if (!array_key_exists('for', $labelAttributes)) {
727
            /** @var string */
728 321
            $labelAttributes['for'] = ArrayHelper::getValue(
729 321
                $this->getAttributes(),
730
                'id',
731 321
                $this->inputWidget->getInputId(),
732
            );
733
        }
734
735 322
        if ($labelClass !== '') {
736 3
            Html::addCssClass($labelAttributes, $labelClass);
737
        }
738
739 322
        return Label::widget()
740 322
            ->attributes($labelAttributes)
741 322
            ->encode($this->getEncode())
742 322
            ->for($this->inputWidget->getFormModel(), $this->inputWidget->getAttribute())
743 322
            ->label($this->getLabel())
744 322
            ->render();
745
    }
746
}
747