Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
RadioBuilder
0.00% covered (danger)
0.00%
0 / 37
0.00% covered (danger)
0.00%
0 / 11
240
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setInputId
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setName
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setLabel
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setValue
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setChecked
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setDisabled
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setInline
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setInputAttributes
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 setWrapperAttributes
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 build
0.00% covered (danger)
0.00%
0 / 16
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * RadioBuilder.php
4 *
5 * This file is part of the Codex design system, the official design system
6 * for Wikimedia projects. It provides the `Radio` class, a builder for constructing
7 * radio button components using the Codex design system.
8 *
9 * A Radio is a binary input that is usually combined in a group of two or more options.
10 * They signal a pattern where users can only select one of the available options. Radios
11 * are also known as “radio buttons.”
12 *
13 * @category Builder
14 * @package  Codex\Builder
15 * @since    0.1.0
16 * @author   Doğu Abaris <abaris@null.net>
17 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
18 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
19 */
20
21namespace Wikimedia\Codex\Builder;
22
23use InvalidArgumentException;
24use Wikimedia\Codex\Component\Label;
25use Wikimedia\Codex\Component\Radio;
26use Wikimedia\Codex\Renderer\RadioRenderer;
27
28/**
29 * RadioBuilder
30 *
31 * This class implements the builder pattern to construct instances of Radio.
32 * It provides a fluent interface for setting various properties and building the
33 * final immutable object with predefined configurations and immutability.
34 *
35 * @category Builder
36 * @package  Codex\Builder
37 * @since    0.1.0
38 * @author   Doğu Abaris <abaris@null.net>
39 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
40 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
41 */
42class RadioBuilder {
43
44    /**
45     * The ID for the radio input.
46     */
47    protected string $inputId = '';
48
49    /**
50     * The name attribute for the radio input.
51     */
52    protected string $name = '';
53
54    /**
55     * The label object for the radio.
56     */
57    protected ?Label $label = null;
58
59    /**
60     * The value associated with the radio input.
61     */
62    protected string $value = '';
63
64    /**
65     * Indicates if the radio is selected by default.
66     */
67    protected bool $checked = false;
68
69    /**
70     * Indicates if the radio is disabled.
71     */
72    protected bool $disabled = false;
73
74    /**
75     * Indicates if the radio should be displayed inline.
76     */
77    protected bool $inline = false;
78
79    /**
80     * Additional HTML attributes for the input.
81     */
82    private array $inputAttributes = [];
83
84    /**
85     * Additional attributes for the wrapper element.
86     */
87    private array $wrapperAttributes = [];
88
89    /**
90     * The renderer instance used to render the radio.
91     */
92    protected RadioRenderer $renderer;
93
94    /**
95     * Constructor for the RadioBuilder class.
96     *
97     * @param RadioRenderer $renderer The renderer to use for rendering the radio.
98     */
99    public function __construct( RadioRenderer $renderer ) {
100        $this->renderer = $renderer;
101    }
102
103    /**
104     * Set the ID for the radio input.
105     *
106     * The ID is a unique identifier for the radio input element. It is used to associate the input
107     * with its corresponding label and for any JavaScript or CSS targeting.
108     *
109     * @since 0.1.0
110     * @param string $inputId The ID for the radio input.
111     * @return $this Returns the Radio instance for method chaining.
112     */
113    public function setInputId( string $inputId ): self {
114        $this->inputId = $inputId;
115
116        return $this;
117    }
118
119    /**
120     * Set the name for the radio input.
121     *
122     * The name attribute is used to identify form data after the form is submitted. It is crucial when
123     * handling groups of radio buttons where only one option can be selected at a time.
124     *
125     * @since 0.1.0
126     * @param string $name The name attribute for the radio input.
127     * @return $this Returns the Radio instance for method chaining.
128     */
129    public function setName( string $name ): self {
130        $this->name = $name;
131
132        return $this;
133    }
134
135    /**
136     * Set the label for the radio input.
137     *
138     * This method accepts a Label object which provides a descriptive label for the radio.
139     *
140     * @since 0.1.0
141     * @param Label $label The Label object for the radio.
142     * @return $this Returns the Radio instance for method chaining.
143     */
144    public function setLabel( Label $label ): self {
145        $this->label = $label;
146
147        return $this;
148    }
149
150    /**
151     * Set the value for the radio input.
152     *
153     * The value is the data that is submitted when the radio button is selected and the form is submitted.
154     * This is particularly important when dealing with groups of radio buttons where each needs a distinct value.
155     *
156     * @since 0.1.0
157     * @param string $value The value for the radio input.
158     * @return $this Returns the Radio instance for method chaining.
159     */
160    public function setValue( string $value ): self {
161        $this->value = $value;
162
163        return $this;
164    }
165
166    /**
167     * Set whether the radio should be checked.
168     *
169     * This method determines whether the radio button is selected by default. If set to `true`,
170     * the radio button will be rendered in a checked state, otherwise, it will be unchecked.
171     *
172     * @since 0.1.0
173     * @param bool $checked Whether the radio button should be checked.
174     * @return $this Returns the Radio instance for method chaining.
175     */
176    public function setChecked( bool $checked ): self {
177        $this->checked = $checked;
178
179        return $this;
180    }
181
182    /**
183     * Set whether the radio should be disabled.
184     *
185     * This method determines whether the radio button is disabled, preventing user interaction.
186     * A disabled radio button cannot be selected or deselected by the user and is typically styled to appear inactive.
187     *
188     * @since 0.1.0
189     * @param bool $disabled Whether the radio button should be disabled.
190     * @return $this Returns the Radio instance for method chaining.
191     */
192    public function setDisabled( bool $disabled ): self {
193        $this->disabled = $disabled;
194
195        return $this;
196    }
197
198    /**
199     * Set whether the radio button should be displayed inline.
200     *
201     * This method determines whether the radio button and its label should be displayed inline with other elements.
202     * Inline radio buttons are typically used when multiple radio buttons need to appear on the same line.
203     *
204     * @since 0.1.0
205     * @param bool $inline Indicates whether the radio button should be displayed inline.
206     * @return $this Returns the Radio instance for method chaining.
207     */
208    public function setInline( bool $inline ): self {
209        $this->inline = $inline;
210
211        return $this;
212    }
213
214    /**
215     * Set additional HTML attributes for the radio input.
216     *
217     * This method allows custom HTML attributes to be added to the radio input element, such as `id`, `data-*`,
218     * `aria-*`, or any other valid attributes. These attributes can be used to integrate the radio button with
219     * JavaScript, enhance accessibility, or provide additional metadata.
220     *
221     * The values of these attributes are automatically escaped to prevent XSS vulnerabilities.
222     *
223     * Example usage:
224     *
225     *     $radio->setInputAttributes([
226     *         'id' => 'radio-button-1',
227     *         'data-toggle' => 'radio-toggle',
228     *         'aria-label' => 'Radio Button 1'
229     *     ]);
230     *
231     * @since 0.1.0
232     * @param array $inputAttributes An associative array of HTML attributes for the input element.
233     * @return $this Returns the Radio instance for method chaining.
234     */
235    public function setInputAttributes( array $inputAttributes ): self {
236        foreach ( $inputAttributes as $key => $value ) {
237            $this->inputAttributes[$key] = $value;
238        }
239
240        return $this;
241    }
242
243    /**
244     * Set additional HTML attributes for the outer wrapper element.
245     *
246     * This method allows custom HTML attributes to be added to the outer wrapper element,
247     * enhancing its behavior or styling.
248     *
249     * Example usage:
250     *
251     *     $textInput->setWrapperAttributes(['id' => 'custom-wrapper']);
252     *
253     * @since 0.1.0
254     * @param array $wrapperAttributes An associative array of HTML attributes for the wrapper element.
255     * @return $this Returns the Radio instance for method chaining.
256     */
257    public function setWrapperAttributes( array $wrapperAttributes ): self {
258        foreach ( $wrapperAttributes as $key => $value ) {
259            $this->wrapperAttributes[$key] = $value;
260        }
261
262        return $this;
263    }
264
265    /**
266     * Build and return the Radio component object.
267     * This method constructs the immutable Radio object with all the properties set via the builder.
268     *
269     * @since 0.1.0
270     * @return Radio The constructed Radio.
271     */
272    public function build(): Radio {
273        if ( !$this->inputId ) {
274            throw new InvalidArgumentException( "The 'id' is required for Radio." );
275        }
276        if ( !$this->label ) {
277            throw new InvalidArgumentException( "The 'label' is required for Radio." );
278        }
279
280        return new Radio(
281            $this->inputId,
282            $this->name,
283            $this->label,
284            $this->value,
285            $this->checked,
286            $this->disabled,
287            $this->inline,
288            $this->inputAttributes,
289            $this->wrapperAttributes,
290            $this->renderer,
291        );
292    }
293}