Test Failed
Pull Request — master (#160)
by Wilmer
02:22
created

FieldAttributes   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 680
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 156
c 1
b 0
f 0
dl 0
loc 680
ccs 97
cts 97
cp 1
rs 6.4799
wmc 54

54 Methods

Rating   Name   Duplication   Size   Complexity  
A errorAttributes() 0 5 1
A addTemplate() 0 5 1
A addInvalidClass() 0 5 1
A getAriaDescribedBy() 0 3 1
A containerName() 0 5 1
A hint() 0 5 1
A getLabelClass() 0 3 1
A getHintClass() 0 3 1
A hintIndividualClass() 0 5 1
A required() 0 5 1
A labelAttributes() 0 5 1
A getLabel() 0 3 1
A labelClass() 0 5 1
A getButtonsIndividualAttributes() 0 3 1
A getHintIndividualClass() 0 3 1
A getErrorAttributes() 0 3 1
A containerIndividualClass() 0 5 1
A buttonsIndividualAttributes() 0 5 1
A getContainerClass() 0 3 1
A ariaDescribedBy() 0 5 1
A getLabelAttributes() 0 3 1
A containerId() 0 5 1
A withoutContainer() 0 5 1
A hintAttributes() 0 5 1
A error() 0 5 1
A getHintTag() 0 3 1
A getHint() 0 3 1
A errorIndividualClass() 0 5 1
A getError() 0 3 1
A inputClass() 0 5 1
A getErrorClass() 0 3 1
A errorClass() 0 5 1
A hintClass() 0 5 1
A label() 0 5 1
A placeholder() 0 5 1
A withInputClass() 0 5 1
A errorMessageCallback() 0 5 1
A getErrorIndividualClass() 0 3 1
A getContainer() 0 3 1
A template() 0 5 1
A containerAttributes() 0 5 1
A hintTag() 0 5 1
A getErrorMessageCallback() 0 3 1
A labelFor() 0 5 1
A errorTag() 0 5 1
A validClass() 0 5 1
A getErrorTag() 0 3 1
A getHintAttributes() 0 3 1
A invalidClass() 0 5 1
A containerClass() 0 5 1
A readonly() 0 5 1
A addValidClass() 0 5 1
A getContainerAttributes() 0 3 1
A getLabelIndividualClass() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like FieldAttributes often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FieldAttributes, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget\Attribute;
6
7
abstract class FieldAttributes extends WidgetAttributes
8
{
9
    private bool $ariaDescribedBy = false;
10
    /** @psalm-var array[][] */
11
    private array $buttonsIndividualAttributes = [];
12
13
    private bool $container = true;
14
    private array $containerAttributes = [];
15
    private string $containerClass = '';
16
    private array $containerIndividualClass = [];
17
18
    private ?string $error = '';
19
    private array $errorAttributes = [];
20
    private string $errorClass = '';
21
    /** @psalm-var string[] */
22
    private array $errorIndividualClass = [];
23
    private array $errorMessageCallback = [];
24
    private string $errorTag = 'div';
25
26
    private ?string $hint = '';
27
    private array $hintAttributes = [];
28
    private string $hintClass = '';
29
    /** @psalm-var string[] */
30
    protected array $hintIndividualClass = [];
31
    private string $hintTag = 'div';
32
33
    protected string $id = '';
34
    protected string $inputClass = '';
35
    protected array $inputsClass = [];
36
37
    private ?string $label = '';
38
    private array $labelAttributes = [];
39
    private string $labelClass = '';
40
    /** @psalm-var string[] */
41
    private array $labelIndividualClass = [];
42
43
    protected string $invalidClass = '';
44 2
    /** @psalm-var array<string, string> */
45
    protected array $invalidsClass = [];
46 2
    protected string $validClass = '';
47 2
    /** @psalm-var array<string, string> */
48 2
    protected array $validsClass = [];
49
    protected string $template = "{label}\n{input}\n{hint}\n{error}";
50
    /** @psalm-var array<string, string> */
51
    protected array $templates = [];
52
    protected array $parts = [];
53
    protected string $type = '';
54
    protected ?string $placeholder = null;
55
56
    /**
57
     * Set invalid class each for field type.
58
     *
59
     * @param array $invalidClass the input class to be used to layout the field.
60
     *
61
     * ```php
62 174
     * [Field::TYPE_TEXT => 'test-class-1', Field::TYPE_SUBMIT_BUTTON => 'test-class-2']
63
     *
64 174
     * @return static
65 174
     *
66 174
     * @psalm-param array<string, string> $invalidClass
67 174
     */
68 174
    public function addInvalidClass(array $invalidClass): self
69
    {
70
        $new = clone $this;
71
        $new->invalidsClass = $invalidClass;
72
        return $new;
73
    }
74
75
    /**
76 2
     * Set layout template for render a field with label, input, hint and error.
77
     *
78 2
     * @param array $template the template to be used to layout the field.
79 2
     *
80 2
     * ```php
81
     * [Field::TYPE_TEXT => '{input}', Field::TYPE_SUBMIT_BUTTON => '<div>{input}</div>']
82
     *
83
     * @return static
84
     *
85
     * @psalm-param array<string, string> $template
86
     */
87
    public function addTemplate(array $template): self
88 9
    {
89
        $new = clone $this;
90 9
        $new->templates = $template;
91 9
        return $new;
92 9
    }
93
94
    /**
95
     * Set invalid class each for field type.
96
     *
97
     * @param array $validsClass the input class to be used to layout the field.
98
     *
99
     * ```php
100 9
     * [Field::TYPE_TEXT => 'test-class-1', Field::TYPE_SUBMIT_BUTTON => 'test-class-2']
101
     *
102 9
     * @return static
103 9
     *
104 9
     * @psalm-param array<string, string> $validsClass
105
     */
106
    public function addValidClass(array $validsClass): self
107
    {
108
        $new = clone $this;
109
        $new->validsClass = $validsClass;
110
        return $new;
111
    }
112 2
113
    /**
114 2
     * Set aria-describedby attribute.
115 2
     *
116 2
     * @return static
117
     *
118
     * @link https://www.w3.org/TR/WCAG20-TECHS/ARIA1.html
119
     */
120
    public function ariaDescribedBy(): self
121
    {
122
        $new = clone $this;
123
        $new->ariaDescribedBy = true;
124 9
        return $new;
125
    }
126 9
127 9
    /**
128 9
     * Set individual attributes for the buttons widgets.
129
     *
130
     * @param array $values Attribute values indexed by attribute names.
131
     * ```php
132
     * [0 => ['value' => 'Submit'], 1 => ['value' => 'Reseteable']]
133
     * ```
134
     *
135
     * @return static
136 2
     *
137
     * @psalm-param array[][] $values
138 2
     */
139 2
    public function buttonsIndividualAttributes(array $values): self
140 2
    {
141
        $new = clone $this;
142
        $new->buttonsIndividualAttributes = $values;
143
        return $new;
144
    }
145
146
    /**
147
     * Set container attributes.
148
     *
149
     * @param array $values Attribute values indexed by attribute names.
150 2
     *
151
     * ```php
152 2
     * ['class' => 'test-class']
153 2
     * ```
154 2
     *
155
     * @return static
156
     *
157
     * @psalm-param array<string, string> $values
158
     */
159
    public function containerAttributes(array $values): self
160
    {
161
        $new = clone $this;
162
        $new->containerAttributes = array_merge($new->containerAttributes, $values);
163
        return $new;
164 9
    }
165
166 9
    /**
167 9
     * Set container css class.
168 9
     *
169
     * @return static
170
     */
171 174
    public function containerClass(string $value): self
172
    {
173 174
        $new = clone $this;
174 1
        $new->containerClass = $value;
175
        return $new;
176
    }
177 173
178
    /**
179
     * Set the ID of the container field.
180 173
     *
181
     * @param string|null $id
182
     *
183
     * @return static
184
     */
185
    public function containerId(?string $id): self
186
    {
187 173
        $new = clone $this;
188
        $new->containerAttributes['id'] = $id;
189
        return $new;
190 173
    }
191 20
192 14
    /**
193
     * Set the name of the container field.
194 20
     *
195
     * @param string|null $id
196 11
     *
197
     * @return static
198 11
     */
199
    public function containerName(?string $id): self
200 20
    {
201
        $new = clone $this;
202 5
        $new->containerAttributes['name'] = $id;
203 5
        return $new;
204
    }
205 20
206
    /**
207 2
     * Set error message for the field.
208
     *
209 2
     * @param string|null $value the error message.
210
     *
211 20
     * @return static The field widget instance.
212
     */
213 1
    public function error(?string $value): self
214
    {
215 1
        $new = clone $this;
216 1
        $new->error = $value;
217 1
        return $new;
218
    }
219
220
    /**
221 1
     * Set error attributes.
222 1
     *
223 1
     * @param array $values Attribute values indexed by attribute names.
224
     *
225
     * ```php
226
     * ['class' => 'test-class']
227 173
     * ```
228
     *
229
     * @return static The field widget instance.
230 1
     */
231
    public function errorAttributes(array $values): self
232 1
    {
233 1
        $new = clone $this;
234 1
        $new->errorAttributes = $values;
235
        return $new;
236 1
    }
237
238
    /**
239
     * Set error css class.
240
     *
241
     * @return static
242
     */
243
    public function errorClass(string $value): self
244 1
    {
245
        $new = clone $this;
246
        $new->errorClass = $value;
247 1
        return $new;
248
    }
249 1
250
    /**
251
     * Set error class used for an invalid field.
252 173
     *
253
     * @param array $errorClass The error class to apply to an invalid field.
254 173
     *
255 173
     * ```php
256
     * [Field::TYPE_TEXT => 'test-class-1', Field::TYPE_SUBMIT_BUTTON => 'test-class-2']
257 173
     * ```
258 173
     *
259 173
     * @return static
260 173
     *
261
     * @psalm-param array<string, string> $errorClass
262 173
     */
263 1
    public function errorIndividualClass(array $errorClass): self
264
    {
265
        $new = clone $this;
266 173
        $new->errorIndividualClass = $errorClass;
267 1
        return $new;
268
    }
269
270 173
    /**
271 8
     * Callback that will be called to obtain an error message.
272 173
     *
273 8
     * The signature of the callback must be:
274
     *
275
     * ```php
276 173
     * [$FormModel, function()]
277 143
     * ```
278
     *
279
     * @param array $value
280 173
     *
281 59
     * @return static
282
     */
283
    public function errorMessageCallback(array $value): self
284 173
    {
285
        $new = clone $this;
286
        $new->errorMessageCallback = $value;
287
        return $new;
288
    }
289
290
    /**
291
     * The tag name of the container element.
292
     *
293
     * Empty to render error messages without container {@see Html::tag()}.
294
     *
295
     * @param string $value
296
     *
297
     * @return static
298
     */
299
    public function errorTag(string $value): self
300
    {
301
        $new = clone $this;
302
        $new->errorTag = $value;
303
        return $new;
304
    }
305
306
    public function getAriaDescribedBy(): bool
307
    {
308
        return $this->ariaDescribedBy;
309
    }
310
311
    public function getButtonsIndividualAttributes(string $index): ?array
312
    {
313
        return $this->buttonsIndividualAttributes[$index] ?? null;
314
    }
315
316
    public function getContainer(): bool
317
    {
318
        return $this->container;
319
    }
320
321
    public function getContainerAttributes(): array
322
    {
323
        return $this->containerAttributes;
324
    }
325
326
    public function getContainerClass(): string
327
    {
328
        return $this->containerClass;
329
    }
330
331
    public function getError(): ?string
332
    {
333
        return $this->error;
334
    }
335
336
    public function getErrorAttributes(): array
337
    {
338
        return $this->errorAttributes;
339
    }
340
341
    public function getErrorClass(): string
342
    {
343
        return $this->errorClass;
344
    }
345
346
    public function getErrorIndividualClass(string $type): ?string
347
    {
348
        return $this->errorIndividualClass[$type] ?? null;
349
    }
350
351
    public function getErrorMessageCallback(): array
352
    {
353
        return $this->errorMessageCallback;
354
    }
355
356
    public function getErrorTag(): string
357
    {
358
        return $this->errorTag;
359
    }
360
361
    public function getHint(): ?string
362
    {
363
        return $this->hint;
364
    }
365
366
    public function getHintAttributes(): array
367
    {
368
        return $this->hintAttributes;
369
    }
370
371
    public function getHintClass(): string
372
    {
373
        return $this->hintClass;
374
    }
375
376
    public function getHintIndividualClass(string $type): ?string
377
    {
378
        return $this->hintIndividualClass[$type] ?? null;
379
    }
380
381
    public function getHintTag(): string
382
    {
383
        return $this->hintTag;
384
    }
385
386
    public function getLabel(): ?string
387
    {
388
        return $this->label;
389
    }
390
391
    public function getLabelAttributes(): array
392
    {
393
        return $this->labelAttributes;
394
    }
395
396
    public function getLabelClass(): string
397
    {
398
        return $this->labelClass;
399
    }
400
401
    public function getLabelIndividualClass(string $type): ?string
402
    {
403
        return $this->labelIndividualClass[$type] ?? null;
404
    }
405
406
    /**
407
     * Set hint message for the field.
408
     *
409
     * @return static
410
     */
411
    public function hint(?string $value): self
412
    {
413
        $new = clone $this;
414
        $new->hint = $value;
415
        return $new;
416
    }
417
418
    /**
419
     * Set hint attributes.
420
     *
421
     * @param array $values Attribute values indexed by attribute names.
422
     *
423
     * ```php
424
     * ['class' => 'test-class']
425
     * ```
426
     *
427
     * @return static The field widget instance.
428
     */
429
    public function hintAttributes(array $values): self
430
    {
431
        $new = clone $this;
432
        $new->hintAttributes = $values;
433
        return $new;
434
    }
435
436
    /**
437
     * Set hint css class.
438
     *
439
     * @return static
440
     */
441
    public function hintClass(string $value): self
442
    {
443
        $new = clone $this;
444
        $new->hintClass = $value;
445
        return $new;
446
    }
447
448
    /**
449
     * Set hint tag name.
450
     *
451
     * @return static
452
     */
453
    public function hintTag(string $value): self
454
    {
455
        $new = clone $this;
456
        $new->hintTag = $value;
457
        return $new;
458
    }
459
460
    /**
461
     * Set hint class for a field.
462
     *
463
     * @param array $hintClass The hint class to be applied to a field.
464
     *
465
     * ```php
466
     * [Field::TYPE_TEXT => 'test-class-1', Field::TYPE_SUBMIT_BUTTON => 'test-class-2']
467
     *
468
     * @return static
469
     *
470
     * @psalm-param array<string, string> $hintClass
471
     */
472
    public function hintIndividualClass(array $hintClass): self
473
    {
474
        $new = clone $this;
475
        $new->hintIndividualClass = $hintClass;
476
        return $new;
477
    }
478
479
    /**
480
     * Set input css class.
481
     *
482
     * @return static
483
     */
484
    public function inputClass(string $value): self
485
    {
486
        $new = clone $this;
487
        $new->inputClass = $value;
488
        return $new;
489
    }
490
491
    /**
492
     * Set invalid css class.
493
     *
494
     * @return static
495
     */
496
    public function invalidClass(string $value): self
497
    {
498
        $new = clone $this;
499
        $new->invalidClass = $value;
500
        return $new;
501
    }
502
503
    /**
504
     * Set label message for the field.
505
     *
506
     * @return static
507
     */
508
    public function label(?string $value): self
509
    {
510
        $new = clone $this;
511
        $new->label = $value;
512
        return $new;
513
    }
514
515
    /**
516
     * Set label attributes.
517
     *
518
     * @param array $values Attribute values indexed by attribute names.
519
     *
520
     * ```php
521
     * ['class' => 'test-class']
522
     * ```
523
     *
524
     * @return static The field widget instance.
525
     */
526
    public function labelAttributes(array $values): self
527
    {
528
        $new = clone $this;
529
        $new->labelAttributes = $values;
530
        return $new;
531
    }
532
533
    /**
534
     * Set the label css class.
535
     *
536
     * @return static
537
     */
538
    public function labelClass(string $value): self
539
    {
540
        $new = clone $this;
541
        $new->labelClass = $value;
542
        return $new;
543
    }
544
545
    /**
546
     * The id of a labelable form-related element in the same document as the tag label element.
547
     *
548
     * The first element in the document with an id matching the value of the for attribute is the labeled control for
549
     * this label element, if it is a labelable element.
550
     *
551
     * @param string|null $value The id of a labelable form-related element in the same document as the tag label
552
     * element. If null, the attribute will be removed.
553
     *
554
     * @return static
555
     */
556
    public function labelFor(?string $value): self
557
    {
558
        $new = clone $this;
559
        $new->labelAttributes['for'] = $value;
560
        return $new;
561
    }
562
563
    /**
564
     * It allows defining placeholder.
565
     *
566
     * @param string $value
567
     *
568
     * @return static
569
     *
570
     * @link https://html.spec.whatwg.org/multipage/input.html#the-placeholder-attribute
571
     */
572
    public function placeholder(string $value): self
573
    {
574
        $new = clone $this;
575
        $new->placeholder = $value;
576
        return $new;
577
    }
578
579
    /**
580
     * A Boolean attribute which, if present, means this field cannot be edited by the user.
581
     * Its value can, however, still be changed by JavaScript code directly setting the HTMLInputElement.value
582
     * property.
583
     *
584
     * @param bool $value
585
     *
586
     * @return static
587
     *
588
     * @link https://html.spec.whatwg.org/multipage/input.html#the-readonly-attribute
589
     */
590
    public function readonly(bool $value = true): self
591
    {
592
        $new = clone $this;
593
        $new->attributes['readonly'] = $value;
594
        return $new;
595
    }
596
597
    /**
598
     * If it is required to fill in a value in order to submit the form.
599
     *
600
     * @return static
601
     *
602
     * @link https://www.w3.org/TR/html52/sec-forms.html#the-required-attribute
603
     */
604
    public function required(): self
605
    {
606
        $new = clone $this;
607
        $new->attributes['required'] = true;
608
        return $new;
609
    }
610
611
    /**
612
     * Set layout template for render a field.
613
     *
614
     * @param string $value
615
     *
616
     * @return static
617
     */
618
    public function template(string $value): self
619
    {
620
        $new = clone $this;
621
        $new->template = $value;
622
        return $new;
623
    }
624
625
    /**
626
     * Set the value valid css class.
627
     *
628
     * @param string $value is the valid css class.
629
     *
630
     * @return static
631
     */
632
    public function validClass(string $value): self
633
    {
634
        $new = clone $this;
635
        $new->validClass = $value;
636
        return $new;
637
    }
638
639
    /**
640
     * Set container class each for field type.
641
     *
642
     * @param array $containerClass The container class to be applied to field's container tag.
643
     *
644
     * ```php
645
     * [Field::TYPE_TEXT => 'test-class-1', Field::TYPE_SUBMIT_BUTTON => 'test-class-2']
646
     *
647
     * @return static
648
     *
649
     * @psalm-param array<string, string> $containerClass
650
     */
651
    public function containerIndividualClass(array $containerClass): self
652
    {
653
        $new = clone $this;
654
        $new->containerIndividualClass = $containerClass;
655
        return $new;
656
    }
657
658
    /**
659
     * Disabled container for field.
660
     *
661
     * @return static
662
     */
663
    public function withoutContainer(): self
664
    {
665
        $new = clone $this;
666
        $new->container = false;
667
        return $new;
668
    }
669
670
    /**
671
     * Set input class for a field.
672
     *
673
     * @param array $inputClass The input class to be applied field container.
674
     *
675
     * ```php
676
     * [Field::TYPE_TEXT => 'test-class-1', Field::TYPE_SUBMIT_BUTTON => 'test-class-2']
677
     *
678
     * @return static
679
     *
680
     * @psalm-param array<string, string> $inputClass
681
     */
682
    public function withInputClass(array $inputClass): self
683
    {
684
        $new = clone $this;
685
        $new->inputsClass = $inputClass;
686
        return $new;
687
    }
688
}
689