Passed
Pull Request — master (#192)
by Sergei
02:16
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
12
use Yiisoft\Form\Field\Part\Error;
13
use Yiisoft\Form\Field\Part\Hint;
14
use Yiisoft\Form\Field\Part\Label;
15
use Yiisoft\Widget\WidgetFactory;
16
17
use function in_array;
18
19
final class FieldFactory
20
{
21
    private const SUPPORT_PLACEHOLDER = 1;
22
23
    private ?array $baseFieldConfig = null;
24
25
    /**
26
     * @param array[] $fieldConfigs
27
     */
28 24
    public function __construct(
29
        private ?string $containerTag = null,
30
        private array $containerTagAttributes = [],
31
        private ?bool $useContainer = null,
32
        private ?string $template = null,
33
        private ?bool $setInputIdAttribute = null,
34
        private array $inputTagAttributes = [],
35
        private array $labelConfig = [],
36
        private array $hintConfig = [],
37
        private array $errorConfig = [],
38
        private ?bool $usePlaceholder = null,
39
        private array $fieldConfigs = [],
40
    ) {
41
    }
42
43 5
    public function label(FormModelInterface $formModel, string $attribute, array $config = []): Label
44
    {
45 5
        $widgetConfig = array_merge(
46 5
            $this->makeLabelConfig(),
47
            $config,
48
        );
49 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

49
        return Label::widget($widgetConfig)->/** @scrutinizer ignore-call */ attribute($formModel, $attribute);
Loading history...
50
    }
51
52 4
    public function hint(FormModelInterface $formModel, string $attribute, array $config = []): Hint
53
    {
54 4
        $widgetConfig = array_merge(
55 4
            $this->hintConfig,
56
            $config,
57
        );
58 4
        return Hint::widget($widgetConfig)->attribute($formModel, $attribute);
59
    }
60
61 4
    public function error(FormModelInterface $formModel, string $attribute, array $config = []): Error
62
    {
63 4
        $widgetConfig = array_merge(
64 4
            $this->errorConfig,
65
            $config,
66
        );
67 4
        return Error::widget($widgetConfig)->attribute($formModel, $attribute);
68
    }
69
70
    /**
71
     * @psalm-template T
72
     * @psalm-param class-string<T> $class
73
     * @psalm-return T
74
     */
75 11
    public function widget(
76
        string $class,
77
        FormModelInterface $formModel,
78
        string $attribute,
79
        array $config = []
80
    ): object {
81 11
        $traits = class_uses($class);
82 11
        if ($traits === false) {
83
            throw new RuntimeException('Invalid field class.');
84
        }
85
86 11
        $supports = [];
87 11
        if (in_array(PlaceholderTrait::class, $traits, true)) {
88 11
            $supports[] = self::SUPPORT_PLACEHOLDER;
89
        }
90
91 11
        $config = array_merge(
92 11
            $this->makeFieldConfig($supports),
93 11
            $this->fieldConfigs[$class] ?? [],
94
            $config,
95 11
            ['class' => $class],
96
        );
97
98
        /** @psalm-var T&AbstractField $widget */
99 11
        $widget = WidgetFactory::createWidget($config);
100
101 11
        return $widget->attribute($formModel, $attribute);
102
    }
103
104
    /**
105
     * @param int[] $supports
106
     */
107 11
    private function makeFieldConfig(array $supports): array
108
    {
109 11
        $config = $this->makeBaseFieldConfig();
110 11
        foreach ($supports as $support) {
111
            switch ($support) {
112 11
                case self::SUPPORT_PLACEHOLDER:
113 11
                    if ($this->usePlaceholder !== null) {
114 2
                        $config['usePlaceholder()'] = [$this->usePlaceholder];
115
                    }
116 11
                    break;
117
            }
118
        }
119 11
        return $config;
120
    }
121
122 11
    private function makeBaseFieldConfig(): array
123
    {
124 11
        if ($this->baseFieldConfig === null) {
125 11
            $this->baseFieldConfig = [];
126
127 11
            if ($this->containerTag !== null) {
128 2
                $this->baseFieldConfig['containerTag()'] = [$this->containerTag];
129
            }
130
131 11
            if ($this->containerTagAttributes !== []) {
132 2
                $this->baseFieldConfig['containerTagAttributes()'] = [$this->containerTagAttributes];
133
            }
134
135 11
            if ($this->useContainer !== null) {
136 1
                $this->baseFieldConfig['useContainer()'] = [$this->useContainer];
137
            }
138
139 11
            if ($this->template !== null) {
140 1
                $this->baseFieldConfig['template()'] = [$this->template];
141
            }
142
143 11
            if ($this->setInputIdAttribute !== null) {
144 1
                $this->baseFieldConfig['setInputIdAttribute()'] = [$this->setInputIdAttribute];
145
            }
146
147 11
            if ($this->inputTagAttributes !== []) {
148 2
                $this->baseFieldConfig['inputTagAttributes()'] = [$this->inputTagAttributes];
149
            }
150
151 11
            $labelConfig = $this->makeLabelConfig();
152 11
            if ($labelConfig !== []) {
153 2
                $this->baseFieldConfig['labelConfig()'] = [$labelConfig];
154
            }
155
156 11
            if ($this->hintConfig !== []) {
157 1
                $this->baseFieldConfig['hintConfig()'] = [$this->hintConfig];
158
            }
159
160 11
            if ($this->errorConfig !== []) {
161 1
                $this->baseFieldConfig['errorConfig()'] = [$this->errorConfig];
162
            }
163
        }
164 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...
165
    }
166
167 16
    private function makeLabelConfig(): array
168
    {
169 16
        $config = [];
170
171 16
        if ($this->setInputIdAttribute === false) {
172 2
            $config['useInputIdAttribute()'] = [false];
173
        }
174
175 16
        return array_merge($config, $this->labelConfig);
176
    }
177
}
178