Passed
Pull Request — master (#192)
by Sergei
03:07
created

Number   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 179
Duplicated Lines 0 %

Test Coverage

Coverage 24.59%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 55
c 2
b 0
f 0
dl 0
loc 179
ccs 15
cts 61
cp 0.2459
rs 10
wmc 23

13 Methods

Rating   Name   Duplication   Size   Complexity  
A required() 0 5 1
B beforeRender() 0 16 8
A prepareInputTagAttributes() 0 3 1
A disabled() 0 5 1
A min() 0 5 1
A max() 0 5 1
A readonly() 0 5 1
A prepareContainerTagAttributes() 0 7 2
A generateInput() 0 11 3
A ariaLabel() 0 5 1
A autofocus() 0 5 1
A tabIndex() 0 5 1
A ariaDescribedBy() 0 5 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Field;
6
7
use InvalidArgumentException;
8
use Yiisoft\Form\Field\Base\EnrichmentFromRules\EnrichmentFromRulesInterface;
9
use Yiisoft\Form\Field\Base\EnrichmentFromRules\EnrichmentFromRulesTrait;
10
use Yiisoft\Form\Field\Base\InputField;
11
use Yiisoft\Form\Field\Base\Placeholder\PlaceholderInterface;
12
use Yiisoft\Form\Field\Base\Placeholder\PlaceholderTrait;
13
use Yiisoft\Form\Field\Base\ValidationClass\ValidationClassInterface;
14
use Yiisoft\Form\Field\Base\ValidationClass\ValidationClassTrait;
15
use Yiisoft\Html\Html;
16
use Yiisoft\Validator\Rule\Number as NumberRule;
17
use Yiisoft\Validator\Rule\Required;
18
19
/**
20
 * A control for setting the element's value to a string representing a number.
21
 *
22
 * @link https://html.spec.whatwg.org/multipage/input.html#number-state-(type=number)
23
 */
24
final class Number
25
    extends InputField
26
    implements EnrichmentFromRulesInterface, PlaceholderInterface, ValidationClassInterface
27
{
28
    use EnrichmentFromRulesTrait;
29
    use PlaceholderTrait;
30
    use ValidationClassTrait;
31
32
    /**
33
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-max
34
     */
35
    public function max(?string $value): self
36
    {
37
        $new = clone $this;
38
        $new->inputTagAttributes['max'] = $value;
39
        return $new;
40
    }
41
42
    /**
43
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-min
44
     */
45
    public function min(?string $value): self
46
    {
47
        $new = clone $this;
48
        $new->inputTagAttributes['min'] = $value;
49
        return $new;
50
    }
51
52
    /**
53
     * A boolean attribute that controls whether or not the user can edit the form control.
54
     *
55
     * @param bool $value Whether to allow the value to be edited by the user.
56
     *
57
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly
58
     */
59
    public function readonly(bool $value = true): self
60
    {
61
        $new = clone $this;
62
        $new->inputTagAttributes['readonly'] = $value;
63
        return $new;
64
    }
65
66
    /**
67
     * A boolean attribute. When specified, the element is required.
68
     *
69
     * @param bool $value Whether the control is required for form submission.
70
     *
71
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-required
72
     */
73
    public function required(bool $value = true): self
74
    {
75
        $new = clone $this;
76
        $new->inputTagAttributes['required'] = $value;
77
        return $new;
78
    }
79
80
    /**
81
     * @link https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#attr-fe-disabled
82
     */
83
    public function disabled(bool $disabled = true): self
84
    {
85
        $new = clone $this;
86
        $new->inputTagAttributes['disabled'] = $disabled;
87
        return $new;
88
    }
89
90
    /**
91
     * Identifies the element (or elements) that describes the object.
92
     *
93
     * @link https://w3c.github.io/aria/#aria-describedby
94
     */
95
    public function ariaDescribedBy(string $value): self
96
    {
97
        $new = clone $this;
98
        $new->inputTagAttributes['aria-describedby'] = $value;
99
        return $new;
100
    }
101
102
    /**
103
     * Defines a string value that labels the current element.
104
     *
105
     * @link https://w3c.github.io/aria/#aria-label
106
     */
107
    public function ariaLabel(string $value): self
108
    {
109
        $new = clone $this;
110
        $new->inputTagAttributes['aria-label'] = $value;
111
        return $new;
112
    }
113
114
    /**
115
     * Focus on the control (put cursor into it) when the page loads. Only one form element could be in focus
116
     * at the same time.
117
     *
118
     * @link https://html.spec.whatwg.org/multipage/interaction.html#attr-fe-autofocus
119
     */
120
    public function autofocus(bool $value = true): self
121
    {
122
        $new = clone $this;
123
        $new->inputTagAttributes['autofocus'] = $value;
124
        return $new;
125
    }
126
127
    /**
128
     * The `tabindex` attribute indicates that its element can be focused, and where it participates in sequential
129
     * keyboard navigation (usually with the Tab key, hence the name).
130
     *
131
     * It accepts an integer as a value, with different results depending on the integer's value:
132
     *
133
     * - A negative value (usually `tabindex="-1"`) means that the element is not reachable via sequential keyboard
134
     *   navigation, but could be focused with Javascript or visually. It's mostly useful to create accessible widgets
135
     *   with JavaScript.
136
     * - `tabindex="0"` means that the element should be focusable in sequential keyboard navigation, but its order is
137
     *   defined by the document's source order.
138
     * - A positive value means the element should be focusable in sequential keyboard navigation, with its order
139
     *   defined by the value of the number. That is, `tabindex="4"` is focused before `tabindex="5"`, but after
140
     *   `tabindex="3"`.
141
     *
142
     * @link https://html.spec.whatwg.org/multipage/interaction.html#attr-tabindex
143
     */
144
    public function tabIndex(?int $value): self
145
    {
146
        $new = clone $this;
147
        $new->inputTagAttributes['tabindex'] = $value;
148
        return $new;
149
    }
150
151
    /**
152
     * @psalm-suppress MixedAssignment,MixedArgument Remove after fix https://github.com/yiisoft/validator/issues/225
153
     */
154 1
    protected function beforeRender(): void
155
    {
156 1
        parent::beforeRender();
157 1
        if ($this->enrichmentFromRules && $this->hasFormModelAndAttribute()) {
158
            $rules = $this->getFormModel()->getRules()[$this->getAttributeName()] ?? [];
159
            foreach ($rules as $rule) {
160
                if ($rule instanceof Required) {
161
                    $this->inputTagAttributes['required'] = true;
162
                }
163
164
                if ($rule instanceof NumberRule) {
165
                    if (null !== $min = $rule->getOptions()['min']) {
166
                        $this->inputTagAttributes['min'] = $min;
167
                    }
168
                    if (null !== $max = $rule->getOptions()['max']) {
169
                        $this->inputTagAttributes['max'] = $max;
170
                    }
171
                }
172
            }
173
        }
174
    }
175
176 1
    protected function generateInput(): string
177
    {
178 1
        $value = $this->getAttributeValue();
179
180 1
        if (!is_numeric($value) && $value !== null) {
181
            throw new InvalidArgumentException('Number widget must be a numeric or null value.');
182
        }
183
184 1
        $tagAttributes = $this->getInputTagAttributes();
185
186 1
        return Html::input('number', $this->getInputName(), $value, $tagAttributes)->render();
187
    }
188
189 1
    protected function prepareContainerTagAttributes(array &$attributes): void
190
    {
191 1
        if ($this->hasFormModelAndAttribute()) {
192 1
            $this->addValidationClassToTagAttributes(
193
                $attributes,
194 1
                $this->getFormModel(),
195 1
                $this->getAttributeName(),
196
            );
197
        }
198
    }
199
200 1
    protected function prepareInputTagAttributes(array &$attributes): void
201
    {
202 1
        $this->preparePlaceholderInInputTagAttributes($attributes);
203
    }
204
}
205