Test Failed
Pull Request — master (#192)
by Sergei
02:42
created

FieldFactory::__construct()   B

Complexity

Conditions 7
Paths 27

Size

Total Lines 31
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 7
eloc 6
nc 27
nop 21
dl 0
loc 31
rs 8.8333
c 3
b 1
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form;
6
7
use InvalidArgumentException;
8
use Yiisoft\Form\Field\Base\EnrichmentFromRules\EnrichmentFromRulesInterface;
9
use Yiisoft\Form\Field\Base\InputField;
10
use Yiisoft\Form\Field\Base\PartsField;
11
use Yiisoft\Form\Field\Base\Placeholder\PlaceholderInterface;
12
use Yiisoft\Form\Field\Base\ValidationClass\ValidationClassInterface;
13
use Yiisoft\Form\Field\Button;
14
use Yiisoft\Form\Field\ButtonGroup;
15
use Yiisoft\Form\Field\Checkbox;
16
use Yiisoft\Form\Field\CheckboxList;
17
use Yiisoft\Form\Field\Date;
18
use Yiisoft\Form\Field\DateTime;
19
use Yiisoft\Form\Field\DateTimeLocal;
20
use Yiisoft\Form\Field\Email;
21
use Yiisoft\Form\Field\ErrorSummary;
22
use Yiisoft\Form\Field\Fieldset;
23
use Yiisoft\Form\Field\File;
24
use Yiisoft\Form\Field\Hidden;
25
use Yiisoft\Form\Field\Image;
26
use Yiisoft\Form\Field\Number;
27
use Yiisoft\Form\Field\Part\Error;
28
use Yiisoft\Form\Field\Part\Hint;
29
use Yiisoft\Form\Field\Part\Label;
30
use Yiisoft\Form\Field\Password;
31
use Yiisoft\Form\Field\RadioList;
32
use Yiisoft\Form\Field\Range;
33
use Yiisoft\Form\Field\ResetButton;
34
use Yiisoft\Form\Field\Select;
35
use Yiisoft\Form\Field\SubmitButton;
36
use Yiisoft\Form\Field\Telephone;
37
use Yiisoft\Form\Field\Text;
38
use Yiisoft\Form\Field\Textarea;
39
use Yiisoft\Form\Field\Url;
40
use Yiisoft\Widget\WidgetFactory;
41
42
final class FieldFactory
43
{
44
    /**
45
     * @param array[] $fieldConfigs
46
     */
47
    public function __construct(
48
        private ?string $containerTag = null,
49
        private array $containerAttributes = [],
50
        private string|array|null $containerClass = null,
51
        private ?bool $useContainer = null,
52
        private ?string $template = null,
53
        private ?string $templateBegin = null,
54
        private ?string $templateEnd = null,
55
        private ?bool $setInputId = null,
56
        private array $inputAttributes = [],
57
        private string|array|null $inputClass = null,
58
        string|array|null $labelClass = null,
59
        private array $labelConfig = [],
60
        string|array|null $hintClass = null,
61
        private array $hintConfig = [],
62
        string|array|null $errorClass = null,
63
        private array $errorConfig = [],
64
        private ?bool $usePlaceholder = null,
65
        private ?string $validClass = null,
66
        private ?string $invalidClass = null,
67
        private ?bool $enrichmentFromRules = null,
68
        private array $fieldConfigs = [],
69
    ) {
70
        if ($labelClass !== null) {
71
            $this->labelConfig['class()'] = is_array($labelClass) ? $labelClass : [$labelClass];
0 ignored issues
show
introduced by
The condition is_array($labelClass) is always true.
Loading history...
72
        }
73
        if ($hintClass !== null) {
74
            $this->hintConfig['class()'] = is_array($hintClass) ? $hintClass : [$hintClass];
0 ignored issues
show
introduced by
The condition is_array($hintClass) is always true.
Loading history...
75
        }
76
        if ($errorClass !== null) {
77
            $this->errorConfig['class()'] = is_array($errorClass) ? $errorClass : [$errorClass];
0 ignored issues
show
introduced by
The condition is_array($errorClass) is always true.
Loading history...
78
        }
79
    }
80
81
    public function button(array $config = []): Button
82
    {
83
        return $this->field(Button::class, $config);
84
    }
85
86
    public function buttonGroup(array $config = []): ButtonGroup
87
    {
88
        return $this->field(ButtonGroup::class, $config);
89
    }
90
91
    public function checkbox(FormModelInterface $formModel, string $attribute, array $config = []): Checkbox
92
    {
93
        return $this->input(Checkbox::class, $formModel, $attribute, $config);
94
    }
95
96
    public function checkboxList(FormModelInterface $formModel, string $attribute, array $config = []): CheckboxList
97
    {
98
        return $this
99
            ->field(CheckboxList::class, $config)
100
            ->formAttribute($formModel, $attribute);
101
    }
102
103
    public function date(FormModelInterface $formModel, string $attribute, array $config = []): Date
104
    {
105
        return $this->input(Date::class, $formModel, $attribute, $config);
106
    }
107
108
    public function dateTime(FormModelInterface $formModel, string $attribute, array $config = []): DateTime
109
    {
110
        return $this->input(DateTime::class, $formModel, $attribute, $config);
111
    }
112
113
    public function dateTimeLocal(FormModelInterface $formModel, string $attribute, array $config = []): DateTimeLocal
114
    {
115
        return $this->input(DateTimeLocal::class, $formModel, $attribute, $config);
116
    }
117
118
    public function email(FormModelInterface $formModel, string $attribute, array $config = []): Email
119
    {
120
        return $this->input(Email::class, $formModel, $attribute, $config);
121
    }
122
123
    public function errorSummary(FormModelInterface $formModel, array $config = []): ErrorSummary
124
    {
125
        return $this
126
            ->field(ErrorSummary::class, $config)
127
            ->formModel($formModel);
128
    }
129
130
    public function fieldset(array $config = []): Fieldset
131
    {
132
        return $this->field(Fieldset::class, $config);
133
    }
134
135
    public function file(FormModelInterface $formModel, string $attribute, array $config = []): File
136
    {
137
        return $this->input(File::class, $formModel, $attribute, $config);
138
    }
139
140
    public function hidden(FormModelInterface $formModel, string $attribute, array $config = []): Hidden
141
    {
142
        return $this->input(Hidden::class, $formModel, $attribute, $config);
143
    }
144
145
    public function image(array $config = []): Image
146
    {
147
        return $this->field(Image::class, $config);
148
    }
149
150
    public function number(FormModelInterface $formModel, string $attribute, array $config = []): Number
151
    {
152
        return $this->input(Number::class, $formModel, $attribute, $config);
153
    }
154
155
    public function password(FormModelInterface $formModel, string $attribute, array $config = []): Password
156
    {
157
        return $this->input(Password::class, $formModel, $attribute, $config);
158
    }
159
160
    public function radioList(FormModelInterface $formModel, string $attribute, array $config = []): RadioList
161
    {
162
        return $this
163
            ->field(RadioList::class, $config)
164
            ->formAttribute($formModel, $attribute);
165
    }
166
167
    public function range(FormModelInterface $formModel, string $attribute, array $config = []): Range
168
    {
169
        return $this->input(Range::class, $formModel, $attribute, $config);
170
    }
171
172
    public function resetButton(array $config = []): ResetButton
173
    {
174
        return $this->field(ResetButton::class, $config);
175
    }
176
177
    public function select(FormModelInterface $formModel, string $attribute, array $config = []): Select
178
    {
179
        return $this->input(Select::class, $formModel, $attribute, $config);
180
    }
181
182
    public function submitButton(array $config = []): SubmitButton
183
    {
184
        return $this->field(SubmitButton::class, $config);
185
    }
186
187
    public function telephone(FormModelInterface $formModel, string $attribute, array $config = []): Telephone
188
    {
189
        return $this->input(Telephone::class, $formModel, $attribute, $config);
190
    }
191
192
    public function text(FormModelInterface $formModel, string $attribute, array $config = []): Text
193
    {
194
        return $this->input(Text::class, $formModel, $attribute, $config);
195
    }
196
197
    public function textarea(FormModelInterface $formModel, string $attribute, array $config = []): Textarea
198
    {
199
        return $this->input(Textarea::class, $formModel, $attribute, $config);
200
    }
201
202
    public function url(FormModelInterface $formModel, string $attribute, array $config = []): Url
203
    {
204
        return $this->input(Url::class, $formModel, $attribute, $config);
205
    }
206
207
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
208
    {
209
        $widgetConfig = array_merge(
210
            $this->labelConfig,
211
            $config,
212
        );
213
        return Label::widget($widgetConfig)->formAttribute($formModel, $attribute);
0 ignored issues
show
Bug introduced by
The method formAttribute() 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\InputField 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

213
        return Label::widget($widgetConfig)->/** @scrutinizer ignore-call */ formAttribute($formModel, $attribute);
Loading history...
214
    }
215
216
    public function hint(FormModelInterface $formModel, string $attribute, array $config = []): Hint
217
    {
218
        $widgetConfig = array_merge(
219
            $this->hintConfig,
220
            $config,
221
        );
222
        return Hint::widget($widgetConfig)->formAttribute($formModel, $attribute);
223
    }
224
225
    public function error(FormModelInterface $formModel, string $attribute, array $config = []): Error
226
    {
227
        $widgetConfig = array_merge(
228
            $this->errorConfig,
229
            $config,
230
        );
231
        return Error::widget($widgetConfig)->formAttribute($formModel, $attribute);
232
    }
233
234
    /**
235
     * @psalm-template T
236
     * @psalm-param class-string<T> $class
237
     * @psalm-return T
238
     */
239
    public function input(string $class, FormModelInterface $formModel, string $attribute, array $config = []): object
240
    {
241
        $widget = $this->field($class, $config);
242
        if (!$widget instanceof InputField) {
243
            throw new InvalidArgumentException(
244
                sprintf(
245
                    'Input widget must be instance of "%s".',
246
                    InputField::class
247
                )
248
            );
249
        }
250
251
        return $widget->formAttribute($formModel, $attribute);
252
    }
253
254
    /**
255
     * @psalm-template T
256
     * @psalm-param class-string<T> $class
257
     * @psalm-return T
258
     */
259
    public function field(string $class, array $config = []): object
260
    {
261
        $config = array_merge(
262
            $this->makeFieldConfig($class),
263
            $this->fieldConfigs[$class] ?? [],
264
            $config,
265
            ['class' => $class],
266
        );
267
268
        /** @psalm-var T */
269
        return WidgetFactory::createWidget($config);
270
    }
271
272
    /**
273
     * @psalm-param class-string $class
274
     */
275
    private function makeFieldConfig(string $class): array
276
    {
277
        $config = [];
278
279
        if ($this->containerTag !== null) {
280
            $config['containerTag()'] = [$this->containerTag];
281
        }
282
        if ($this->containerAttributes !== []) {
283
            $config['containerAttributes()'] = [$this->containerAttributes];
284
        }
285
        if ($this->containerClass !== null) {
286
            $config['containerClass()'] = is_array($this->containerClass)
287
                ? $this->containerClass
288
                : [$this->containerClass];
289
        }
290
        if ($this->useContainer !== null) {
291
            $config['useContainer()'] = [$this->useContainer];
292
        }
293
294
        if (is_a($class, PartsField::class, true)) {
295
            if ($this->template !== null) {
296
                $config['template()'] = [$this->template];
297
            }
298
            if ($this->templateBegin !== null) {
299
                $config['templateBegin()'] = [$this->templateBegin];
300
            }
301
            if ($this->templateEnd !== null) {
302
                $config['templateEnd()'] = [$this->templateEnd];
303
            }
304
            if ($this->labelConfig !== []) {
305
                $config['labelConfig()'] = [$this->labelConfig];
306
            }
307
            if ($this->hintConfig !== []) {
308
                $config['hintConfig()'] = [$this->hintConfig];
309
            }
310
            if ($this->errorConfig !== []) {
311
                $config['errorConfig()'] = [$this->errorConfig];
312
            }
313
        }
314
315
        if (is_a($class, InputField::class, true)) {
316
            if ($this->setInputId !== null) {
317
                $config['setInputId()'] = [$this->setInputId];
318
                if ($this->setInputId === false) {
319
                    $config['labelConfig()'] = [
320
                        $this->labelConfig + ['useInputId()' => [false]],
321
                    ];
322
                }
323
            }
324
            if ($this->inputAttributes !== []) {
325
                $config['inputAttributes()'] = [$this->inputAttributes];
326
            }
327
            if ($this->inputClass !== null) {
328
                $config['inputClass()'] = is_array($this->inputClass)
329
                    ? $this->inputClass
330
                    : [$this->inputClass];
331
            }
332
        }
333
334
        if (is_a($class, PlaceholderInterface::class, true)) {
335
            if ($this->usePlaceholder !== null) {
336
                $config['usePlaceholder()'] = [$this->usePlaceholder];
337
            }
338
        }
339
340
        if (is_a($class, EnrichmentFromRulesInterface::class, true)) {
341
            if ($this->enrichmentFromRules !== null) {
342
                $config['enrichmentFromRules()'] = [$this->enrichmentFromRules];
343
            }
344
        }
345
346
        if (is_a($class, ValidationClassInterface::class, true)) {
347
            if ($this->validClass !== null) {
348
                $config['validClass()'] = [$this->validClass];
349
            }
350
            if ($this->invalidClass !== null) {
351
                $config['invalidClass()'] = [$this->invalidClass];
352
            }
353
        }
354
355
        return $config;
356
    }
357
}
358