Passed
Push — master ( 6b3bd5...b249fa )
by Sergei
05:31 queued 02:48
created

Range::beforeRender()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2.0625

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 0
dl 0
loc 5
ccs 3
cts 4
cp 0.75
crap 2.0625
rs 10
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 7
    public function max(float|int|string|Stringable|null $value): self
45
    {
46 7
        $new = clone $this;
47 7
        $new->inputAttributes['max'] = $value;
48 7
        return $new;
49
    }
50
51
    /**
52
     * Minimum value.
53
     *
54
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-min
55
     */
56 7
    public function min(float|int|string|Stringable|null $value): self
57
    {
58 7
        $new = clone $this;
59 7
        $new->inputAttributes['min'] = $value;
60 7
        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 5
    public function step(float|int|string|Stringable|null $value): self
69
    {
70 5
        $new = clone $this;
71 5
        $new->inputAttributes['step'] = $value;
72 5
        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 1
    public function list(?string $id): self
81
    {
82 1
        $new = clone $this;
83 1
        $new->inputAttributes['list'] = $id;
84 1
        return $new;
85
    }
86
87
    /**
88
     * @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-disabled
89
     */
90 1
    public function disabled(bool $disabled = true): self
91
    {
92 1
        $new = clone $this;
93 1
        $new->inputAttributes['disabled'] = $disabled;
94 1
        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 1
    public function ariaDescribedBy(?string $value): self
103
    {
104 1
        $new = clone $this;
105 1
        $new->inputAttributes['aria-describedby'] = $value;
106 1
        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 1
    public function ariaLabel(?string $value): self
115
    {
116 1
        $new = clone $this;
117 1
        $new->inputAttributes['aria-label'] = $value;
118 1
        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 1
    public function autofocus(bool $value = true): self
128
    {
129 1
        $new = clone $this;
130 1
        $new->inputAttributes['autofocus'] = $value;
131 1
        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 1
    public function tabIndex(?int $value): self
152
    {
153 1
        $new = clone $this;
154 1
        $new->inputAttributes['tabindex'] = $value;
155 1
        return $new;
156
    }
157
158 4
    public function showOutput(bool $show = true): self
159
    {
160 4
        $new = clone $this;
161 4
        $new->showOutput = $show;
162 4
        return $new;
163
    }
164
165 2
    public function outputTag(string $tagName): self
166
    {
167 2
        if ($tagName === '') {
168 1
            throw new InvalidArgumentException('The output tag name it cannot be empty value.');
169
        }
170
171 1
        $new = clone $this;
172 1
        $new->outputTag = $tagName;
173 1
        return $new;
174
    }
175
176 3
    public function outputAttributes(array $attributes): self
177
    {
178 3
        $new = clone $this;
179 3
        $new->outputAttributes = $attributes;
180 3
        return $new;
181
    }
182
183 1
    public function addOutputAttributes(array $attributes): self
184
    {
185 1
        $new = clone $this;
186 1
        $new->outputAttributes = array_merge($new->outputAttributes, $attributes);
187 1
        return $new;
188
    }
189
190 27
    protected function beforeRender(): void
191
    {
192 27
        parent::beforeRender();
193 27
        if ($this->enrichFromValidationRules) {
194
            $this->enrichment = ThemeContainer::getEnrichment($this, $this->getInputData());
195
        }
196
    }
197
198 27
    protected function generateInput(): string
199
    {
200 27
        $value = $this->getValue();
201
202 27
        if (!is_string($value) && !is_numeric($value) && $value !== null) {
203 1
            throw new InvalidArgumentException('Range field requires a string, numeric or null value.');
204
        }
205
206
        /** @psalm-suppress MixedArgument We guess that enrichment contain correct values. */
207 26
        $inputAttributes = array_merge(
208 26
            $this->enrichment['inputAttributes'] ?? [],
209 26
            $this->getInputAttributes()
210 26
        );
211
212 26
        $tag = Html::range($this->getName(), $value, $inputAttributes);
213 26
        if ($this->showOutput) {
214 4
            $tag = $tag
215 4
                ->showOutput()
216 4
                ->outputTag($this->outputTag)
217 4
                ->addOutputAttributes($this->outputAttributes);
218
        }
219
220 26
        return $tag->render();
221
    }
222
223 5
    protected function prepareContainerAttributes(array &$attributes): void
224
    {
225 5
        $this->addValidationClassToAttributes($attributes, $this->getInputData());
226
    }
227
228 26
    protected function prepareInputAttributes(array &$attributes): void
229
    {
230 26
        $this->addInputValidationClassToAttributes($attributes, $this->getInputData());
231
    }
232
}
233