Passed
Pull Request — master (#160)
by Wilmer
10:36
created

CheckboxList::run()   B

Complexity

Conditions 6
Paths 7

Size

Total Lines 44
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 23
CRAP Score 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 6
eloc 23
c 2
b 0
f 0
nc 7
nop 0
dl 0
loc 44
ccs 23
cts 23
cp 1
crap 6
rs 8.9297
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\GlobalAttributes;
12
use Yiisoft\Html\Widget\CheckboxList\CheckboxItem;
13
use Yiisoft\Html\Widget\CheckboxList\CheckboxList as CheckboxListTag;
14
15
/*
16
 * Generates a list of checkboxes.
17
 *
18
 * A checkbox list allows multiple selection.
19
 */
20
final class CheckboxList extends AbstractWidget
21
{
22
    use GlobalAttributes;
23
24
    private array $containerAttributes = [];
25
    private ?string $containerTag = 'div';
26
    /** @psalm-var array[] $value */
27
    private array $individualItemsAttributes = [];
28
    /** @var string[] */
29
    private array $items = [];
30
    /** @var bool[]|float[]|int[]|string[]|Stringable[] */
31
    private array $itemsAsValues = [];
0 ignored issues
show
introduced by
The private property $itemsAsValues is not used, and could be removed.
Loading history...
32
    private array $itemsAttributes = [];
33
    /** @psalm-var Closure(CheckboxItem):string|null */
34
    private ?Closure $itemsFormatter = null;
35
    /** @var bool[]|float[]|int[]|string[]|Stringable[] */
36
    private array $itemsFromValues = [];
37
    private string $separator = "\n";
38
39
    /**
40
     * The container attributes for generating the list of checkboxes tag using {@see CheckBoxList}.
41
     *
42
     * @param array $attributes
43
     *
44
     * @return static
45
     *
46
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
47
     */
48 4
    public function containerAttributes(array $attributes): self
49
    {
50 4
        $new = clone $this;
51 4
        $new->containerAttributes = $attributes;
52 4
        return $new;
53
    }
54
55
    /**
56
     * The tag name for the container element.
57
     *
58
     * @param string|null $tag tag name. if `null` disabled rendering.
59
     *
60
     * @return static
61
     */
62 7
    public function containerTag(?string $tag = null): self
63
    {
64 7
        $new = clone $this;
65 7
        $new->containerTag = $tag;
66 7
        return $new;
67
    }
68
69
    /**
70
     * The specified attributes for items.
71
     *
72
     * @param array $attributes
73
     *
74
     * @return static
75
     *
76
     * @psalm-param array[] $attributes
77
     */
78 4
    public function individualItemsAttributes(array $attributes = []): self
79
    {
80 4
        $new = clone $this;
81 4
        $new->individualItemsAttributes = $attributes;
82 4
        return $new;
83
    }
84
85
    /**
86
     * The data used to generate the list of checkboxes.
87
     *
88
     * The array keys are the list of checkboxes values, and the array key values are the corresponding labels.
89
     *
90
     * @param string[] $items
91
     *
92
     * @return static
93
     */
94 28
    public function items(array $items = []): self
95
    {
96 28
        $new = clone $this;
97 28
        $new->items = $items;
98 28
        return $new;
99
    }
100
101
    /**
102
     * The items attribute for generating the list of checkboxes tag using {@see CheckBoxList}.
103
     *
104
     * @param array $attributes
105
     *
106
     * @return static
107
     *
108
     * {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
109
     */
110 5
    public function itemsAttributes(array $attributes = []): self
111
    {
112 5
        $new = clone $this;
113 5
        $new->itemsAttributes = $attributes;
114 5
        return $new;
115
    }
116
117
    /**
118
     * Callable, a callback that can be used to customize the generation of the HTML code corresponding to a single
119
     * item in $items.
120
     *
121
     * The signature of this callback must be:
122
     *
123
     * ```php
124
     * function ($index, $label, $name, $checked, $value)
125
     * ```
126
     *
127
     * @param Closure|null $formatter
128
     *
129
     * @return static
130
     *
131
     * @psalm-param Closure(CheckboxItem):string|null $formatter
132
     */
133 4
    public function itemsFormatter(?Closure $formatter): self
134
    {
135 4
        $new = clone $this;
136 4
        $new->itemsFormatter = $formatter;
137 4
        return $new;
138
    }
139
140
    /**
141
     * The data used to generate the list of checkboxes.
142
     *
143
     * The array keys are the list of checkboxes values, and the array values are the corresponding labels.
144
     *
145
     * @param bool[]|float[]|int[]|string[]|Stringable[] $itemsFromValues
146
     *
147
     * @return static
148
     */
149 4
    public function itemsFromValues(array $itemsFromValues = []): self
150
    {
151 4
        $new = clone $this;
152 4
        $new->itemsFromValues = $itemsFromValues;
153 4
        return $new;
154
    }
155
156
    /**
157
     * The HTML code that separates items.
158
     *
159
     * @param string $separator
160
     *
161
     * @return static
162
     */
163 4
    public function separator(string $separator): self
164
    {
165 4
        $new = clone $this;
166 4
        $new->separator = $separator;
167 4
        return $new;
168
    }
169
170
    /**
171
     * @return string the generated checkbox list.
172
     */
173 33
    protected function run(): string
174
    {
175 33
        $new = clone $this;
176
177
        /**
178
         *  @var iterable<int, scalar|Stringable>|scalar|Stringable|null
179
         *
180
         *  @link https://html.spec.whatwg.org/multipage/input.html#attr-input-value
181
         */
182 33
        $value = HtmlForm::getAttributeValue($new->getFormModel(), $new->getAttribute());
183
184 33
        if (!is_iterable($value) && null !== $value) {
185 3
            throw new InvalidArgumentException('CheckboxList widget must be a array or null value.');
186
        }
187
188 30
        $checkboxList = CheckboxListTag::create($new->getName());
189
190 30
        $new->containerAttributes['id'] = $new->containerAttributes['id'] ?? $new->getId();
191
192
        /** @var bool */
193 30
        $itemsEncodeLabels = $new->attributes['itemsEncodeLabels'] ?? true;
194
195
        /** @var bool */
196 30
        $itemsAsEncodeLabels = $new->attributes['itemsAsEncodeLabels'] ?? true;
197
198 30
        if ($new->items !== []) {
199 27
            $checkboxList = $checkboxList->items($new->items, $itemsEncodeLabels);
200 3
        } elseif ($new->itemsFromValues !== []) {
201 3
            $checkboxList = $checkboxList->itemsFromValues($new->itemsFromValues, $itemsAsEncodeLabels);
202
        }
203
204 30
        if ($new->itemsAttributes !== []) {
205 4
            $checkboxList = $checkboxList->replaceCheckboxAttributes($new->itemsAttributes);
206
        }
207
208
        return $checkboxList
209 30
            ->checkboxAttributes($new->attributes)
210 30
            ->containerAttributes($new->containerAttributes)
211 30
            ->containerTag($new->containerTag)
212 30
            ->individualInputAttributes($new->individualItemsAttributes)
213 30
            ->itemFormatter($new->itemsFormatter)
214 30
            ->separator($new->separator)
215 30
            ->values($value ?? [])
216 30
            ->render();
217
    }
218
}
219