Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.53% covered (success)
97.53%
79 / 81
93.33% covered (success)
93.33%
14 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
RadioSet
97.53% covered (success)
97.53%
79 / 81
93.33% covered (success)
93.33%
14 / 15
44
0.00% covered (danger)
0.00%
0 / 1
 __construct
93.10% covered (success)
93.10%
27 / 29
0.00% covered (danger)
0.00%
0 / 1
10.03
 setDisabled
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 setReadonly
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 setRadioAttribute
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setRadioAttributes
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setValue
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
6
 resetValue
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 getValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setChecked
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getChecked
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setLegend
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getLegend
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 validate
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 render
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Form\Element;
15
16use Pop\Dom\Child;
17
18/**
19 * Form radio element set class
20 *
21 * @category   Pop
22 * @package    Pop\Form
23 * @author     Nick Sagona, III <dev@nolainteractive.com>
24 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
25 * @license    http://www.popphp.org/license     New BSD License
26 * @version    4.0.0
27 */
28
29class RadioSet extends AbstractElement
30{
31
32    /**
33     * Array of radio input elements
34     * @var array
35     */
36    protected array $radios = [];
37
38    /**
39     * Array of checked values
40     * @var ?string
41     */
42    protected ?string $checked = null;
43
44    /**
45     * Fieldset legend
46     * @var ?string
47     */
48    protected ?string $legend = null;
49
50    /**
51     * Constructor
52     *
53     * Instantiate the radio input form elements
54     *
55     * @param  string  $name
56     * @param  array   $values
57     * @param  ?string $checked
58     * @param  ?string $indent
59     */
60    public function __construct(string $name, array $values, ?string $checked = null, ?string $indent = null)
61    {
62        parent::__construct('fieldset');
63
64        $this->setName($name);
65        $this->setAttribute('class', 'radio-fieldset');
66
67        if ($checked !== null) {
68            $this->setValue($checked);
69        }
70
71        if ($indent !== null) {
72            $this->setIndent($indent);
73        }
74
75        // Create the radio elements and related span elements.
76        $i = null;
77        foreach ($values as $k => $v) {
78            $radio = new Input\Radio($name, null, $indent);
79            $radio->setAttributes([
80                'class' => 'radio',
81                'id'    => ($name . $i),
82                'value' => $k
83            ]);
84
85            if (is_array($v) && isset($v['value']) && isset($v['attributes'])) {
86                $nodeValue = $v['value'];
87                $radio->setAttributes($v['attributes']);
88            } else {
89                $nodeValue = $v;
90            }
91
92            // Determine if the current radio element is checked.
93            if (($this->checked !== null) && ($k == $this->checked)) {
94                $radio->check();
95            }
96
97            $span = new Child('span');
98            if ($indent !== null) {
99                $span->setIndent($indent);
100            }
101            $span->setAttribute('class', 'radio-span');
102            $span->setNodeValue($nodeValue);
103            $this->addChildren([$radio, $span]);
104            $this->radios[] = $radio;
105            $i++;
106        }
107    }
108
109    /**
110     * Set whether the form element is disabled
111     *
112     * @param  bool $disabled
113     * @return RadioSet
114     */
115    public function setDisabled(bool $disabled): RadioSet
116    {
117        if ($disabled) {
118            foreach ($this->childNodes as $childNode) {
119                $childNode->setAttribute('disabled', 'disabled');
120            }
121        } else {
122            foreach ($this->childNodes as $childNode) {
123                $childNode->removeAttribute('disabled');
124            }
125        }
126
127        return parent::setDisabled($disabled);
128    }
129
130    /**
131     * Set whether the form element is readonly
132     *
133     * @param  bool $readonly
134     * @return RadioSet
135     */
136    public function setReadonly(bool $readonly): RadioSet
137    {
138        if ($readonly) {
139            foreach ($this->childNodes as $childNode) {
140                $childNode->setAttribute('readonly', 'readonly');
141                $childNode->setAttribute('onclick', 'return false;');
142            }
143        } else {
144            foreach ($this->childNodes as $childNode) {
145                $childNode->removeAttribute('readonly');
146                $childNode->removeAttribute('onclick');
147            }
148        }
149
150        return parent::setReadonly($readonly);
151    }
152
153    /**
154     * Set an attribute for the input radio elements
155     *
156     * @param  string $a
157     * @param  string $v
158     * @return Child
159     */
160    public function setRadioAttribute(string $a, string $v): Child
161    {
162        foreach ($this->radios as $radio) {
163            $radio->setAttribute($a, $v);
164            if ($a == 'tabindex') {
165                $v++;
166            }
167
168        }
169        return $this;
170    }
171
172    /**
173     * Set an attribute or attributes for the input radio elements
174     *
175     * @param  array $a
176     * @return Child
177     */
178    public function setRadioAttributes(array $a): Child
179    {
180        foreach ($this->radios as $radio) {
181            $radio->setAttributes($a);
182            if (isset($a['tabindex'])) {
183                $a['tabindex']++;
184            }
185        }
186        return $this;
187    }
188
189    /**
190     * Set the checked value of the radio form elements
191     *
192     * @param  mixed $value
193     * @return RadioSet
194     */
195    public function setValue(mixed $value): RadioSet
196    {
197        $this->checked = $value;
198
199        if (($this->checked !== null) && ($this->hasChildren())) {
200            foreach ($this->childNodes as $child) {
201                if ($child instanceof Input\Radio) {
202                    if ($child->getValue() == $this->checked) {
203                        $child->check();
204                    } else {
205                        $child->uncheck();
206                    }
207                }
208            }
209        }
210        return $this;
211    }
212
213    /**
214     * Reset the value of the form element
215     *
216     * @return RadioSet
217     */
218    public function resetValue(): RadioSet
219    {
220        $this->checked = null;
221        foreach ($this->childNodes as $child) {
222            if ($child instanceof Input\Radio) {
223                $child->uncheck();
224            }
225        }
226        return $this;
227    }
228
229    /**
230     * Get radio form element checked value
231     *
232     * @return mixed
233     */
234    public function getValue(): mixed
235    {
236        return $this->checked;
237    }
238
239    /**
240     * Get form element object type
241     *
242     * @return string
243     */
244    public function getType(): string
245    {
246        return 'radio';
247    }
248
249    /**
250     * Set the checked value
251     *
252     * @param  mixed $checked
253     * @return RadioSet
254     */
255    public function setChecked(mixed $checked): RadioSet
256    {
257        return $this->setValue($checked);
258    }
259
260    /**
261     * Get the checked value
262     *
263     * @return mixed
264     */
265    public function getChecked(): mixed
266    {
267        return $this->getValue();
268    }
269
270    /**
271     * Method to set fieldset legend
272     *
273     * @param  string $legend
274     * @return RadioSet
275     */
276    public function setLegend(string $legend): RadioSet
277    {
278        $this->legend = $legend;
279        return $this;
280    }
281
282    /**
283     * Method to get fieldset legend
284     *
285     * @return ?string
286     */
287    public function getLegend(): ?string
288    {
289        return $this->legend;
290    }
291
292    /**
293     * Validate the form element object
294     *
295     * @param  array $formValues
296     * @return bool
297     */
298    public function validate(array $formValues = []): bool
299    {
300        $value = $this->getValue();
301
302        // Check if the element is required
303        if (($this->required) && empty($value)) {
304            $this->errors[] = 'This field is required.';
305        }
306
307        $this->validateValue($value, $formValues);
308
309        return (count($this->errors) == 0);
310    }
311
312    /**
313     * Render the child and its child nodes
314     *
315     * @param  int     $depth
316     * @param  ?string $indent
317     * @param  bool    $inner
318     * @return string
319     */
320    public function render(int $depth = 0, ?string $indent = null, bool $inner = false): string
321    {
322        if (!empty($this->legend)) {
323            $this->addChild(new Child('legend', $this->legend));
324        }
325        return parent::render($depth, $indent, $inner);
326    }
327
328}