Passed
Pull Request — master (#192)
by Alexander
02:31
created

FieldFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 0
c 2
b 1
f 0
nc 1
nop 11
dl 0
loc 13
ccs 1
cts 1
cp 1
crap 1
rs 10

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 RuntimeException;
8
9
use Yiisoft\Form\Field\Base\AbstractField;
10
use Yiisoft\Form\Field\Base\PlaceholderTrait;
11
use Yiisoft\Form\Field\Checkbox;
12
use Yiisoft\Form\Field\Date;
13
use Yiisoft\Form\Field\DateTimeLocal;
14
use Yiisoft\Form\Field\Email;
15
use Yiisoft\Form\Field\Hidden;
16
use Yiisoft\Form\Field\Part\Error;
17
use Yiisoft\Form\Field\Part\Hint;
18
use Yiisoft\Form\Field\Part\Label;
19
use Yiisoft\Form\Field\Text;
20
use Yiisoft\Widget\WidgetFactory;
21
22
use function in_array;
23
24
final class FieldFactory
25
{
26
    private const SUPPORT_PLACEHOLDER = 1;
27
28
    private ?array $baseFieldConfig = null;
29
30
    /**
31
     * @param array[] $fieldConfigs
32
     */
33 17
    public function __construct(
34
        private ?string $containerTag = null,
35
        private array $containerTagAttributes = [],
36
        private ?bool $useContainer = null,
37
        private ?string $template = null,
38
        private ?bool $setInputIdAttribute = null,
39
        private array $inputTagAttributes = [],
40
        private array $labelConfig = [],
41
        private array $hintConfig = [],
42
        private array $errorConfig = [],
43
        private ?bool $usePlaceholder = null,
44
        private array $fieldConfigs = [],
45
    ) {
46
    }
47
48 1
    public function checkbox(FormModelInterface $formModel, string $attribute, array $config = []): Checkbox
49
    {
50 1
        return $this->field(Checkbox::class, $formModel, $attribute, $config);
51
    }
52
53 1
    public function date(FormModelInterface $formModel, string $attribute, array $config = []): Date
54
    {
55 1
        return $this->field(Date::class, $formModel, $attribute, $config);
56
    }
57
58 1
    public function dateTimeLocal(FormModelInterface $formModel, string $attribute, array $config = []): DateTimeLocal
59
    {
60 1
        return $this->field(DateTimeLocal::class, $formModel, $attribute, $config);
61
    }
62
63 1
    public function email(FormModelInterface $formModel, string $attribute, array $config = []): Email
64
    {
65 1
        return $this->field(Email::class, $formModel, $attribute, $config);
66
    }
67
68 1
    public function hidden(FormModelInterface $formModel, string $attribute, array $config = []): Hidden
69
    {
70 1
        return $this->field(Hidden::class, $formModel, $attribute, $config);
71
    }
72
73 10
    public function text(FormModelInterface $formModel, string $attribute, array $config = []): Text
74
    {
75 10
        return $this->field(Text::class, $formModel, $attribute, $config);
76
    }
77
78 4
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
79
    {
80 4
        $widgetConfig = array_merge(
81 4
            $this->makeLabelConfig(),
82
            $config,
83
        );
84 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\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

84
        return Label::widget($widgetConfig)->/** @scrutinizer ignore-call */ attribute($formModel, $attribute);
Loading history...
85
    }
86
87 3
    public function hint(FormModelInterface $formModel, string $attribute, array $config = []): Hint
88
    {
89 3
        $widgetConfig = array_merge(
90 3
            $this->hintConfig,
91
            $config,
92
        );
93 3
        return Hint::widget($widgetConfig)->attribute($formModel, $attribute);
94
    }
95
96 3
    public function error(FormModelInterface $formModel, string $attribute, array $config = []): Error
97
    {
98 3
        $widgetConfig = array_merge(
99 3
            $this->errorConfig,
100
            $config,
101
        );
102 3
        return Error::widget($widgetConfig)->attribute($formModel, $attribute);
103
    }
104
105
    /**
106
     * @psalm-template T
107
     * @psalm-param class-string<T> $class
108
     * @psalm-return T
109
     */
110 15
    public function field(string $class, FormModelInterface $formModel, string $attribute, array $config = []): object
111
    {
112 15
        $traits = class_uses($class);
113 15
        if ($traits === false) {
114
            throw new RuntimeException('Invalid field class.');
115
        }
116
117 15
        $supports = [];
118 15
        if (in_array(PlaceholderTrait::class, $traits, true)) {
119 11
            $supports[] = self::SUPPORT_PLACEHOLDER;
120
        }
121
122 15
        $config = array_merge(
123 15
            $this->makeFieldConfig($supports),
124 15
            $this->fieldConfigs[$class] ?? [],
125
            $config,
126 15
            ['class' => $class],
127
        );
128
129
        /** @psalm-var T&AbstractField $widget */
130 15
        $widget = WidgetFactory::createWidget($config);
131
132 15
        return $widget->attribute($formModel, $attribute);
133
    }
134
135
    /**
136
     * @param int[] $supports
137
     */
138 15
    private function makeFieldConfig(array $supports): array
139
    {
140 15
        $config = $this->makeBaseFieldConfig();
141 15
        foreach ($supports as $support) {
142
            switch ($support) {
143 11
                case self::SUPPORT_PLACEHOLDER:
144 11
                    if ($this->usePlaceholder !== null) {
145 2
                        $config['usePlaceholder()'] = [$this->usePlaceholder];
146
                    }
147 11
                    break;
148
            }
149
        }
150 15
        return $config;
151
    }
152
153 15
    private function makeBaseFieldConfig(): array
154
    {
155 15
        if ($this->baseFieldConfig === null) {
156 10
            $this->baseFieldConfig = [];
157
158 10
            if ($this->containerTag !== null) {
159 2
                $this->baseFieldConfig['containerTag()'] = [$this->containerTag];
160
            }
161
162 10
            if ($this->containerTagAttributes !== []) {
163 2
                $this->baseFieldConfig['containerTagAttributes()'] = [$this->containerTagAttributes];
164
            }
165
166 10
            if ($this->useContainer !== null) {
167 1
                $this->baseFieldConfig['useContainer()'] = [$this->useContainer];
168
            }
169
170 10
            if ($this->template !== null) {
171 1
                $this->baseFieldConfig['template()'] = [$this->template];
172
            }
173
174 10
            if ($this->setInputIdAttribute !== null) {
175 1
                $this->baseFieldConfig['setInputIdAttribute()'] = [$this->setInputIdAttribute];
176
            }
177
178 10
            if ($this->inputTagAttributes !== []) {
179 2
                $this->baseFieldConfig['inputTagAttributes()'] = [$this->inputTagAttributes];
180
            }
181
182 10
            $labelConfig = $this->makeLabelConfig();
183 10
            if ($labelConfig !== []) {
184 2
                $this->baseFieldConfig['labelConfig()'] = [$labelConfig];
185
            }
186
187 10
            if ($this->hintConfig !== []) {
188 1
                $this->baseFieldConfig['hintConfig()'] = [$this->hintConfig];
189
            }
190
191 10
            if ($this->errorConfig !== []) {
192 1
                $this->baseFieldConfig['errorConfig()'] = [$this->errorConfig];
193
            }
194
        }
195 15
        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...
196
    }
197
198 14
    private function makeLabelConfig(): array
199
    {
200 14
        $config = [];
201
202 14
        if ($this->setInputIdAttribute === false) {
203 2
            $config['useInputIdAttribute()'] = [false];
204
        }
205
206 14
        return array_merge($config, $this->labelConfig);
207
    }
208
}
209