Test Failed
Pull Request — master (#159)
by Alexander
02:49
created

AbstractField::getInputName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field\Base;
6
7
use InvalidArgumentException;
8
use Yiisoft\Form\Field\Part\Error;
9
use Yiisoft\Form\Field\Part\Hint;
10
use Yiisoft\Form\Field\Part\Label;
11
use Yiisoft\Form\Helper\HtmlForm;
12
use Yiisoft\Html\Tag\Base\Tag;
13
use Yiisoft\Html\Tag\CustomTag;
14
use Yiisoft\Widget\Widget;
15
16
abstract class AbstractField extends Widget
17
{
18
    use FormAttributeTrait;
19
20
    /**
21
     * @psalm-var non-empty-string
22
     */
23
    private string $containerTag = 'div';
24
    private array $containerTagAttributes = [];
25
    private bool $withoutContainer = false;
26
27
    private string $template = "{label}\n{input}\n{hint}\n{error}";
28
29
    private ?string $inputId = null;
30
    private ?string $inputIdFromTag = null;
31
    private bool $setInputIdAttribute = true;
32
33
    private array $labelConfig = [];
34
    private array $hintConfig = [];
35
    private array $errorConfig = [];
36
37
    /**
38
     * @return static
39
     */
40
    final public function containerTag(string $tag): self
41
    {
42
        if ($tag === '') {
43
            throw new InvalidArgumentException('Tag name cannot be empty.');
44
        }
45
46
        $new = clone $this;
47
        $new->containerTag = $tag;
48
        return $new;
49
    }
50
51
    /**
52
     * @return static
53
     */
54
    final public function containerTagAttributes(array $attributes): self
55
    {
56
        $new = clone $this;
57
        $new->containerTagAttributes = $attributes;
58
        return $new;
59
    }
60
61
    final public function withoutContainer(): self
62
    {
63
        $new = clone $this;
64
        $new->withoutContainer = true;
65
        return $new;
66
    }
67
68
    /**
69
     * Set layout template for render a field.
70
     *
71
     * @param string $template
72
     *
73
     * @return static
74
     */
75
    final public function template(string $template): self
76
    {
77
        $new = clone $this;
78
        $new->template = $template;
79
        return $new;
80
    }
81
82
    /**
83
     * @return static
84
     */
85
    final public function inputId(?string $inputId): self
86
    {
87
        $new = clone $this;
88
        $new->inputId = $inputId;
89
        return $new;
90
    }
91
92
    /**
93
     * @return static
94
     */
95
    final public function setInputIdAttribute(bool $value): self
96
    {
97
        $new = clone $this;
98
        $new->setInputIdAttribute = $value;
99
        return $new;
100
    }
101
102
    /**
103
     * @return static
104
     */
105
    final public function labelConfig(array $config): self
106
    {
107
        $new = clone $this;
108
        $new->labelConfig = $config;
109
        return $new;
110
    }
111
112
    /**
113
     * @return static
114
     */
115
    final public function label(?string $content): self
116
    {
117
        $new = clone $this;
118
        $new->labelConfig['content()'] = [$content];
119
        return $new;
120
    }
121
122
    /**
123
     * @return static
124
     */
125
    final public function hintConfig(array $config): self
126
    {
127
        $new = clone $this;
128
        $new->hintConfig = $config;
129
        return $new;
130
    }
131
132
    final public function hint(?string $content): self
133
    {
134
        $new = clone $this;
135
        $new->hintConfig['content()'] = [$content];
136
        return $new;
137
    }
138
139
    /**
140
     * @return static
141
     */
142
    final public function errorConfig(array $config): self
143
    {
144
        $new = clone $this;
145
        $new->errorConfig = $config;
146
        return $new;
147
    }
148
149
    final protected function getInputName(): string
150
    {
151
        return HtmlForm::getInputName($this->getFormModel(), $this->attribute);
152
    }
153
154
    final protected function prepareIdInInputTag(Tag $tag): Tag
155
    {
156
        /** @var mixed $idFromTag */
157
        $idFromTag = $tag->getAttribute('id');
0 ignored issues
show
Bug introduced by
The method getAttribute() does not exist on Yiisoft\Html\Tag\Base\Tag. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

157
        /** @scrutinizer ignore-call */ 
158
        $idFromTag = $tag->getAttribute('id');

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
158
        if ($idFromTag !== null) {
159
            $this->inputIdFromTag = (string) $idFromTag;
160
        }
161
162
        if ($this->setInputIdAttribute) {
163
            if ($this->inputId !== null) {
164
                $tag = $tag->id($this->inputId);
165
            } elseif ($idFromTag === null) {
166
                $tag = $tag->id($this->getInputId());
167
            }
168
        }
169
170
        return $tag;
171
    }
172
173
    final protected function run(): string
174
    {
175
        if ($this->withoutContainer) {
176
            return $this->generateContent();
177
        }
178
179
        $containerTag = CustomTag::name($this->containerTag);
180
        if ($this->containerTagAttributes !== []) {
181
            $containerTag = $containerTag->attributes($this->containerTagAttributes);
182
        }
183
184
        return $containerTag->open()
185
            . PHP_EOL
186
            . $this->generateContent()
187
            . PHP_EOL
188
            . $containerTag->close();
189
    }
190
191
    abstract protected function generateInput(): string;
192
193
    private function generateContent(): string
194
    {
195
        $parts = [
196
            '{input}' => $this->generateInput(),
197
            '{label}' => $this->generateLabel(),
198
            '{hint}' => $this->generateHint(),
199
            '{error}' => $this->generateError(),
200
        ];
201
202
        return preg_replace('/^\h*\v+/m', '', trim(strtr($this->template, $parts)));
203
    }
204
205
    private function generateLabel(): string
206
    {
207
        $label = Label::widget($this->labelConfig)
208
            ->attribute($this->getFormModel(), $this->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

208
            ->/** @scrutinizer ignore-call */ attribute($this->getFormModel(), $this->attribute);
Loading history...
209
210
        if ($this->setInputIdAttribute === false) {
211
            $label = $label->useInputIdAttribute(false);
212
        }
213
214
        if ($this->inputId !== null) {
215
            $label = $label->forId($this->inputId);
216
        } elseif ($this->inputIdFromTag !== null) {
217
            $label = $label->forId($this->inputIdFromTag);
218
        }
219
220
        return $label->render();
221
    }
222
223
    private function generateHint(): string
224
    {
225
        return Hint::widget($this->hintConfig)
226
            ->attribute($this->getFormModel(), $this->attribute)
227
            ->render();
228
    }
229
230
    private function generateError(): string
231
    {
232
        return Error::widget($this->errorConfig)
233
            ->attribute($this->getFormModel(), $this->attribute)
234
            ->render();
235
    }
236
}
237