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

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