Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 46 |
|
0.00% |
0 / 8 |
CRAP | |
0.00% |
0 / 1 |
SelectBuilder | |
0.00% |
0 / 46 |
|
0.00% |
0 / 8 |
306 | |
0.00% |
0 / 1 |
__construct | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
setId | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setOptions | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
30 | |||
setOptGroups | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
30 | |||
setAttributes | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
6 | |||
setDisabled | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
setSelectedOption | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
build | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
2 |
1 | <?php |
2 | /** |
3 | * SelectBuilder.php |
4 | * |
5 | * This file is part of the Codex design system, the official design system |
6 | * for Wikimedia projects. It provides the `Select` class, a builder for constructing |
7 | * select elements using the Codex design system. |
8 | * |
9 | * A Select is an input with a dropdown menu of predefined, selectable items. |
10 | * |
11 | * @category Builder |
12 | * @package Codex\Builder |
13 | * @since 0.1.0 |
14 | * @author Doğu Abaris <abaris@null.net> |
15 | * @license https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later |
16 | * @link https://doc.wikimedia.org/codex/main/ Codex Documentation |
17 | */ |
18 | |
19 | namespace Wikimedia\Codex\Builder; |
20 | |
21 | use InvalidArgumentException; |
22 | use Wikimedia\Codex\Component\Select; |
23 | use Wikimedia\Codex\Renderer\SelectRenderer; |
24 | |
25 | /** |
26 | * SelectBuilder |
27 | * |
28 | * This class implements the builder pattern to construct instances of Select. |
29 | * It provides a fluent interface for setting various properties and building the |
30 | * final immutable object with predefined configurations and immutability. |
31 | * |
32 | * @category Builder |
33 | * @package Codex\Builder |
34 | * @since 0.1.0 |
35 | * @author Doğu Abaris <abaris@null.net> |
36 | * @license https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later |
37 | * @link https://doc.wikimedia.org/codex/main/ Codex Documentation |
38 | */ |
39 | class SelectBuilder { |
40 | |
41 | /** |
42 | * The ID for the select. |
43 | */ |
44 | protected string $id = ''; |
45 | |
46 | /** |
47 | * The options available in the select dropdown. |
48 | */ |
49 | protected array $options = []; |
50 | |
51 | /** |
52 | * The optGroups that group options under labels in the select dropdown. |
53 | */ |
54 | protected array $optGroups = []; |
55 | |
56 | /** |
57 | * The selected option value. |
58 | */ |
59 | protected ?string $selectedOption = null; |
60 | |
61 | /** |
62 | * Additional HTML attributes for the `<select>` element. |
63 | */ |
64 | protected array $attributes = []; |
65 | |
66 | /** |
67 | * Indicates if the select element is disabled. |
68 | */ |
69 | protected bool $disabled = false; |
70 | |
71 | /** |
72 | * The renderer instance used to render the select. |
73 | */ |
74 | protected SelectRenderer $renderer; |
75 | |
76 | /** |
77 | * Constructor for the SelectBuilder class. |
78 | * |
79 | * @param SelectRenderer $renderer The renderer to use for rendering the select. |
80 | */ |
81 | public function __construct( SelectRenderer $renderer ) { |
82 | $this->renderer = $renderer; |
83 | } |
84 | |
85 | /** |
86 | * Set the Selects HTML ID attribute. |
87 | * |
88 | * @since 0.1.0 |
89 | * @param string $id The ID for the Select element. |
90 | * @return $this |
91 | */ |
92 | public function setId( string $id ): self { |
93 | $this->id = $id; |
94 | |
95 | return $this; |
96 | } |
97 | |
98 | /** |
99 | * Set one or more options for the select element. |
100 | * |
101 | * This method allows one or more options to be added to the select dropdown. |
102 | * Each option can be provided as a simple key-value pair, or as an array with `value`, `text`, |
103 | * and `selected` keys for more complex options. |
104 | * |
105 | * Example usage: |
106 | * |
107 | * // Using key-value pairs: |
108 | * $select->setOptions([ |
109 | * 'value1' => 'Label 1', |
110 | * 'value2' => 'Label 2' |
111 | * ]); |
112 | * |
113 | * // Using an array for more complex options: |
114 | * $select->setOptions([ |
115 | * ['value' => 'value1', 'text' => 'Label 1', 'selected' => true], |
116 | * ['value' => 'value2', 'text' => 'Label 2'] |
117 | * ]); |
118 | * |
119 | * @since 0.1.0 |
120 | * @param array $options An array of options, either as key-value pairs or |
121 | * arrays with `value`, `text`, and `selected` keys. |
122 | * @return $this Returns the Select instance for method chaining. |
123 | */ |
124 | public function setOptions( array $options ): self { |
125 | if ( !$options ) { |
126 | throw new InvalidArgumentException( 'At least one option is required for the select element.' ); |
127 | } |
128 | |
129 | foreach ( $options as $key => $option ) { |
130 | if ( is_string( $key ) ) { |
131 | // Handle key-value pairs for simple options |
132 | $this->options[] = ( new OptionBuilder ) |
133 | ->setValue( $key ) |
134 | ->setText( $option )->build(); |
135 | } elseif ( is_array( $option ) ) { |
136 | // Handle more complex array structure for options |
137 | $this->options[] = ( new OptionBuilder ) |
138 | ->setValue( $option['value'] ) |
139 | ->setText( $option['text'] ) |
140 | ->setSelected( $option['selected'] ?? false )->build(); |
141 | } |
142 | } |
143 | |
144 | return $this; |
145 | } |
146 | |
147 | /** |
148 | * Set the optGroups for the select element. |
149 | * |
150 | * This method allows options to be grouped under labels in the select dropdown. |
151 | * Each optGroup can contain options that are either key-value pairs or arrays with `value`, |
152 | * `text`, and `selected` keys for more complex options. |
153 | * |
154 | * Example usage: |
155 | * |
156 | * $select->setOptGroups([ |
157 | * 'Group 1' => [ |
158 | * 'value1' => 'Option 1', |
159 | * ['value' => 'value2', 'text' => 'Option 2', 'selected' => true] |
160 | * ], |
161 | * 'Group 2' => [ |
162 | * 'value3' => 'Option 3', |
163 | * 'value4' => 'Option 4' |
164 | * ] |
165 | * ]); |
166 | * |
167 | * @since 0.1.0 |
168 | * @param array $optGroups An associative array of optGroups where keys are labels and values are arrays of options. |
169 | * @return $this Returns the Select instance for method chaining. |
170 | */ |
171 | public function setOptGroups( array $optGroups ): self { |
172 | foreach ( $optGroups as $label => $groupOptions ) { |
173 | $group = []; |
174 | foreach ( $groupOptions as $key => $option ) { |
175 | if ( is_string( $key ) ) { |
176 | // Handle key-value pairs for options in the group |
177 | $group[] = ( new OptionBuilder ) |
178 | ->setValue( $key ) |
179 | ->setText( $option )->build(); |
180 | } elseif ( is_array( $option ) ) { |
181 | // Handle more complex array structure for group options |
182 | $group[] = ( new OptionBuilder ) |
183 | ->setValue( $option['value'] ) |
184 | ->setText( $option['text'] ) |
185 | ->setSelected( $option['selected'] ?? false )->build(); |
186 | } |
187 | } |
188 | $this->optGroups[$label] = $group; |
189 | } |
190 | |
191 | return $this; |
192 | } |
193 | |
194 | /** |
195 | * Set additional HTML attributes for the `<select>` element. |
196 | * |
197 | * This method allows custom HTML attributes to be added to the `<select>` element, |
198 | * such as `id`, `data-*`, `aria-*`, or any other valid attributes. These attributes can be used |
199 | * to enhance accessibility or integrate with JavaScript. |
200 | * |
201 | * Example usage: |
202 | * |
203 | * $select->setAttributes([ |
204 | * 'id' => 'select-example', |
205 | * 'data-category' => 'selection', |
206 | * ]); |
207 | * |
208 | * @since 0.1.0 |
209 | * @param array $attributes An associative array of HTML attributes. |
210 | * @return $this Returns the Select instance for method chaining. |
211 | */ |
212 | public function setAttributes( array $attributes ): self { |
213 | foreach ( $attributes as $key => $value ) { |
214 | $this->attributes[$key] = $value; |
215 | } |
216 | return $this; |
217 | } |
218 | |
219 | /** |
220 | * Set whether the select element should be disabled. |
221 | * |
222 | * This method disables the select element, preventing user interaction. |
223 | * When called with `true`, the `disabled` attribute is added to the `<select>` element. |
224 | * |
225 | * Example usage: |
226 | * |
227 | * $select->setDisabled(true); |
228 | * |
229 | * @since 0.1.0 |
230 | * @param bool $disabled Indicates whether the select element should be disabled. |
231 | * @return $this Returns the Select instance for method chaining. |
232 | */ |
233 | public function setDisabled( bool $disabled ): self { |
234 | $this->disabled = $disabled; |
235 | |
236 | return $this; |
237 | } |
238 | |
239 | /** |
240 | * Set the selected option for the select element. |
241 | * |
242 | * This method specifies which option should be selected by default when the select element is rendered. |
243 | * |
244 | * @since 0.1.0 |
245 | * @param string|null $value The value of the option to be selected, or null to unset the selection. |
246 | * @return $this Returns the Select instance for method chaining. |
247 | */ |
248 | public function setSelectedOption( ?string $value ): self { |
249 | $this->selectedOption = $value; |
250 | |
251 | return $this; |
252 | } |
253 | |
254 | /** |
255 | * Build and return the Select component object. |
256 | * This method constructs the immutable Select object with all the properties set via the builder. |
257 | * |
258 | * @since 0.1.0 |
259 | * @return Select The constructed Select. |
260 | */ |
261 | public function build(): Select { |
262 | return new Select( |
263 | $this->id, |
264 | $this->options, |
265 | $this->optGroups, |
266 | $this->selectedOption, |
267 | $this->attributes, |
268 | $this->disabled, |
269 | $this->renderer |
270 | ); |
271 | } |
272 | } |