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

FieldFactory::makeBaseFieldConfig()   F

Complexity

Conditions 11
Paths 513

Size

Total Lines 43
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 11

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 22
c 1
b 0
f 0
nc 513
nop 0
dl 0
loc 43
ccs 23
cts 23
cp 1
crap 11
rs 3.8263

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Number;
17
use Yiisoft\Form\Field\Part\Error;
18
use Yiisoft\Form\Field\Part\Hint;
19
use Yiisoft\Form\Field\Part\Label;
20
use Yiisoft\Form\Field\Password;
21
use Yiisoft\Form\Field\Telephone;
22
use Yiisoft\Form\Field\Text;
23
use Yiisoft\Form\Field\Textarea;
24
use Yiisoft\Form\Field\Url;
25
use Yiisoft\Widget\WidgetFactory;
26
27
use function in_array;
28
29
final class FieldFactory
30
{
31
    private const SUPPORT_PLACEHOLDER = 1;
32
33
    private ?array $baseFieldConfig = null;
34
35
    /**
36
     * @param array[] $fieldConfigs
37
     */
38 17
    public function __construct(
39
        private ?string $containerTag = null,
40
        private array $containerTagAttributes = [],
41
        private ?bool $useContainer = null,
42
        private ?string $template = null,
43
        private ?bool $setInputIdAttribute = null,
44
        private array $inputTagAttributes = [],
45
        private array $labelConfig = [],
46
        private array $hintConfig = [],
47
        private array $errorConfig = [],
48
        private ?bool $usePlaceholder = null,
49
        private array $fieldConfigs = [],
50
    ) {
51
    }
52
53 1
    public function checkbox(FormModelInterface $formModel, string $attribute, array $config = []): Checkbox
54
    {
55 1
        return $this->field(Checkbox::class, $formModel, $attribute, $config);
56
    }
57
58 1
    public function date(FormModelInterface $formModel, string $attribute, array $config = []): Date
59
    {
60 1
        return $this->field(Date::class, $formModel, $attribute, $config);
61
    }
62
63 1
    public function dateTimeLocal(FormModelInterface $formModel, string $attribute, array $config = []): DateTimeLocal
64
    {
65 1
        return $this->field(DateTimeLocal::class, $formModel, $attribute, $config);
66
    }
67
68 1
    public function email(FormModelInterface $formModel, string $attribute, array $config = []): Email
69
    {
70 1
        return $this->field(Email::class, $formModel, $attribute, $config);
71
    }
72
73 1
    public function hidden(FormModelInterface $formModel, string $attribute, array $config = []): Hidden
74
    {
75 1
        return $this->field(Hidden::class, $formModel, $attribute, $config);
76
    }
77
78 1
    public function number(FormModelInterface $formModel, string $attribute, array $config = []): Number
79
    {
80 1
        return $this->field(Number::class, $formModel, $attribute, $config);
81
    }
82
83 1
    public function password(FormModelInterface $formModel, string $attribute, array $config = []): Password
84
    {
85 1
        return $this->field(Password::class, $formModel, $attribute, $config);
86
    }
87
88 1
    public function telephone(FormModelInterface $formModel, string $attribute, array $config = []): Telephone
89
    {
90 1
        return $this->field(Telephone::class, $formModel, $attribute, $config);
91
    }
92
93 10
    public function text(FormModelInterface $formModel, string $attribute, array $config = []): Text
94
    {
95 10
        return $this->field(Text::class, $formModel, $attribute, $config);
96
    }
97
98 1
    public function textarea(FormModelInterface $formModel, string $attribute, array $config = []): Textarea
99
    {
100 1
        return $this->field(Textarea::class, $formModel, $attribute, $config);
101
    }
102
103 1
    public function url(FormModelInterface $formModel, string $attribute, array $config = []): Url
104
    {
105 1
        return $this->field(Url::class, $formModel, $attribute, $config);
106
    }
107
108 4
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
109
    {
110 4
        $widgetConfig = array_merge(
111 4
            $this->makeLabelConfig(),
112
            $config,
113
        );
114 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

114
        return Label::widget($widgetConfig)->/** @scrutinizer ignore-call */ attribute($formModel, $attribute);
Loading history...
115
    }
116
117 3
    public function hint(FormModelInterface $formModel, string $attribute, array $config = []): Hint
118
    {
119 3
        $widgetConfig = array_merge(
120 3
            $this->hintConfig,
121
            $config,
122
        );
123 3
        return Hint::widget($widgetConfig)->attribute($formModel, $attribute);
124
    }
125
126 3
    public function error(FormModelInterface $formModel, string $attribute, array $config = []): Error
127
    {
128 3
        $widgetConfig = array_merge(
129 3
            $this->errorConfig,
130
            $config,
131
        );
132 3
        return Error::widget($widgetConfig)->attribute($formModel, $attribute);
133
    }
134
135
    /**
136
     * @psalm-template T
137
     * @psalm-param class-string<T> $class
138
     * @psalm-return T
139
     */
140 20
    public function field(string $class, FormModelInterface $formModel, string $attribute, array $config = []): object
141
    {
142 20
        $traits = class_uses($class);
143 20
        if ($traits === false) {
144
            throw new RuntimeException('Invalid field class.');
145
        }
146
147 20
        $supports = [];
148 20
        if (in_array(PlaceholderTrait::class, $traits, true)) {
149 16
            $supports[] = self::SUPPORT_PLACEHOLDER;
150
        }
151
152 20
        $config = array_merge(
153 20
            $this->makeFieldConfig($supports),
154 20
            $this->fieldConfigs[$class] ?? [],
155
            $config,
156 20
            ['class' => $class],
157
        );
158
159
        /** @psalm-var T&AbstractField $widget */
160 20
        $widget = WidgetFactory::createWidget($config);
161
162 20
        return $widget->attribute($formModel, $attribute);
163
    }
164
165
    /**
166
     * @param int[] $supports
167
     */
168 20
    private function makeFieldConfig(array $supports): array
169
    {
170 20
        $config = $this->makeBaseFieldConfig();
171 20
        foreach ($supports as $support) {
172
            switch ($support) {
173 16
                case self::SUPPORT_PLACEHOLDER:
174 16
                    if ($this->usePlaceholder !== null) {
175 2
                        $config['usePlaceholder()'] = [$this->usePlaceholder];
176
                    }
177 16
                    break;
178
            }
179
        }
180 20
        return $config;
181
    }
182
183 20
    private function makeBaseFieldConfig(): array
184
    {
185 20
        if ($this->baseFieldConfig === null) {
186 10
            $this->baseFieldConfig = [];
187
188 10
            if ($this->containerTag !== null) {
189 2
                $this->baseFieldConfig['containerTag()'] = [$this->containerTag];
190
            }
191
192 10
            if ($this->containerTagAttributes !== []) {
193 2
                $this->baseFieldConfig['containerTagAttributes()'] = [$this->containerTagAttributes];
194
            }
195
196 10
            if ($this->useContainer !== null) {
197 1
                $this->baseFieldConfig['useContainer()'] = [$this->useContainer];
198
            }
199
200 10
            if ($this->template !== null) {
201 1
                $this->baseFieldConfig['template()'] = [$this->template];
202
            }
203
204 10
            if ($this->setInputIdAttribute !== null) {
205 1
                $this->baseFieldConfig['setInputIdAttribute()'] = [$this->setInputIdAttribute];
206
            }
207
208 10
            if ($this->inputTagAttributes !== []) {
209 2
                $this->baseFieldConfig['inputTagAttributes()'] = [$this->inputTagAttributes];
210
            }
211
212 10
            $labelConfig = $this->makeLabelConfig();
213 10
            if ($labelConfig !== []) {
214 2
                $this->baseFieldConfig['labelConfig()'] = [$labelConfig];
215
            }
216
217 10
            if ($this->hintConfig !== []) {
218 1
                $this->baseFieldConfig['hintConfig()'] = [$this->hintConfig];
219
            }
220
221 10
            if ($this->errorConfig !== []) {
222 1
                $this->baseFieldConfig['errorConfig()'] = [$this->errorConfig];
223
            }
224
        }
225 20
        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...
226
    }
227
228 14
    private function makeLabelConfig(): array
229
    {
230 14
        $config = [];
231
232 14
        if ($this->setInputIdAttribute === false) {
233 2
            $config['useInputIdAttribute()'] = [false];
234
        }
235
236 14
        return array_merge($config, $this->labelConfig);
237
    }
238
}
239