Passed
Pull Request — master (#160)
by Wilmer
02:43
created

RadioList::containerAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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