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

FieldFactory::email()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 3
dl 0
loc 3
ccs 2
cts 2
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;
6
7
use InvalidArgumentException;
8
use RuntimeException;
9
10
use Yiisoft\Form\Field\Base\AbstractInputField;
11
use Yiisoft\Form\Field\Base\AbstractField;
12
use Yiisoft\Form\Field\Base\PlaceholderTrait;
13
use Yiisoft\Form\Field\Button;
14
use Yiisoft\Form\Field\Checkbox;
15
use Yiisoft\Form\Field\CheckboxList;
16
use Yiisoft\Form\Field\Date;
17
use Yiisoft\Form\Field\DateTime;
18
use Yiisoft\Form\Field\DateTimeLocal;
19
use Yiisoft\Form\Field\Email;
20
use Yiisoft\Form\Field\Fieldset;
21
use Yiisoft\Form\Field\Hidden;
22
use Yiisoft\Form\Field\Image;
23
use Yiisoft\Form\Field\Number;
24
use Yiisoft\Form\Field\Part\Error;
25
use Yiisoft\Form\Field\Part\Hint;
26
use Yiisoft\Form\Field\Part\Label;
27
use Yiisoft\Form\Field\Password;
28
use Yiisoft\Form\Field\RadioList;
29
use Yiisoft\Form\Field\Range;
30
use Yiisoft\Form\Field\ResetButton;
31
use Yiisoft\Form\Field\Select;
32
use Yiisoft\Form\Field\SubmitButton;
33
use Yiisoft\Form\Field\Telephone;
34
use Yiisoft\Form\Field\Text;
35
use Yiisoft\Form\Field\Textarea;
36
use Yiisoft\Form\Field\Url;
37
use Yiisoft\Widget\WidgetFactory;
38
39
use function in_array;
40
41
final class FieldFactory
42
{
43
    private const SUPPORT_PLACEHOLDER = 1;
44
45
    private ?array $baseFieldConfig = null;
46
47
    /**
48
     * @param array[] $fieldConfigs
49
     */
50 17
    public function __construct(
51
        private ?string $containerTag = null,
52
        private array $containerTagAttributes = [],
53
        private ?bool $useContainer = null,
54
        private ?string $template = null,
55
        private ?bool $setInputIdAttribute = null,
56
        private array $inputTagAttributes = [],
57
        private array $labelConfig = [],
58
        private array $hintConfig = [],
59
        private array $errorConfig = [],
60
        private ?bool $usePlaceholder = null,
61
        private array $fieldConfigs = [],
62
    ) {
63
    }
64
65 1
    public function button(array $config = []): Button
66
    {
67 1
        return $this->field(Button::class, $config);
68
    }
69
70 1
    public function checkbox(FormModelInterface $formModel, string $attribute, array $config = []): Checkbox
71
    {
72 1
        return $this->input(Checkbox::class, $formModel, $attribute, $config);
73
    }
74
75 1
    public function checkboxList(FormModelInterface $formModel, string $attribute, array $config = []): CheckboxList
76
    {
77
        return $this
78 1
            ->field(CheckboxList::class, $config)
79 1
            ->attribute($formModel, $attribute);
80
    }
81
82 1
    public function date(FormModelInterface $formModel, string $attribute, array $config = []): Date
83
    {
84 1
        return $this->input(Date::class, $formModel, $attribute, $config);
85
    }
86
87 1
    public function dateTime(FormModelInterface $formModel, string $attribute, array $config = []): DateTime
88
    {
89 1
        return $this->input(DateTime::class, $formModel, $attribute, $config);
90
    }
91
92 1
    public function dateTimeLocal(FormModelInterface $formModel, string $attribute, array $config = []): DateTimeLocal
93
    {
94 1
        return $this->input(DateTimeLocal::class, $formModel, $attribute, $config);
95
    }
96
97 1
    public function email(FormModelInterface $formModel, string $attribute, array $config = []): Email
98
    {
99 1
        return $this->input(Email::class, $formModel, $attribute, $config);
100
    }
101
102 1
    public function fieldset(array $config = []): Fieldset
103
    {
104 1
        return $this->field(Fieldset::class, $config);
105
    }
106
107 1
    public function hidden(FormModelInterface $formModel, string $attribute, array $config = []): Hidden
108
    {
109 1
        return $this->input(Hidden::class, $formModel, $attribute, $config);
110
    }
111
112 1
    public function image(array $config = []): Image
113
    {
114 1
        return $this->field(Image::class, $config);
115
    }
116
117 1
    public function number(FormModelInterface $formModel, string $attribute, array $config = []): Number
118
    {
119 1
        return $this->input(Number::class, $formModel, $attribute, $config);
120
    }
121
122 1
    public function password(FormModelInterface $formModel, string $attribute, array $config = []): Password
123
    {
124 1
        return $this->input(Password::class, $formModel, $attribute, $config);
125
    }
126
127 1
    public function radioList(FormModelInterface $formModel, string $attribute, array $config = []): RadioList
128
    {
129
        return $this
130 1
            ->field(RadioList::class, $config)
131 1
            ->attribute($formModel, $attribute);
132
    }
133
134 1
    public function range(FormModelInterface $formModel, string $attribute, array $config = []): Range
135
    {
136 1
        return $this->input(Range::class, $formModel, $attribute, $config);
137
    }
138
139 1
    public function resetButton(array $config = []): ResetButton
140
    {
141 1
        return $this->field(ResetButton::class, $config);
142
    }
143
144 1
    public function select(FormModelInterface $formModel, string $attribute, array $config = []): Select
145
    {
146 1
        return $this->input(Select::class, $formModel, $attribute, $config);
147
    }
148
149 1
    public function submitButton(array $config = []): SubmitButton
150
    {
151 1
        return $this->field(SubmitButton::class, $config);
152
    }
153
154 1
    public function telephone(FormModelInterface $formModel, string $attribute, array $config = []): Telephone
155
    {
156 1
        return $this->input(Telephone::class, $formModel, $attribute, $config);
157
    }
158
159 12
    public function text(FormModelInterface $formModel, string $attribute, array $config = []): Text
160
    {
161 12
        return $this->input(Text::class, $formModel, $attribute, $config);
162
    }
163
164 1
    public function textarea(FormModelInterface $formModel, string $attribute, array $config = []): Textarea
165
    {
166 1
        return $this->input(Textarea::class, $formModel, $attribute, $config);
167
    }
168
169 1
    public function url(FormModelInterface $formModel, string $attribute, array $config = []): Url
170
    {
171 1
        return $this->input(Url::class, $formModel, $attribute, $config);
172
    }
173
174 4
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
175
    {
176 4
        $widgetConfig = array_merge(
177 4
            $this->makeLabelConfig(),
178
            $config,
179
        );
180 4
        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\Part\Error or Yiisoft\Form\Field\Part\Hint or Yiisoft\Form\Field\RadioList or Yiisoft\Form\Field\Base\AbstractInputField or Yiisoft\Form\Field\CheckboxList. ( Ignorable by Annotation )

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

180
        return Label::widget($widgetConfig)->/** @scrutinizer ignore-call */ attribute($formModel, $attribute);
Loading history...
181
    }
182
183 3
    public function hint(FormModelInterface $formModel, string $attribute, array $config = []): Hint
184
    {
185 3
        $widgetConfig = array_merge(
186 3
            $this->hintConfig,
187
            $config,
188
        );
189 3
        return Hint::widget($widgetConfig)->attribute($formModel, $attribute);
190
    }
191
192 3
    public function error(FormModelInterface $formModel, string $attribute, array $config = []): Error
193
    {
194 3
        $widgetConfig = array_merge(
195 3
            $this->errorConfig,
196
            $config,
197
        );
198 3
        return Error::widget($widgetConfig)->attribute($formModel, $attribute);
199
    }
200
201
    /**
202
     * @psalm-template T
203
     * @psalm-param class-string<T> $class
204
     * @psalm-return T
205
     */
206 25
    public function input(string $class, FormModelInterface $formModel, string $attribute, array $config = []): object
207
    {
208 25
        $widget = $this->field($class, $config);
209 25
        if (!$widget instanceof AbstractInputField) {
210
            throw new InvalidArgumentException(
211
                sprintf(
212
                    'Input widget must be instance of "%s".',
213
                    AbstractInputField::class
214
                )
215
            );
216
        }
217
218 25
        return $widget->attribute($formModel, $attribute);
219
    }
220
221
    /**
222
     * @psalm-template T
223
     * @psalm-param class-string<T> $class
224
     * @psalm-return T
225
     */
226 32
    public function field(string $class, array $config = []): object
227
    {
228 32
        $traits = class_uses($class);
229 32
        if ($traits === false) {
230
            throw new RuntimeException('Invalid field class.');
231
        }
232
233 32
        $supports = [];
234 32
        if (in_array(PlaceholderTrait::class, $traits, true)) {
235 18
            $supports[] = self::SUPPORT_PLACEHOLDER;
236
        }
237
238 32
        $config = array_merge(
239 32
            $this->makeFieldConfig($supports),
240 32
            $this->fieldConfigs[$class] ?? [],
241
            $config,
242 32
            ['class' => $class],
243
        );
244
245
        /** @psalm-var T&AbstractField */
246 32
        return WidgetFactory::createWidget($config);
247
    }
248
249
    /**
250
     * @param int[] $supports
251
     */
252 32
    private function makeFieldConfig(array $supports): array
253
    {
254 32
        $config = $this->makeBaseFieldConfig();
255 32
        foreach ($supports as $support) {
256
            switch ($support) {
257 18
                case self::SUPPORT_PLACEHOLDER:
258 18
                    if ($this->usePlaceholder !== null) {
259 2
                        $config['usePlaceholder()'] = [$this->usePlaceholder];
260
                    }
261 18
                    break;
262
            }
263
        }
264 32
        return $config;
265
    }
266
267 32
    private function makeBaseFieldConfig(): array
268
    {
269 32
        if ($this->baseFieldConfig === null) {
270 10
            $this->baseFieldConfig = [];
271
272 10
            if ($this->containerTag !== null) {
273 2
                $this->baseFieldConfig['containerTag()'] = [$this->containerTag];
274
            }
275
276 10
            if ($this->containerTagAttributes !== []) {
277 2
                $this->baseFieldConfig['containerTagAttributes()'] = [$this->containerTagAttributes];
278
            }
279
280 10
            if ($this->useContainer !== null) {
281 1
                $this->baseFieldConfig['useContainer()'] = [$this->useContainer];
282
            }
283
284 10
            if ($this->template !== null) {
285 1
                $this->baseFieldConfig['template()'] = [$this->template];
286
            }
287
288 10
            if ($this->setInputIdAttribute !== null) {
289 1
                $this->baseFieldConfig['setInputIdAttribute()'] = [$this->setInputIdAttribute];
290
            }
291
292 10
            if ($this->inputTagAttributes !== []) {
293 2
                $this->baseFieldConfig['inputTagAttributes()'] = [$this->inputTagAttributes];
294
            }
295
296 10
            $labelConfig = $this->makeLabelConfig();
297 10
            if ($labelConfig !== []) {
298 2
                $this->baseFieldConfig['labelConfig()'] = [$labelConfig];
299
            }
300
301 10
            if ($this->hintConfig !== []) {
302 1
                $this->baseFieldConfig['hintConfig()'] = [$this->hintConfig];
303
            }
304
305 10
            if ($this->errorConfig !== []) {
306 1
                $this->baseFieldConfig['errorConfig()'] = [$this->errorConfig];
307
            }
308
        }
309 32
        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...
310
    }
311
312 14
    private function makeLabelConfig(): array
313
    {
314 14
        $config = [];
315
316 14
        if ($this->setInputIdAttribute === false) {
317 2
            $config['useInputIdAttribute()'] = [false];
318
        }
319
320 14
        return array_merge($config, $this->labelConfig);
321
    }
322
}
323