Passed
Pull Request — master (#192)
by Sergei
02:09
created

FieldFactory::label()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
c 1
b 0
f 0
nc 1
nop 3
dl 0
loc 7
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form;
6
7
use RuntimeException;
8
9
use Yiisoft\Form\Field\Base\AbstractField;
10
use Yiisoft\Form\Field\Base\PlaceholderTrait;
11
use Yiisoft\Form\Field\Part\Error;
12
use Yiisoft\Form\Field\Part\Hint;
13
use Yiisoft\Form\Field\Part\Label;
14
use Yiisoft\Widget\WidgetFactory;
15
16
use function in_array;
17
18
final class FieldFactory
19
{
20
    private const SUPPORT_PLACEHOLDER = 1;
21
22
    private ?array $baseFieldConfig = null;
23
24
    /**
25
     * @param array[] $fieldConfigs
26
     */
27 24
    public function __construct(
28
        private ?string $containerTag = null,
29
        private array $containerTagAttributes = [],
30
        private ?bool $useContainer = null,
31
        private ?string $template = null,
32
        private ?bool $setInputIdAttribute = null,
33
        private array $inputTagAttributes = [],
34
        private array $labelConfig = [],
35
        private array $hintConfig = [],
36
        private array $errorConfig = [],
37
        private ?bool $usePlaceholder = null,
38
        private array $fieldConfigs = [],
39
    ) {
40
    }
41
42 5
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
43
    {
44 5
        $widgetConfig = array_merge(
45 5
            $this->makeLabelConfig(),
46
            $config,
47
        );
48 5
        return Label::widget($widgetConfig)->attribute($formModel, $attribute);
0 ignored issues
show
Bug introduced by
The method attribute() does not exist on Yiisoft\Widget\Widget. It seems like you code against a sub-type of Yiisoft\Widget\Widget such as Yiisoft\Form\Field\Part\Label or Yiisoft\Form\Field\Base\AbstractField or Yiisoft\Form\Field\Part\Error or Yiisoft\Form\Field\Part\Hint. ( Ignorable by Annotation )

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

48
        return Label::widget($widgetConfig)->/** @scrutinizer ignore-call */ attribute($formModel, $attribute);
Loading history...
49
    }
50
51 4
    public function hint(FormModelInterface $formModel, string $attribute, array $config = []): Hint
52
    {
53 4
        $widgetConfig = array_merge(
54 4
            $this->hintConfig,
55
            $config,
56
        );
57 4
        return Hint::widget($widgetConfig)->attribute($formModel, $attribute);
58
    }
59
60 4
    public function error(FormModelInterface $formModel, string $attribute, array $config = []): Error
61
    {
62 4
        $widgetConfig = array_merge(
63 4
            $this->errorConfig,
64
            $config,
65
        );
66 4
        return Error::widget($widgetConfig)->attribute($formModel, $attribute);
67
    }
68
69
    /**
70
     * @psalm-template T
71
     * @psalm-param class-string<T> $class
72
     * @psalm-return T
73
     */
74 11
    public function widget(
75
        string $class,
76
        FormModelInterface $formModel,
77
        string $attribute,
78
        array $config = []
79
    ): object {
80 11
        $traits = class_uses($class);
81 11
        if ($traits === false) {
82
            throw new RuntimeException('Invalid field class.');
83
        }
84
85 11
        $supports = [];
86 11
        if (in_array(PlaceholderTrait::class, $traits, true)) {
87 11
            $supports[] = self::SUPPORT_PLACEHOLDER;
88
        }
89
90 11
        $config = array_merge(
91 11
            $this->makeFieldConfig($supports),
92 11
            $this->fieldConfigs[$class] ?? [],
93
            $config,
94 11
            ['class' => $class],
95
        );
96
97
        /** @psalm-var T&AbstractField $widget */
98 11
        $widget = WidgetFactory::createWidget($config);
99
100 11
        return $widget->attribute($formModel, $attribute);
101
    }
102
103
    /**
104
     * @param int[] $supports
105
     */
106 11
    private function makeFieldConfig(array $supports): array
107
    {
108 11
        $config = $this->makeBaseFieldConfig();
109 11
        foreach ($supports as $support) {
110
            switch ($support) {
111 11
                case self::SUPPORT_PLACEHOLDER:
112 11
                    if ($this->usePlaceholder !== null) {
113 2
                        $config['usePlaceholder()'] = [$this->usePlaceholder];
114
                    }
115 11
                    break;
116
            }
117
        }
118 11
        return $config;
119
    }
120
121 11
    private function makeBaseFieldConfig(): array
122
    {
123 11
        if ($this->baseFieldConfig === null) {
124 11
            $this->baseFieldConfig = [];
125
126 11
            if ($this->containerTag !== null) {
127 2
                $this->baseFieldConfig['containerTag()'] = [$this->containerTag];
128
            }
129
130 11
            if ($this->containerTagAttributes !== []) {
131 2
                $this->baseFieldConfig['containerTagAttributes()'] = [$this->containerTagAttributes];
132
            }
133
134 11
            if ($this->useContainer !== null) {
135 1
                $this->baseFieldConfig['useContainer()'] = [$this->useContainer];
136
            }
137
138 11
            if ($this->template !== null) {
139 1
                $this->baseFieldConfig['template()'] = [$this->template];
140
            }
141
142 11
            if ($this->setInputIdAttribute !== null) {
143 1
                $this->baseFieldConfig['setInputIdAttribute()'] = [$this->setInputIdAttribute];
144
            }
145
146 11
            if ($this->inputTagAttributes !== []) {
147 2
                $this->baseFieldConfig['inputTagAttributes()'] = [$this->inputTagAttributes];
148
            }
149
150 11
            $labelConfig = $this->makeLabelConfig();
151 11
            if ($labelConfig !== []) {
152 2
                $this->baseFieldConfig['labelConfig()'] = [$labelConfig];
153
            }
154
155 11
            if ($this->hintConfig !== []) {
156 1
                $this->baseFieldConfig['hintConfig()'] = [$this->hintConfig];
157
            }
158
159 11
            if ($this->errorConfig !== []) {
160 1
                $this->baseFieldConfig['errorConfig()'] = [$this->errorConfig];
161
            }
162
        }
163 11
        return $this->baseFieldConfig;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->baseFieldConfig could return the type null which is incompatible with the type-hinted return array. Consider adding an additional type-check to rule them out.
Loading history...
164
    }
165
166 16
    private function makeLabelConfig(): array
167
    {
168 16
        $config = [];
169
170 16
        if ($this->setInputIdAttribute === false) {
171 2
            $config['useInputIdAttribute()'] = [false];
172
        }
173
174 16
        return array_merge($config, $this->labelConfig);
175
    }
176
}
177