Passed
Pull Request — master (#192)
by Alexander
02:31
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\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