Passed
Pull Request — master (#192)
by Alexander
05:47 queued 02:55
created

FieldAttributes::getContainerClass()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2.0185

Importance

Changes 0
Metric Value
cc 2
eloc 5
c 0
b 0
f 0
nc 2
nop 0
dl 0
loc 8
ccs 5
cts 6
cp 0.8333
crap 2.0185
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget\Attribute;
6
7
use Stringable;
8
9
abstract class FieldAttributes extends WidgetAttributes
10
{
11
    private ?bool $ariaDescribedBy = null;
12
    private ?bool $container = null;
13
    private array $containerAttributes = [];
14
    private string $containerClass = '';
15
    private array $defaultTokens = [];
16
    private array $defaultValues = [];
17
    private ?string $error = '';
18
    private array $errorAttributes = [];
19
    private string $errorClass = '';
20
    private array $errorMessageCallback = [];
21
    private string $errorTag = '';
22
    private ?string $hint = '';
23
    private array $hintAttributes = [];
24
    private string $hintClass = '';
25
    private string $hintTag = '';
26
    private string $inputClass = '';
27
    private ?string $label = '';
28
    private array $labelAttributes = [];
29
    private string $labelClass = '';
30
    private string $invalidClass = '';
31
    private string $validClass = '';
32
    private ?string $placeholder = null;
33
    private string $template = '';
34
    private string $type = '';
35
36
    /**
37
     * Set aria-describedby attribute.
38
     *
39
     * @param bool $value Whether to set aria-describedby attribute.
40
     *
41
     * @return static
42
     *
43
     * @link https://www.w3.org/TR/WCAG20-TECHS/ARIA1.html
44
     */
45 1
    public function ariaDescribedBy(bool $value): static
46
    {
47 1
        $new = clone $this;
48 1
        $new->ariaDescribedBy = $value;
49 1
        return $new;
50
    }
51
52
    /**
53
     * Set aria-label attribute.
54
     *
55
     * @param string $value
56
     *
57
     * @return static
58
     */
59 1
    public function ariaLabel(string $value): static
60
    {
61 1
        $new = clone $this;
62 1
        $new->attributes['aria-label'] = $value;
63 1
        return $new;
64
    }
65
66
    /**
67
     * Enable, disabled container for field.
68
     *
69
     * @param bool $value Is the container disabled or not.
70
     *
71
     * @return static
72
     */
73 1
    public function container(bool $value): static
74
    {
75 1
        $new = clone $this;
76 1
        $new->container = $value;
77 1
        return $new;
78
    }
79
80
    /**
81
     * Set container attributes.
82
     *
83
     * @param array $values Attribute values indexed by attribute names.
84
     *
85
     * ```php
86
     * ['class' => 'test-class']
87
     * ```
88
     *
89
     * @return static
90
     *
91
     * @psalm-param array<string, string> $values
92
     */
93 1
    public function containerAttributes(array $values): static
94
    {
95 1
        $new = clone $this;
96 1
        $new->containerAttributes = array_merge($new->containerAttributes, $values);
97 1
        return $new;
98
    }
99
100
    /**
101
     * Set container css class.
102
     *
103
     * @param string $value
104
     *
105
     * @return static
106
     */
107 1
    public function containerClass(string $value): static
108
    {
109 1
        $new = clone $this;
110 1
        $new->containerClass = $value;
111 1
        return $new;
112
    }
113
114
    /**
115
     * Set the ID of the container field.
116
     *
117
     * @param string|null $id
118
     *
119
     * @return static
120
     */
121 1
    public function containerId(?string $id): static
122
    {
123 1
        $new = clone $this;
124 1
        $new->containerAttributes['id'] = $id;
125 1
        return $new;
126
    }
127
128
    /**
129
     * Set the name of the container field.
130
     *
131
     * @param string|null $id
132
     *
133
     * @return static
134
     */
135 1
    public function containerName(?string $id): static
136
    {
137 1
        $new = clone $this;
138 1
        $new->containerAttributes['name'] = $id;
139 1
        return $new;
140
    }
141
142
    /**
143
     * Set default tokens.
144
     *
145
     * @param array $values Token values indexed by token names.
146
     *
147
     * @return static
148
     */
149 1
    public function defaultTokens(array $values): static
150
    {
151 1
        $new = clone $this;
152 1
        $new->defaultTokens = $values;
153 1
        return $new;
154
    }
155
156
    /**
157
     * Set default values for field widget.
158
     *
159
     * @param array $values The default values indexed by field type.
160
     *
161
     * ```php
162
     * [
163
     *     Text::class => [
164
     *         'label' => 'label-test',
165
     *     ],
166
     * ];
167
     *
168
     * @return static
169
     */
170 1
    public function defaultValues(array $values): static
171
    {
172 1
        $new = clone $this;
173 1
        $new->defaultValues = $values;
174 1
        return $new;
175
    }
176
177
    /**
178
     * Set error message for the field.
179
     *
180
     * @param string|null $value the error message.
181
     *
182
     * @return static The field widget instance.
183
     */
184 1
    public function error(?string $value): static
185
    {
186 1
        $new = clone $this;
187 1
        $new->error = $value;
188 1
        return $new;
189
    }
190
191
    /**
192
     * Set error attributes.
193
     *
194
     * @param array $values Attribute values indexed by attribute names.
195
     *
196
     * ```php
197
     * ['class' => 'test-class']
198
     * ```
199
     *
200
     * @return static The field widget instance.
201
     */
202 1
    public function errorAttributes(array $values): static
203
    {
204 1
        $new = clone $this;
205 1
        $new->errorAttributes = $values;
206 1
        return $new;
207
    }
208
209
    /**
210
     * Set error css class.
211
     *
212
     * @param string $value
213
     *
214
     * @return static
215
     */
216 1
    public function errorClass(string $value): static
217
    {
218 1
        $new = clone $this;
219 1
        $new->errorClass = $value;
220 1
        return $new;
221
    }
222
223
    /**
224
     * Callback that will be called to obtain an error message.
225
     *
226
     * The signature of the callback must be:
227
     *
228
     * ```php
229
     * [$FormModel, function()]
230
     * ```
231
     *
232
     * @param array $value
233
     *
234
     * @return static
235
     */
236 1
    public function errorMessageCallback(array $value): static
237
    {
238 1
        $new = clone $this;
239 1
        $new->errorMessageCallback = $value;
240 1
        return $new;
241
    }
242
243
    /**
244
     * The tag name of the container element.
245
     *
246
     * Empty to render error messages without container {@see Html::tag()}.
247
     *
248
     * @param string $value
249
     *
250
     * @return static
251
     */
252 1
    public function errorTag(string $value): static
253
    {
254 1
        $new = clone $this;
255 1
        $new->errorTag = $value;
256 1
        return $new;
257
    }
258
259
    /**
260
     * Set hint message for the field.
261
     *
262
     * @param string|null $value
263
     *
264
     * @return static
265
     */
266 1
    public function hint(?string $value): static
267
    {
268 1
        $new = clone $this;
269 1
        $new->hint = $value;
270 1
        return $new;
271
    }
272
273
    /**
274
     * Set hint attributes.
275
     *
276
     * @param array $values Attribute values indexed by attribute names.
277
     *
278
     * ```php
279
     * ['class' => 'test-class']
280
     * ```
281
     *
282
     * @return static The field widget instance.
283
     */
284 1
    public function hintAttributes(array $values): static
285
    {
286 1
        $new = clone $this;
287 1
        $new->hintAttributes = $values;
288 1
        return $new;
289
    }
290
291
    /**
292
     * Set hint css class.
293
     *
294
     * @param string $value
295
     *
296
     * @return static
297
     */
298 1
    public function hintClass(string $value): static
299
    {
300 1
        $new = clone $this;
301 1
        $new->hintClass = $value;
302 1
        return $new;
303
    }
304
305
    /**
306
     * Set hint tag name.
307
     *
308
     * @param string $value
309
     *
310
     * @return static
311
     */
312 1
    public function hintTag(string $value): static
313
    {
314 1
        $new = clone $this;
315 1
        $new->hintTag = $value;
316 1
        return $new;
317
    }
318
319
    /**
320
     * Set input css class.
321
     *
322
     * @param string $value
323
     *
324
     * @return static
325
     */
326 1
    public function inputClass(string $value): static
327
    {
328 1
        $new = clone $this;
329 1
        $new->inputClass = $value;
330 1
        return $new;
331
    }
332
333
    /**
334
     * Set invalid css class.
335
     *
336
     * @param string $value
337
     *
338
     * @return static
339
     */
340 1
    public function invalidClass(string $value): static
341
    {
342 1
        $new = clone $this;
343 1
        $new->invalidClass = $value;
344 1
        return $new;
345
    }
346
347
    /**
348
     * Set label message for the field.
349
     *
350
     * @param string|null $value
351
     *
352
     * @return static
353
     */
354 1
    public function label(?string $value): static
355
    {
356 1
        $new = clone $this;
357 1
        $new->label = $value;
358 1
        return $new;
359
    }
360
361
    /**
362
     * Set label attributes.
363
     *
364
     * @param array $values Attribute values indexed by attribute names.
365
     *
366
     * ```php
367
     * ['class' => 'test-class']
368
     * ```
369
     *
370
     * @return static The field widget instance.
371
     */
372 1
    public function labelAttributes(array $values): static
373
    {
374 1
        $new = clone $this;
375 1
        $new->labelAttributes = $values;
376 1
        return $new;
377
    }
378
379
    /**
380
     * Set the label css class.
381
     *
382
     * @param string $value
383
     *
384
     * @return static
385
     */
386 1
    public function labelClass(string $value): static
387
    {
388 1
        $new = clone $this;
389 1
        $new->labelClass = $value;
390 1
        return $new;
391
    }
392
393
    /**
394
     * The id of a label-able form-related element in the same document as the tag label element.
395
     *
396
     * The first element in the document with an id matching the value of the for attribute is the labeled control for
397
     * this label element, if it is a label-able element.
398
     *
399
     * @param string|null $value The id of a label-able form-related element in the same document as the tag label
400
     * element. If null, the attribute will be removed.
401
     *
402
     * @return static
403
     */
404 1
    public function labelFor(?string $value): static
405
    {
406 1
        $new = clone $this;
407 1
        $new->labelAttributes['for'] = $value;
408 1
        return $new;
409
    }
410
411
    /**
412
     * It allows defining placeholder.
413
     *
414
     * @param string $value
415
     *
416
     * @return static
417
     *
418
     * @link https://html.spec.whatwg.org/multipage/input.html#the-placeholder-attribute
419
     */
420 1
    public function placeholder(string $value): static
421
    {
422 1
        $new = clone $this;
423 1
        $new->placeholder = $value;
424 1
        return $new;
425
    }
426
427
    /**
428
     * A Boolean attribute which, if present, means this field cannot be edited by the user.
429
     * Its value can, however, still be changed by JavaScript code directly setting the HTMLInputElement.value
430
     * property.
431
     *
432
     * @param bool $value
433
     *
434
     * @return static
435
     *
436
     * @link https://html.spec.whatwg.org/multipage/input.html#the-readonly-attribute
437
     */
438 1
    public function readonly(bool $value = true): static
439
    {
440 1
        $new = clone $this;
441 1
        $new->attributes['readonly'] = $value;
442 1
        return $new;
443
    }
444
445
    /**
446
     * Replace individual one token for current field instance.
447
     *
448
     * @param string $token
449
     * @param string|Stringable $value
450
     *
451
     * @return static
452
     */
453 1
    public function replaceIndividualToken(string $token, string|Stringable $value): static
454
    {
455 1
        $new = clone $this;
456 1
        $new->defaultTokens[$token] = $value;
457 1
        return $new;
458
    }
459
460
    /**
461
     * If it is required to fill in a value in order to submit the form.
462
     *
463
     * @return static
464
     *
465
     * @link https://www.w3.org/TR/html52/sec-forms.html#the-required-attribute
466
     */
467 2
    public function required(): static
468
    {
469 2
        $new = clone $this;
470 2
        $new->attributes['required'] = true;
471 2
        return $new;
472
    }
473
474
    /**
475
     * Set layout template for render a field.
476
     *
477
     * @param string $value
478
     *
479
     * @return static
480
     */
481 1
    public function template(string $value): static
482
    {
483 1
        $new = clone $this;
484 1
        $new->template = $value;
485 1
        return $new;
486
    }
487
488
    /**
489
     * Set the value valid css class.
490
     *
491
     * @param string $value is the valid css class.
492
     *
493
     * @return static
494
     */
495 1
    public function validClass(string $value): static
496
    {
497 1
        $new = clone $this;
498 1
        $new->validClass = $value;
499 1
        return $new;
500
    }
501
502
    /**
503
     * Return aria described by field.
504
     *
505
     * if aria described by is not set, and aria described by default is set, then return aria described by default.
506
     *
507
     * @return bool|null
508
     */
509 13
    protected function getAriaDescribedBy(): ?bool
510
    {
511 13
        $ariaDescribedBy = $this->ariaDescribedBy;
512 13
        $ariaDescribedByDefault = $this->getDefaultValue($this->type, 'ariaDescribedBy');
513
514 13
        if (is_bool($ariaDescribedByDefault)) {
515
            $ariaDescribedBy = $ariaDescribedByDefault;
516
        }
517
518 13
        return $ariaDescribedBy;
519
    }
520
521
    /**
522
     * Return attributes for field.
523
     *
524
     * if attributes is empty string, and attributes default value is not empty string, then return attributes default
525
     * value.
526
     *
527
     * @return array
528
     */
529 13
    protected function getAttributes(): array
530
    {
531 13
        $attributes = $this->attributes;
532 13
        $attributesDefault = $this->getDefaultValue($this->type, 'attributes');
533
534 13
        return match (is_array($attributesDefault) && $attributesDefault !== []) {
535
            true => $attributesDefault,
536 13
            false => $attributes,
537
        };
538
    }
539
540
    /**
541
     * Return enabled, disabled container for field.
542
     *
543
     * if container is not set, and container default value is bool, then return container default value.
544
     *
545
     * @return bool|null
546
     */
547 13
    protected function getContainer(): ?bool
548
    {
549 13
        $container = $this->container;
550 13
        $containerDefault = $this->getDefaultValue($this->type, 'container');
551
552 13
        if (is_bool($containerDefault)) {
553
            $container = $containerDefault;
554
        }
555
556 13
        return $container ?? true;
557
    }
558
559
    /**
560
     * Return attributes for container for field.
561
     *
562
     * if attributes container is empty array, and attributes container default value is not empty array, then return
563
     * attributes container default value.
564
     *
565
     * @return array
566
     */
567 13
    protected function getContainerAttributes(): array
568
    {
569 13
        $containerAttributes = $this->containerAttributes;
570 13
        $containerDefaultAttributes = $this->getDefaultValue($this->type, 'containerAttributes');
571
572 13
        return match (is_array($containerDefaultAttributes) && $containerDefaultAttributes !== []) {
573
            true => $containerDefaultAttributes,
574 13
            false => $containerAttributes,
575
        };
576
    }
577
578
    /**
579
     * Return class for container field.
580
     *
581
     * if container class is empty string, and container class default value is not empty string, then return container
582
     * class default value.
583
     *
584
     * @return string
585
     */
586 13
    protected function getContainerClass(): string
587
    {
588 13
        $containerClass = $this->containerClass;
589 13
        $containerDefaultClass = $this->getDefaultValue($this->type, 'containerClass');
590
591 13
        return match (is_string($containerDefaultClass) && $containerDefaultClass !== '') {
592
            true => $containerDefaultClass,
593 13
            false => $containerClass,
594
        };
595
    }
596
597
    /**
598
     * Return default tokens.
599
     *
600
     * The value is used in case tokens array is empty.
601
     */
602 13
    protected function getDefaultTokens(): array
603
    {
604 13
        $defaultTokens = $this->defaultTokens;
605 13
        $defaultTokensDefault = $this->getDefaultValue($this->type, 'defaultTokens');
606
607 13
        return match (is_array($defaultTokensDefault) && $defaultTokensDefault !== []) {
608
            true => $defaultTokensDefault,
609 13
            false => $defaultTokens,
610
        };
611
    }
612
613
    /**
614
     * Return definition for field.
615
     */
616 13
    protected function getDefinitions(): array
617
    {
618 13
        $definitions = $this->getDefaultValue($this->type, 'definitions') ?? [];
619 13
        return is_array($definitions) ? $definitions : [];
620
    }
621
622
    /**
623
     * Return error message for the field.
624
     *
625
     * if error message is empty string, and error message default value is not empty string, then return error message
626
     * default value.
627
     *
628
     * @return string|null
629
     */
630 13
    protected function getError(): ?string
631
    {
632 13
        $error = $this->error;
633 13
        $errorDefault = $this->getDefaultValue($this->type, 'error');
634
635 13
        return match (is_string($errorDefault) && $errorDefault !== '') {
636
            true => $errorDefault,
637 13
            false => $error,
638
        };
639
    }
640
641
    /**
642
     * Return error attribute for the field.
643
     *
644
     * if error attribute is empty string, and error attribute default value is not empty string, then return error
645
     * attribute default value.
646
     *
647
     * @return array
648
     */
649 13
    protected function getErrorAttributes(): array
650
    {
651 13
        $errorAttributes = $this->errorAttributes;
652 13
        $errorAttributesDefault = $this->getDefaultValue($this->type, 'errorAttributes');
653
654 13
        return match (is_array($errorAttributesDefault) && $errorAttributesDefault !== []) {
655
            true => $errorAttributesDefault,
656 13
            false => $errorAttributes,
657
        };
658
    }
659
660
    /**
661
     * Return error class for the field.
662
     *
663
     * if error class is empty string, and error class default value is not empty string, then return error class
664
     * default value.
665
     *
666
     * @return string
667
     */
668 13
    protected function getErrorClass(): string
669
    {
670 13
        $errorClass = $this->errorClass;
671 13
        $errorClassDefault = $this->getDefaultValue($this->type, 'errorClass');
672
673 13
        return match (is_string($errorClassDefault) && $errorClassDefault !== '') {
674
            true => $errorClassDefault,
675 13
            false => $errorClass,
676
        };
677
    }
678
679
    /**
680
     * Return error message callback for the field.
681
     *
682
     * if error message callback is empty array, and error message callback default value is not empty array, then
683
     * return error message callback default value.
684
     */
685 13
    protected function getErrorMessageCallback(): array
686
    {
687 13
        $errorMessageCallback = $this->errorMessageCallback;
688 13
        $errorMessageCallbackDefault = $this->getDefaultValue($this->type, 'errorMessageCallback');
689
690 13
        return match (is_array($errorMessageCallbackDefault) && $errorMessageCallbackDefault !== []) {
691
            true => $errorMessageCallbackDefault,
692 13
            false => $errorMessageCallback,
693
        };
694
    }
695
696
    /**
697
     * Return error tag for the field.
698
     *
699
     * if error tag is empty string, and error tag default value is not empty string, then return error tag default
700
     * value.
701
     *
702
     * @return string
703
     */
704 13
    protected function getErrorTag(): string
705
    {
706 13
        $errorTag = $this->errorTag;
707 13
        $errorTagDefault = $this->getDefaultValue($this->type, 'errorTag');
708
709 13
        return match (is_string($errorTagDefault) && $errorTagDefault !== '') {
710
            true => $errorTagDefault,
711 13
            false => $errorTag === '' ? 'div' : $errorTag,
712
        };
713
    }
714
715
    /**
716
     * Return hint for field.
717
     *
718
     * if hint is empty string, and hint default value is not empty string, then return hint default value.
719
     *
720
     * @return string|null
721
     */
722 13
    protected function getHint(): ?string
723
    {
724 13
        $hint = $this->hint;
725 13
        $hintDefault = $this->getDefaultValue($this->type, 'hint') ?? '';
726
727 13
        return match (is_string($hintDefault) && $hintDefault !== '') {
728
            true => $hintDefault,
729 13
            false => $hint,
730
        };
731
    }
732
733
    /**
734
     * Return hint attributes for field.
735
     *
736
     * if hint attributes is empty array, and hint default value is not empty array, then return hint default value.
737
     *
738
     * @return array
739
     */
740 13
    protected function getHintAttributes(): array
741
    {
742 13
        $hintAttributes = $this->hintAttributes;
743 13
        $hintAttributesDefault = $this->getDefaultValue($this->type, 'hintAttributes') ?? [];
744
745 13
        return match (is_array($hintAttributesDefault) && $hintAttributesDefault !== []) {
746
            true => $hintAttributesDefault,
747 13
            false => $hintAttributes,
748
        };
749
    }
750
751
    /**
752
     * Return hint class for field.
753
     *
754
     * if hint class is empty string, and hint default value is not empty string, then return hint default value.
755
     *
756
     * @return string
757
     */
758 13
    protected function getHintClass(): string
759
    {
760 13
        $hintClass = $this->hintClass;
761 13
        $hintClassDefault = $this->getDefaultValue($this->type, 'hintClass') ?? '';
762
763 13
        return match (is_string($hintClassDefault) && $hintClassDefault !== '') {
764
            true => $hintClassDefault,
765 13
            false => $hintClass,
766
        };
767
    }
768
769
    /**
770
     * Return hint tag for field.
771
     *
772
     * if hint tag is empty string, and hint default value is not empty string, then return hint default value.
773
     *
774
     * @return string
775
     */
776 13
    protected function getHintTag(): string
777
    {
778 13
        $hintTag = $this->hintTag;
779 13
        $hintTagDefault = $this->getDefaultValue($this->type, 'hintTag') ?? '';
780
781 13
        return match (is_string($hintTagDefault) && $hintTagDefault !== '') {
782
            true => $hintTagDefault,
783 13
            false => $hintTag === '' ? 'div' : $hintTag,
784
        };
785
    }
786
787
    /**
788
     * Return input class for field.
789
     *
790
     * if input class is empty string, and input class default value is not empty string, then return input class
791
     * default value.
792
     *
793
     * @return string
794
     */
795 13
    protected function getInputClass(): string
796
    {
797 13
        $inputClass = $this->inputClass;
798 13
        $inputClassDefault = $this->getDefaultValue($this->type, 'inputClass');
799
800 13
        return match (is_string($inputClassDefault) && $inputClassDefault !== '') {
801
            true => $inputClassDefault,
802 13
            false => $inputClass,
803
        };
804
    }
805
806
    /**
807
     * Return invalid class for field.
808
     *
809
     * if invalid class is empty string, and invalid class default value is not empty string, then return invalid class
810
     * default value.
811
     *
812
     * @return string
813
     */
814 13
    protected function getInvalidClass(): string
815
    {
816 13
        $invalidClass = $this->invalidClass;
817 13
        $invalidClassDefault = $this->getDefaultValue($this->type, 'invalidClass');
818
819 13
        return match (is_string($invalidClassDefault) && $invalidClassDefault !== '') {
820
            true => $invalidClassDefault,
821 13
            false => $invalidClass,
822
        };
823
    }
824
825
    /**
826
     * Return label for field.
827
     *
828
     * if label is empty string, and label default value is not empty string, then return label default value.
829
     *
830
     * @return string|null
831
     */
832 13
    protected function getLabel(): ?string
833
    {
834 13
        $label = $this->label;
835 13
        $labelDefault = $this->getDefaultValue($this->type, 'label') ?? '';
836
837 13
        return match (is_string($labelDefault) && $labelDefault !== '') {
838
            true => $labelDefault,
839 13
            false => $label,
840
        };
841
    }
842
843
    /**
844
     * Return label attributes for field.
845
     *
846
     * if label attributes is empty array, and label attributes default value is not empty array, then return label
847
     * attributes default value.
848
     *
849
     * @return array
850
     */
851 13
    protected function getLabelAttributes(): array
852
    {
853 13
        $labelAttributes = $this->labelAttributes;
854 13
        $labelAttributesDefault = $this->getDefaultValue($this->type, 'labelAttributes') ?? [];
855
856 13
        return match (is_array($labelAttributesDefault) && $labelAttributesDefault !== []) {
857
            true => $labelAttributesDefault,
858 13
            false => $labelAttributes,
859
        };
860
    }
861
862
    /**
863
     * Return label css class for field.
864
     *
865
     * if label css class is empty string, and label css class default value is not null, then return label css class
866
     * default value.
867
     *
868
     * @return string
869
     */
870 13
    protected function getLabelClass(): string
871
    {
872 13
        $labelClass = $this->labelClass;
873 13
        $labelClassDefault = $this->getDefaultValue($this->type, 'labelClass') ?? '';
874
875 13
        return match (is_string($labelClassDefault) && $labelClassDefault !== '') {
876
            true => $labelClassDefault,
877 13
            false => $labelClass,
878
        };
879
    }
880
881
    /**
882
     * Return placeholder for field.
883
     *
884
     * if placeholder is empty string, and placeholder default value is not empty string, then return placeholder
885
     * default value.
886
     *
887
     * @return string|null
888
     */
889
    protected function getPlaceholder(): ?string
890
    {
891
        $placeholder = $this->placeholder;
892
        $placeholderDefault = $this->getDefaultValue($this->type, 'placeholder') ?? '';
893
894
        return match (is_string($placeholderDefault) && $placeholderDefault !== '') {
895
            true => $placeholderDefault,
896
            false => $placeholder,
897
        };
898
    }
899
900
    /**
901
     * Return template for field.
902
     *
903
     * if template is empty string, and template default value is not empty string, then return template default value.
904
     *
905
     * @return string
906
     */
907 13
    protected function getTemplate(): string
908
    {
909 13
        $template = $this->template;
910 13
        $templateDefault = $this->getDefaultValue($this->type, 'template') ?? '';
911
912 13
        return match (is_string($templateDefault) && $templateDefault !== '') {
913
            true => $templateDefault,
914 13
            false => $template === '' ? "{label}\n{input}\n{hint}\n{error}" : $template,
915
        };
916
    }
917
918
    /**
919
     * Return valid class for field.
920
     *
921
     * if valid class is empty string, and valid class default value is not empty string, then return valid class
922
     * default value.
923
     *
924
     * @return string
925
     */
926 13
    protected function getValidClass(): string
927
    {
928 13
        $validClass = $this->validClass;
929 13
        $validDefaultClass = $this->getDefaultValue($this->type, 'validClass') ?? '';
930
931 13
        return match (is_string($validDefaultClass) && $validDefaultClass !== '') {
932
            true => $validDefaultClass,
933 13
            false => $validClass,
934
        };
935
    }
936
937
    /**
938
     * Set type class of the field.
939
     *
940
     * @param string $type The type class of the field.
941
     *
942
     * @return static
943
     */
944 14
    protected function type(string $type): static
945
    {
946 14
        $new = clone $this;
947 14
        $new->type = $type;
948 14
        return $new;
949
    }
950
951 13
    private function getDefaultValue(string $type, string $key): array|bool|string|null
952
    {
953
        /** @var array|bool|string|null */
954 13
        return $this->defaultValues[$type][$key] ?? null;
955
    }
956
}
957