Passed
Pull Request — master (#192)
by Sergei
02:16
created

FieldFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 1
eloc 0
c 2
b 1
f 0
nc 1
nop 11
dl 0
loc 13
ccs 1
cts 1
cp 1
crap 1
rs 10

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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