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

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