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
CheckboxSet
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
9.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
 setCheckboxAttribute
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
3
 setCheckboxAttributes
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
7
 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
 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
 getType
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 checkbox 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 CheckboxSet extends AbstractElement
30{
31
32    /**
33     * Array of checkbox input elements
34     * @var array
35     */
36    protected array $checkboxes = [];
37
38    /**
39     * Array of checked values
40     * @var array
41     */
42    protected array $checked = [];
43
44    /**
45     * Fieldset legend
46     * @var ?string
47     */
48    protected ?string $legend = null;
49
50    /**
51     * Constructor
52     *
53     * Instantiate a fieldset of checkbox input form elements
54     *
55     * @param  string            $name
56     * @param  array             $values
57     * @param  string|array|null $checked
58     * @param  ?string           $indent
59     */
60    public function __construct(string $name, array $values, string|array|null $checked = null, ?string $indent = null)
61    {
62        parent::__construct('fieldset');
63
64        $this->setName($name);
65        $this->setAttribute('class', 'checkbox-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 checkbox elements and related span elements.
76        $i = null;
77        foreach ($values as $k => $v) {
78            $checkbox = new Input\Checkbox($name . '[]', null, $indent);
79            $checkbox->setAttributes([
80                'class' => 'checkbox',
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                $checkbox->setAttributes($v['attributes']);
88            } else {
89                $nodeValue = $v;
90            }
91
92            // Determine if the current radio element is checked.
93            if (in_array($k, $this->checked)) {
94                $checkbox->check();
95            }
96
97            $span = new Child('span');
98            if ($indent !== null) {
99                $span->setIndent($indent);
100            }
101            $span->setAttribute('class', 'checkbox-span');
102            $span->setNodeValue($nodeValue);
103            $this->addChildren([$checkbox, $span]);
104            $this->checkboxes[] = $checkbox;
105            $i++;
106        }
107    }
108
109    /**
110     * Set whether the form element is disabled
111     *
112     * @param  bool $disabled
113     * @return CheckboxSet
114     */
115    public function setDisabled(bool $disabled): CheckboxSet
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 CheckboxSet
135     */
136    public function setReadonly(bool $readonly): CheckboxSet
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 checkbox elements
155     *
156     * @param  string $a
157     * @param  string $v
158     * @return Child
159     */
160    public function setCheckboxAttribute(string $a, string $v): Child
161    {
162        foreach ($this->checkboxes as $checkbox) {
163            $checkbox->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 checkbox elements
174     *
175     * @param  array $a
176     * @return Child
177     */
178    public function setCheckboxAttributes(array $a): Child
179    {
180        foreach ($this->checkboxes as $checkbox) {
181            $checkbox->setAttributes($a);
182            if (isset($a['tabindex'])) {
183                $a['tabindex']++;
184            }
185        }
186        return $this;
187    }
188
189
190    /**
191     * Set the checked value of the checkbox form elements
192     *
193     * @param  mixed $value
194     * @return CheckboxSet
195     */
196    public function setValue(mixed $value): CheckboxSet
197    {
198        $this->checked = (!is_array($value)) ? [$value] : $value;
199
200        if ((count($this->checked) > 0) && ($this->hasChildren())) {
201            foreach ($this->childNodes as $child) {
202                if ($child instanceof Input\Checkbox) {
203                    if (in_array($child->getValue(), $this->checked)) {
204                        $child->check();
205                    } else {
206                        $child->uncheck();
207                    }
208                }
209            }
210        }
211        return $this;
212    }
213
214    /**
215     * Reset the value of the form element
216     *
217     * @return CheckboxSet
218     */
219    public function resetValue(): CheckboxSet
220    {
221        $this->checked = [];
222        foreach ($this->childNodes as $child) {
223            if ($child instanceof Input\Checkbox) {
224                $child->uncheck();
225            }
226        }
227        return $this;
228    }
229
230    /**
231     * Get checkbox form element checked value
232     *
233     * @return mixed
234     */
235    public function getValue(): mixed
236    {
237        return $this->checked;
238    }
239
240    /**
241     * Set the checked value
242     *
243     * @param  mixed $checked
244     * @return CheckboxSet
245     */
246    public function setChecked(mixed $checked): CheckboxSet
247    {
248        return $this->setValue($checked);
249    }
250
251    /**
252     * Get the checked value
253     *
254     * @return mixed
255     */
256    public function getChecked(): mixed
257    {
258        return $this->getValue();
259    }
260
261    /**
262     * Method to set fieldset legend
263     *
264     * @param  string $legend
265     * @return CheckboxSet
266     */
267    public function setLegend(string $legend): CheckboxSet
268    {
269        $this->legend = $legend;
270        return $this;
271    }
272
273    /**
274     * Method to get fieldset legend
275     *
276     * @return ?string
277     */
278    public function getLegend(): ?string
279    {
280        return $this->legend;
281    }
282
283    /**
284     * Get form element object type
285     *
286     * @return string
287     */
288    public function getType(): string
289    {
290        return 'checkbox';
291    }
292
293    /**
294     * Validate the form element object
295     *
296     * @param  array $formValues
297     * @return bool
298     */
299    public function validate(array $formValues = []): bool
300    {
301        $value = $this->getValue();
302
303        // Check if the element is required
304        if (($this->required) && empty($value)) {
305            $this->errors[] = 'This field is required.';
306        }
307
308        $this->validateValue($value, $formValues);
309
310        return (count($this->errors) == 0);
311    }
312
313    /**
314     * Render the child and its child nodes
315     *
316     * @param  int     $depth
317     * @param  ?string $indent
318     * @param  bool    $inner
319     * @return string
320     */
321    public function render(int $depth = 0, ?string $indent = null, bool $inner = false): string
322    {
323        if (!empty($this->legend)) {
324            $this->addChild(new Child('legend', $this->legend));
325        }
326        return parent::render($depth, $indent, $inner);
327    }
328
329}