Passed
Push — master ( caef29...2aa586 )
by Wilmer
13:50 queued 11:33
created

CheckboxList   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 227
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 64
c 2
b 0
f 0
dl 0
loc 227
ccs 62
cts 62
cp 1
rs 10
wmc 15

11 Methods

Rating   Name   Duplication   Size   Complexity  
A itemsFormatter() 0 5 1
A disabled() 0 5 1
A separator() 0 5 1
A items() 0 5 1
A containerTag() 0 5 1
A itemsFromValues() 0 5 1
A individualItemsAttributes() 0 5 1
A itemsAttributes() 0 5 1
A containerAttributes() 0 5 1
A readonly() 0 5 1
A run() 0 36 5
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Form\Widget;
6
7
use Closure;
8
use InvalidArgumentException;
9
use Stringable;
10
use Yiisoft\Form\Helper\HtmlForm;
11
use Yiisoft\Form\Widget\Attribute\CommonAttributes;
12
use Yiisoft\Form\Widget\Attribute\ModelAttributes;
13
use Yiisoft\Html\Widget\CheckboxList\CheckboxItem;
14
use Yiisoft\Html\Widget\CheckboxList\CheckboxList as CheckboxListTag;
15
use Yiisoft\Widget\Widget;
16
17
/*
18
 * Generates a list of checkboxes.
19
 *
20
 * A checkbox list allows multiple selection.
21
 */
