Test Failed
Push — extract-attributes ( 6e6144...c9c1de )
by Dmitriy
07:22 queued 12s
created

Input::getId()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 4
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 9
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget;
6
7
use Yiisoft\Arrays\ArrayHelper;
8
use Yiisoft\Form\FormModelInterface;
9
use Yiisoft\Form\Helper\HtmlForm;
10
use Yiisoft\Form\HtmlOptions\HtmlOptionsProvider;
11
use Yiisoft\Html\Html;
12
use Yiisoft\Widget\Widget;
13
use function in_array;
14
15
final class Input extends Widget
16
{
17
    private ?string $id = null;
18
    private FormModelInterface $data;
19
    private string $attribute;
20
    private array $options = [];
21
    private string $charset = 'UTF-8';
22
    private bool $noPlaceholder = false;
23
    private string $type;
24
25
    /**
26
     * Generates an input tag for the given form attribute.
27
     *
28
     * @return string the generated input tag.
29
     */
30
    public function run(): string
31
    {
32
        $new = clone $this;
33
34
        if ($new->noPlaceholder === false) {
35
            $new->setPlaceholder();
36
        }
37
38
        if (!empty($new->getId())) {
39
            $new->options['id'] = $new->getId();
40
        }
41
42
        return Html::input($new->type, $new->getName(), $new->getValue())
43
            ->attributes($new->options)
44
            ->render();
45
    }
46
47
    /**
48
     * Set form model, name and options for the widget.
49
     *
50
     * @param FormModelInterface $data Form model.
51
     * @param string $attribute Form model property this widget is rendered for.
52
     * @param array $options The HTML attributes for the widget container tag.
53
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
54
     *
55
     * @return self
56
     */
57
    public function config(FormModelInterface $data, string $attribute, array $options = []): self
58
    {
59
        $new = clone $this;
60
        $new->data = $data;
61
        $new->attribute = $attribute;
62
        $rules = $data->getRules()[$attribute] ?? [];
63
        foreach ($rules as $rule) {
64
            if ($rule instanceof HtmlOptionsProvider) {
65
                $new->options = array_merge($new->options, $rule->getHtmlOptions());
66
            }
67
        }
68
        $new->options = array_merge($new->options, $options);
69
        return $new;
70
    }
71
72
    /**
73
     * Focus on the control (put cursor into it) when the page loads.
74
     * Only one form element could be in focus at the same time.
75
     *
76
     * It cannot be applied if the type attribute has a hidden value (that is, you cannot automatically set the cursor
77
     * to a hidden control).
78
     *
79
     * @param bool $value
80
     *
81
     * @return self
82
     */
83
    public function autofocus(bool $value = true): self
84
    {
85
        $new = clone $this;
86
        $new->options['autofocus'] = $value;
87
        return $new;
88
    }
89
90
    /**
91
     * Set the character set used to generate the widget id. See {@see HtmlForm::getInputId()}.
92
     *
93
     * @param string $value
94
     *
95
     * @return self
96
     */
97
    public function charset(string $value): self
98
    {
99
        $new = clone $this;
100
        $new->charset = $value;
101
        return $new;
102
    }
103
104
    /**
105
     * Set whether the element is disabled or not.
106
     *
107
     * If this attribute is set to `true`, the element is disabled. Disabled elements are usually drawn with grayed-out
108
     * text.
109
     * If the element is disabled, it does not respond to user actions, it cannot be focused, and the command event
110
     * will not fire. In the case of form elements, it will not be submitted. Do not set the attribute to true, as
111
     * this will suggest you can set it to false to enable the element again, which is not the case.
112
     *
113
     * @param bool $value
114
     *
115
     * @return self
116
     */
117
    public function disabled(bool $value = true): self
118
    {
119
        $new = clone $this;
120
        $new->options['disabled'] = $value;
121
        return $new;
122
    }
123
124
    /**
125
     * Specifies the form element the tag input element belongs to. The value of this attribute must be the id
126
     * attribute of a {@see Form} element in the same document.
127
     *
128
     * @param string $value
129
     *
130
     * @return self
131
     */
132
    public function form(string $value): self
133
    {
134
        $new = clone $this;
135
        $new->options['form'] = $value;
136
        return $new;
137
    }
138
139
    /**
140
     * Allows you to disable placeholder.
141
     *
142
     * @param bool $value
143
     *
144
     * @return self
145
     */
146
    public function noPlaceholder(bool $value = true): self
147
    {
148
        $new = clone $this;
149
        $new->noPlaceholder = $value;
150
        return $new;
151
    }
152
153
    /**
154
     * It allows defining placeholder.
155
     *
156
     * @param string $value
157
     *
158
     * @return self
159
     */
160
    public function placeholder(string $value): self
161
    {
162
        $new = clone $this;
163
        $new->options['placeholder'] = $value;
164
        return $new;
165
    }
166
167
    /**
168
     * If it is required to fill in a value in order to submit the form.
169
     *
170
     * @param bool $value
171
     *
172
     * @return self
173
     */
174
    public function required(bool $value = true): self
175
    {
176
        $new = clone $this;
177
        $new->options['required'] = $value;
178
        return $new;
179
    }
180
181
    /**
182
     * The tabindex global attribute indicates that its element can be focused, and where it participates in sequential
183
     * keyboard navigation (usually with the Tab key, hence the name).
184
     *
185
     * It accepts an integer as a value, with different results depending on the integer's value:
186
     *
187
     * - A negative value (usually tabindex="-1") means that the element is not reachable via sequential keyboard
188
     * navigation, but could be focused with Javascript or visually. It's mostly useful to create accessible widgets
189
     * with JavaScript.
190
     * - tabindex="0" means that the element should be focusable in sequential keyboard navigation, but its order is
191
     * defined by the document's source order.
192
     * - A positive value means the element should be focusable in sequential keyboard navigation, with its order
193
     * defined by the value of the number. That is, tabindex="4" is focused before tabindex="5", but after tabindex="3".
194
     *
195
     * @param int $value
196
     *
197
     * @return self
198
     */
199
    public function tabIndex(int $value = 0): self
200
    {
201
        $new = clone $this;
202
        $new->options['tabindex'] = $value;
203
        return $new;
204
    }
205
206
    /**
207
     * Type of the input control to use.
208
     *
209
     * @param string $value
210
     *
211
     * @return self
212
     */
213
    public function type(string $value): self
214
    {
215
        $new = clone $this;
216
        $new->type = $value;
217
        return $new;
218
    }
219
220
    private function getId(): string
221
    {
222
        $id = $this->options['id'] ?? $this->id;
223
224
        if ($id === null) {
225
            $id = HtmlForm::getInputId($this->data, $this->attribute, $this->charset);
226
        }
227
228
        return $id !== false ? (string) $id : '';
229
    }
230
231
    private function getName(): string
232
    {
233
        return ArrayHelper::remove($this->options, 'name', HtmlForm::getInputName($this->data, $this->attribute));
234
    }
235
236
    private function getValue()
237
    {
238
        $value = HtmlForm::getAttributeValue($this->data, $this->attribute);
239
        if ($value !== null && is_scalar($value)) {
240
            $value = (string)$value;
241
        }
242
243
        return ArrayHelper::remove(
244
            $this->options,
245
            'value',
246
            $value
247
        );
248
    }
249
250
    private function setPlaceholder(): void
251
    {
252
        if (!isset($this->options['placeholder']) && !(in_array($this->type, ['date', 'file', 'hidden', 'color'], true))) {
253
            $attributeName = HtmlForm::getAttributeName($this->attribute);
254
            $this->options['placeholder'] = $this->data->getAttributeLabel($attributeName);
255
        }
256
    }
257
}
258