Passed
Pull Request — master (#159)
by Sergei
11:02
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 0
Metric Value
cc 11
eloc 22
nc 513
nop 0
dl 0
loc 43
ccs 23
cts 23
cp 1
crap 11
rs 3.8263
c 0
b 0
f 0

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
use Yiisoft\Form\Field\Base\AbstractField;
9
use Yiisoft\Form\Field\Base\PlaceholderTrait;
10
use Yiisoft\Form\Field\Part\Error;
11
use Yiisoft\Form\Field\Part\Hint;
12
use Yiisoft\Form\Field\Part\Label;
13
use Yiisoft\Widget\WidgetFactory;
14
15
use function in_array;
16
17
final class FieldFactory
18
{
19
    private const PLACEHOLDER = 1;
20
21
    //
22
    // Common
23
    //
24
25
    private ?string $containerTag;
26
    private array $containerTagAttributes;
27
    private ?bool $useContainer;
28
29
    private ?string $template;
30
31
    private ?bool $setInputIdAttribute;
32
33
    private array $formElementTagAttributes;
34
35
    private array $labelConfig;
36
    private array $hintConfig;
37
    private array $errorConfig;
38
39
    //
40
    // Placeholder
41
    //
42
43
    private ?bool $usePlaceholder;
44
45
    //
46
    // Field configurations
47
    //
48
49
    /**
50
     * @var array[]
51
     */
52
    private array $fieldConfigs;
53
54
    //
55
    // Internal properties
56
    //
57
58
    private ?array $baseFieldConfig = null;
59
60 24
    public function __construct(FieldFactoryConfig $config)
61
    {
62 24
        $this->containerTag = $config->getContainerTag();
63 24
        $this->containerTagAttributes = $config->getContainerTagAttributes();
64 24
        $this->useContainer = $config->getUseContainer();
65
66 24
        $this->template = $config->getTemplate();
67
68 24
        $this->setInputIdAttribute = $config->getSetInputIdAttribute();
69
70 24
        $this->formElementTagAttributes = $config->getFormElementTagAttributes();
71
72 24
        $this->labelConfig = $config->getLabelConfig();
73 24
        $this->hintConfig = $config->getHintConfig();
74 24
        $this->errorConfig = $config->getErrorConfig();
75
76 24
        $this->usePlaceholder = $config->getUsePlaceholder();
77
78 24
        $this->fieldConfigs = $config->getFieldConfigs();
79 24
    }
80
81 5
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
82
    {
83 5
        $widgetConfig = array_merge(
84 5
            $this->makeLabelConfig(),
85
            $config,
86
        );
87 5
        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

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