22
final class CheckboxList extends Widget
23
{
24
    use CommonAttributes;
25
    use ModelAttributes;
26
27
    private array $containerAttributes = [];
28
    private ?string $containerTag = 'div';
29
    /** @psalm-var array[] $value */
30
    private array $individualItemsAttributes = [];
31
    /** @var string[] */
32
    private array $items = [];
33
    /** @var bool[]|float[]|int[]|string[]|Stringable[] */
34
    private array $itemsAsValues = [];
0 ignored issues
show
introduced by
The private property $itemsAsValues is not used, and could be removed.
Loading history...
35
    private array $itemsAttributes = [];
36
    /** @psalm-var Closure(CheckboxItem):string|null */
37
    private ?Closure $itemsFormatter = null;
38
    /** @var bool[]|float[]|int[]|string[]|Stringable[] */
39
    private array $itemsFromValues = [];
40
    private string $separator = "\n";
41
42
    /**
43
     * The container attributes for generating the list of checkboxes tag using {@see CheckBoxList}.
44
     *
45
     * @param array $attributes
46
     *
47
     * @return static
48
     *
49
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
50
     */
51 3
    public function containerAttributes(array $attributes): self
52
    {
53 3
        $new = clone $this;
54 3
        $new->containerAttributes = $attributes;
55 3
        return $new;
56
    }
57
58
    /**
59
     * The tag name for the container element.
60
     *
61
     * @param string|null $tag tag name. if `null` disabled rendering.
62
     *
63
     * @return static
64
     */
65 5
    public function containerTag(?string $tag = null): self
66
    {
67 5
        $new = clone $this;
68 5
        $new->containerTag = $tag;
69 5
        return $new;
70
    }
71
72
    /**
73
     * Set whether the element is disabled or not.
74
     *
75
     * If this attribute is set to `true`, the element is disabled. Disabled elements are usually drawn with grayed-out
76
     * text.
77
     * If the element is disabled, it does not respond to user actions, it cannot be focused, and the command event
78
     * will not fire. In the case of form elements, it will not be submitted. Do not set the attribute to true, as
79
     * this will suggest you can set it to false to enable the element again, which is not the case.
80
     *
81
     * @param bool $value
82
     *
83
     * @return static
84
     *
85
     * @link https://www.w3.org/TR/html52/sec-forms.html#element-attrdef-disabledformelements-disabled
86
     */
87 2
    public function disabled(bool $value = true): self
88
    {
89 2
        $new = clone $this;
90 2
        $new->itemsAttributes['disabled'] = $value;
91 2
        return $new;
92
    }
93
94
    /**
95
     * The specified attributes for items.
96
     *
97
     * @param array $attributes
98
     *
99
     * @return static
100
     *
101
     * @psalm-param array[] $attributes
102
     */
103 3
    public function individualItemsAttributes(array $attributes = []): self
104
    {
105 3
        $new = clone $this;
106 3
        $new->individualItemsAttributes = $attributes;
107 3
        return $new;
108
    }
109
110
    /**
111
     * The data used to generate the list of checkboxes.
112
     *
113
     * The array keys are the list of checkboxes values, and the array key values are the corresponding labels.
114
     *
115
     * @param string[] $items
116
     *
117
     * @return static
118
     */
119 25
    public function items(array $items = []): self
120
    {
121 25
        $new = clone $this;
122 25
        $new->items = $items;
123 25
        return $new;
124
    }
125
126
    /**
127
     * The items attributes for generating the list of checkboxes tag using {@see CheckBoxList}.
128
     *
129
     * @param array $attributes
130
     *
131
     * @return static
132
     *
133
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
134
     */
135 4
    public function itemsAttributes(array $attributes = []): self
136
    {
137 4
        $new = clone $this;
138 4
        $new->itemsAttributes = $attributes;
139 4
        return $new;
140
    }
141
142
    /**
143
     * Callable, a callback that can be used to customize the generation of the HTML code corresponding to a single
144
     * item in $items.
145
     *
146
     * The signature of this callback must be:
147
     *
148
     * ```php
149
     * function ($index, $label, $name, $checked, $value)
150
     * ```
151
     *
152
     * @param Closure|null $formatter
153
     *
154
     * @return static
155
     *
156
     * @psalm-param Closure(CheckboxItem):string|null $formatter
157
     */
158 3
    public function itemsFormatter(?Closure $formatter): self
159
    {
160 3
        $new = clone $this;
161 3
        $new->itemsFormatter = $formatter;
162 3
        return $new;
163
    }
164
165
    /**
166
     * The data used to generate the list of checkboxes.
167
     *
168
     * The array keys are the list of checkboxes values, and the array values are the corresponding labels.
169
     *
170
     * @param bool[]|float[]|int[]|string[]|Stringable[] $itemsFromValues
171
     *
172
     * @return static
173
     */
174 15
    public function itemsFromValues(array $itemsFromValues = []): self
175
    {
176 15
        $new = clone $this;
177 15
        $new->itemsFromValues = $itemsFromValues;
178 15
        return $new;
179
    }
180
181
    /**
182
     * The readonly attribute is a boolean attribute that controls whether the user can edit the form control.
183
     * When specified, the element is not mutable.
184
     *
185
     * @return static
186
     *
187
     * @link https://html.spec.whatwg.org/multipage/input.html#attr-input-readonly
188
     */
189 3
    public function readonly(): self
190
    {
191 3
        $new = clone $this;
192 3
        $new->itemsAttributes['readonly'] = true;
193 3
        return $new;
194
    }
195
196
    /**
197
     * The HTML code that separates items.
198
     *
199
     * @param string $separator
200
     *
201
     * @return static
202
     */
203 3
    public function separator(string $separator): self
204
    {
205 3
        $new = clone $this;
206 3
        $new->separator = $separator;
207 3
        return $new;
208
    }
209
210
    /**
211
     * @return string the generated checkbox list.
212
     */
213 26
    protected function run(): string
214
    {
215 26
        $new = clone $this;
216 26
        $checkboxList = CheckboxListTag::create(HtmlForm::getInputName($new->getFormModel(), $new->attribute));
217
218
        /** @var iterable<int, scalar|Stringable>|scalar|Stringable|null */
219 26
        $value = HtmlForm::getAttributeValue($new->getFormModel(), $new->attribute);
220
221 26
        if (!is_iterable($value) && null !== $value) {
222 2
            throw new InvalidArgumentException('CheckboxList widget must be a array or null value.');
223
        }
224
225 24
        $new->containerAttributes['id'] = $new->containerAttributes['id'] ?? $new->getId();
226
227
        /** @var bool */
228 24
        $itemsEncodeLabels = $new->attributes['itemsEncodeLabels'] ?? true;
229
230
        /** @var bool */
231 24
        $itemsAsEncodeLabels = $new->attributes['itemsAsEncodeLabels'] ?? true;
232
233 24
        if ($new->items !== []) {
234 22
            $checkboxList = $checkboxList->items($new->items, $itemsEncodeLabels);
235 2
        } elseif ($new->itemsFromValues !== []) {
236 2
            $checkboxList = $checkboxList->itemsFromValues($new->itemsFromValues, $itemsAsEncodeLabels);
237
        }
238
239
        return $checkboxList
240 24
            ->checkboxAttributes($new->attributes)
241 24
            ->containerAttributes($new->containerAttributes)
242 24
            ->containerTag($new->containerTag)
243 24
            ->individualInputAttributes($new->individualItemsAttributes)
244 24
            ->itemFormatter($new->itemsFormatter)
245 24
            ->replaceCheckboxAttributes($new->itemsAttributes)
246 24
            ->separator($new->separator)
247 24
            ->values($value ?? [])
248 24
            ->render();
249
    }
250
}
251