Range::generateInput()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 5

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 13
c 1
b 0
f 0
nc 3
nop 0
dl 0
loc 23
ccs 15
cts 15
cp 1
crap 5
rs 9.5222
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field;
6
7
use InvalidArgumentException;
8
use Stringable;
9
use Yiisoft\Form\Field\Base\EnrichFromValidationRules\EnrichFromValidationRulesInterface;
10
use Yiisoft\Form\Field\Base\EnrichFromValidationRules\EnrichFromValidationRulesTrait;
11
use Yiisoft\Form\Field\Base\InputField;
12
use Yiisoft\Form\Field\Base\ValidationClass\ValidationClassInterface;
13
use Yiisoft\Form\Field\Base\ValidationClass\ValidationClassTrait;
14
use Yiisoft\Form\ThemeContainer;
15
use Yiisoft\Html\Html;
16
17
use function is_string;
18
19
/**
20
 * Represents `<input>` element of type "range" are let the user specify a numeric value which must be no less than
21
 * a given value, and no more than another given value.
22
 *
23
 * @link https://html.spec.whatwg.org/multipage/input.html#range-state-(type=range)
24
 * @link https://developer.mozilla.org/docs/Web/HTML/Element/input/range
25
 */
26
final class Range extends InputField implements EnrichFromValidationRulesInterface, ValidationClassInterface
27
{
28
    use EnrichFromValidationRulesTrait;
29
    use ValidationClassTrait;
30
31
    private bool $showOutput = false;
32
33
    /**
34
     * @psalm-var non-empty-string
35
     */
36
    private string $outputTag = 'span';
37
    private array $outputAttributes = [];
38
39
    /**
40
     * Maximum value.
41
     *
42
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-max
43
     */
44 10
    public function max(float|int|string|Stringable|null $value): self
45
    {
46 10
        $new = clone $this;
47 10
        $new->inputAttributes['max'] = $value;
48 10
        return $new;
49
    }
50
51
    /**
52
     * Minimum value.
53
     *
54
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-min
55
     */
56 10
    public function min(float|int|string|Stringable|null $value): self
57
    {
58 10
        $new = clone $this;
59 10
        $new->inputAttributes['min'] = $value;
60 10
        return $new;
61
    }
62
63
    /**
64
     * Granularity to be matched by the form control's value.
65
     *
66
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-step
67
     */
68 6
    public function step(float|int|string|Stringable|null $value): self
69
    {
70 6
        $new = clone $this;
71 6
        $new->inputAttributes['step'] = $value;
72 6
        return $new;
73
    }
74
75
    /**
76
     * ID of element that lists predefined options suggested to the user.
77
     *
78
     * @link https://html.spec.whatwg.org/multipage/input.html#the-list-attribute
79
     */
80 2
    public function list(?string $id): self
81
    {
82 2
        $new = clone $this;
83 2
        $new->inputAttributes['list'] = $id;
84 2
        return $new;
85
    }
86
87
    /**
88
     * @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-disabled
89
     */
90 2
    public function disabled(bool $disabled = true): self
91
    {
92 2
        $new = clone $this;
93 2
        $new->inputAttributes['disabled'] = $disabled;
94 2
        return $new;
95
    }
96
97
    /**
98
     * Identifies the element (or elements) that describes the object.
99
     *
100
     * @link https://w3c.github.io/aria/#aria-describedby
101
     */
102 2
    public function ariaDescribedBy(?string $value): self
103
    {
104 2
        $new = clone $this;
105 2
        $new->inputAttributes['aria-describedby'] = $value;
106 2
        return $new;
107
    }
108
109
    /**
110
     * Defines a string value that labels the current element.
111
     *
112
     * @link https://w3c.github.io/aria/#aria-label
113
     */
114 2
    public function ariaLabel(?string $value): self
115
    {
116 2
        $new = clone $this;
117 2
        $new->inputAttributes['aria-label'] = $value;
118 2
        return $new;
119
    }
120
121
    /**
122
     * Focus on the control (put cursor into it) when the page loads. Only one form element could be in focus
123
     * at the same time.
124
     *
125
     * @link https://html.spec.whatwg.org/multipage/interaction.html#attr-fe-autofocus
126
     */
127 2
    public function autofocus(bool $value = true): self
128
    {
129 2
        $new = clone $this;
130 2
        $new->inputAttributes['autofocus'] = $value;
131 2
        return $new;
132
    }
133
134
    /**
135
     * The `tabindex` attribute indicates that its element can be focused, and where it participates in sequential
136
     * keyboard navigation (usually with the Tab key, hence the name).
137
     *
138
     * It accepts an integer as a value, with different results depending on the integer's value:
139
     *
140
     * - A negative value (usually `tabindex="-1"`) means that the element is not reachable via sequential keyboard
141
     *   navigation, but could be focused with Javascript or visually. It's mostly useful to create accessible widgets
142
     *   with JavaScript.
143
     * - `tabindex="0"` means that the element should be focusable in sequential keyboard navigation, but its order is
144
     *   defined by the document's source order.
145
     * - A positive value means the element should be focusable in sequential keyboard navigation, with its order
146
     *   defined by the value of the number. That is, `tabindex="4"` is focused before `tabindex="5"`, but after
147
     *   `tabindex="3"`.
148
     *
149
     * @link https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex
150
     */
151 2
    public function tabIndex(?int $value): self
152
    {
153 2
        $new = clone $this;
154 2
        $new->inputAttributes['tabindex'] = $value;
155 2
        return $new;
156
    }
157
158 5
    public function showOutput(bool $show = true): self
159
    {
160 5
        $new = clone $this;
161 5
        $new->showOutput = $show;
162 5
        return $new;
163
    }
164
165 3
    public function outputTag(string $tagName): self
166
    {
167 3
        if ($tagName === '') {
168 1
            throw new InvalidArgumentException('The output tag name it cannot be empty value.');
169
        }
170
171 2
        $new = clone $this;
172 2
        $new->outputTag = $tagName;
173 2
        return $new;
174
    }
175
176 4
    public function outputAttributes(array $attributes): self
177
    {
178 4
        $new = clone $this;
179 4
        $new->outputAttributes = $attributes;
180 4
        return $new;
181
    }
182
183 2
    public function addOutputAttributes(array $attributes): self
184
    {
185 2
        $new = clone $this;
186 2
        $new->outputAttributes = array_merge($new->outputAttributes, $attributes);
187 2
        return $new;
188
    }
189
190 36
    protected function beforeRender(): void
191
    {
192 36
        if ($this->enrichFromValidationRules) {
193 1
            $this->enrichment = ThemeContainer::getEnrichment($this, $this->getInputData());
194
        }
195
    }
196
197 36
    protected function generateInput(): string
198
    {
199 36
        $value = $this->getValue();
200
201 36
        if (!is_string($value) && !is_numeric($value) && $value !== null) {
202 1
            throw new InvalidArgumentException('Range field requires a string, numeric or null value.');
203
        }
204
205
        /** @psalm-suppress MixedArgument We guess that enrichment contain correct values. */
206 35
        $inputAttributes = array_merge(
207 35
            $this->enrichment['inputAttributes'] ?? [],
208 35
            $this->getInputAttributes()
209 35
        );
210
211 35
        $tag = Html::range($this->getName(), $value, $inputAttributes);
212 35
        if ($this->showOutput) {
213 4
            $tag = $tag
214 4
                ->showOutput()
215 4
                ->outputTag($this->outputTag)
216 4
                ->addOutputAttributes($this->outputAttributes);
217
        }
218
219 35
        return $tag->render();
220
    }
221
222 14
    protected function prepareContainerAttributes(array &$attributes): void
223
    {
224 14
        $this->addValidationClassToAttributes(
225 14
            $attributes,
226 14
            $this->getInputData(),
227 14
            $this->hasCustomError() ? true : null,
228 14
        );
229
    }
230
231 35
    protected function prepareInputAttributes(array &$attributes): void
232
    {
233 35
        $this->addInputValidationClassToAttributes(
234 35
            $attributes,
235 35
            $this->getInputData(),
236 35
            $this->hasCustomError() ? true : null,
237 35
        );
238
    }
239
}
240