Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
TextAreaBuilder
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 15
342
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
 setId
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
 setValue
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setTextAreaAttributes
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
 setDisabled
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setReadonly
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setHasStartIcon
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setHasEndIcon
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setStartIconClass
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setEndIconClass
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setPlaceholder
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setStatus
0.00% covered (danger)
0.00%
0 / 4
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
2
1<?php
2/**
3 * TextAreaBuilder.php
4 *
5 * This file is part of the Codex design system, the official design system
6 * for Wikimedia projects. It provides the `TextArea` class, a builder for constructing
7 * textarea components using the Codex design system.
8 *
9 * A TextArea is a multi-line text input that allows manual resizing if needed.
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
19namespace Wikimedia\Codex\Builder;
20
21use InvalidArgumentException;
22use Wikimedia\Codex\Component\TextArea;
23use Wikimedia\Codex\Renderer\TextAreaRenderer;
24
25/**
26 * TextAreaBuilder
27 *
28 * This class implements the builder pattern to construct instances of TextArea.
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 */
39class TextAreaBuilder {
40
41    /**
42     * Allowed validation statuses for the TextArea.
43     */
44    private const ALLOWED_STATUSES = [
45        'default',
46        'error',
47        'warning',
48        'success'
49    ];
50
51    /**
52     * The ID for the textarea.
53     */
54    protected string $id = '';
55
56    /**
57     * The name attribute of the textarea element.
58     */
59    private string $name = '';
60
61    /**
62     * The default value of the textarea.
63     */
64    private string $value = '';
65
66    /**
67     * Additional HTML attributes for the TextArea.
68     */
69    private array $textAreaAttributes = [];
70
71    /**
72     * Additional attributes for the wrapper element.
73     */
74    private array $wrapperAttributes = [];
75
76    /**
77     * Indicates whether the textarea is disabled. If true, the textarea is not editable.
78     */
79    private bool $disabled = false;
80
81    /**
82     * Indicates whether the textarea is read-only. If true, the content cannot be modified but can be selected.
83     */
84    private bool $readonly = false;
85
86    /**
87     * Indicates if a start icon should be displayed in the textarea. If true, a start icon is included.
88     */
89    private bool $hasStartIcon = false;
90
91    /**
92     * Indicates if an end icon should be displayed in the textarea. If true, an end icon is included.
93     */
94    private bool $hasEndIcon = false;
95
96    /**
97     * CSS class for the start icon. Used for styling the start icon.
98     */
99    private string $startIconClass = '';
100
101    /**
102     * CSS class for the end icon. Used for styling the end icon.
103     */
104    private string $endIconClass = '';
105
106    /**
107     * Placeholder text displayed in the textarea when it is empty.
108     */
109    private string $placeholder = '';
110
111    /**
112     * Validation status for the textarea.
113     */
114    private string $status = 'default';
115
116    /**
117     * The renderer instance used to render the textarea.
118     */
119    protected TextAreaRenderer $renderer;
120
121    /**
122     * Constructor for the TextArea class.
123     *
124     * @param TextAreaRenderer $renderer The renderer to use for rendering the textarea.
125     */
126    public function __construct( TextAreaRenderer $renderer ) {
127        $this->renderer = $renderer;
128    }
129
130    /**
131     * Set the TextArea HTML ID attribute.
132     *
133     * @since 0.1.0
134     * @param string $id The ID for the TextArea element.
135     * @return $this
136     */
137    public function setId( string $id ): self {
138        $this->id = $id;
139
140        return $this;
141    }
142
143    /**
144     * Set the name attribute for the textarea element.
145     *
146     * This method sets the name attribute for the textarea element, which is used to identify
147     * the textarea form control when submitting the form data.
148     *
149     * Example usage:
150     *
151     *     $textArea->setName('description');
152     *
153     * @since 0.1.0
154     * @param string $name The name attribute for the textarea.
155     * @return $this Returns the TextArea instance for method chaining.
156     */
157    public function setName( string $name ): self {
158        $this->name = $name;
159
160        return $this;
161    }
162
163    /**
164     * Set the default content inside the textarea.
165     *
166     * This method sets the initial content that will be displayed inside the textarea.
167     * The content can be prefilled with a default value if necessary.
168     *
169     * Example usage:
170     *
171     *     $textArea->setValue('Default content...');
172     *
173     * @since 0.1.0
174     * @param mixed $value The content to be displayed inside the textarea.
175     * @return $this Returns the TextArea instance for method chaining.
176     */
177    public function setValue( $value ): self {
178        $this->value = $value;
179
180        return $this;
181    }
182
183    /**
184     * Set additional HTML attributes for the textarea element.
185     *
186     * This method allows custom HTML attributes to be added to the textarea element,
187     * such as `id`, `data-*`, `aria-*`, or any other valid attributes that enhance functionality or accessibility.
188     *
189     * Example usage:
190     *
191     *     $textArea->setTextAreaAttributes([
192     *         'id' => 'text-area-id',
193     *         'data-category' => 'input',
194     *     ]);
195     *
196     * @since 0.1.0
197     * @param array $textAreaAttributes An associative array of HTML attributes for the textarea element.
198     * @return $this Returns the TextArea instance for method chaining.
199     */
200    public function setTextAreaAttributes( array $textAreaAttributes ): self {
201        foreach ( $textAreaAttributes as $key => $value ) {
202            $this->textAreaAttributes[$key] = $value;
203        }
204
205        return $this;
206    }
207
208    /**
209     * Set additional HTML attributes for the outer wrapper element.
210     *
211     * This method allows custom HTML attributes to be added to the outer wrapper element,
212     * enhancing its behavior or styling.
213     *
214     * Example usage:
215     *
216     *        $textArea->setWrapperAttributes(['id' => 'custom-wrapper']);
217     *
218     * @since 0.1.0
219     * @param array $wrapperAttributes An associative array of HTML attributes.
220     * @return $this Returns the TextArea instance for method chaining.
221     */
222    public function setWrapperAttributes( array $wrapperAttributes ): self {
223        foreach ( $wrapperAttributes as $key => $value ) {
224            $this->wrapperAttributes[$key] = $value;
225        }
226
227        return $this;
228    }
229
230    /**
231     * Set the disabled state for the textarea.
232     *
233     * This method disables the textarea, making it uneditable and visually distinct.
234     * The disabled attribute is useful for read-only forms or when the input is temporarily inactive.
235     *
236     * Example usage:
237     *
238     *     $textArea->setDisabled(true);
239     *
240     * @since 0.1.0
241     * @param bool $disabled Indicates whether the textarea should be disabled.
242     * @return $this Returns the TextArea instance for method chaining.
243     */
244    public function setDisabled( bool $disabled ): self {
245        $this->disabled = $disabled;
246
247        return $this;
248    }
249
250    /**
251     * Set the readonly state for the textarea.
252     *
253     * This method makes the textarea read-only, meaning users can view the content
254     * but cannot modify it. The readonly attribute is useful when displaying static content.
255     *
256     * Example usage:
257     *
258     *     $textArea->setReadonly(true);
259     *
260     * @since 0.1.0
261     * @param bool $readonly Indicates whether the textarea should be read-only.
262     * @return $this Returns the TextArea instance for method chaining.
263     */
264    public function setReadonly( bool $readonly ): self {
265        $this->readonly = $readonly;
266
267        return $this;
268    }
269
270    /**
271     * Set whether the textarea has a start icon.
272     *
273     * This method specifies whether the textarea should have an icon at the start.
274     * The icon can be used to visually indicate the type of input expected in the textarea.
275     *
276     * Example usage:
277     *
278     *     $textArea->setHasStartIcon(true);
279     *
280     * @since 0.1.0
281     * @param bool $hasStartIcon Indicates whether the textarea has a start icon.
282     * @return $this Returns the TextArea instance for method chaining.
283     */
284    public function setHasStartIcon( bool $hasStartIcon ): self {
285        $this->hasStartIcon = $hasStartIcon;
286
287        return $this;
288    }
289
290    /**
291     * Set whether the textarea has an end icon.
292     *
293     * This method specifies whether the textarea should have an icon at the end.
294     * The icon can be used to visually indicate additional functionality or context related to the input.
295     *
296     * Example usage:
297     *
298     *     $textArea->setHasEndIcon(true);
299     *
300     * @since 0.1.0
301     * @param bool $hasEndIcon Indicates whether the textarea has an end icon.
302     * @return $this Returns the TextArea instance for method chaining.
303     */
304    public function setHasEndIcon( bool $hasEndIcon ): self {
305        $this->hasEndIcon = $hasEndIcon;
306
307        return $this;
308    }
309
310    /**
311     * Set the CSS class for the start icon.
312     *
313     * This method specifies the CSS class that will be applied to the start icon.
314     * The class can be used to style the icon or apply a background image.
315     *
316     * Example usage:
317     *
318     *     $textArea->setStartIconClass('icon-class-name');
319     *
320     * @since 0.1.0
321     * @param string $startIconClass The CSS class for the start icon.
322     * @return $this Returns the TextArea instance for method chaining.
323     */
324    public function setStartIconClass( string $startIconClass ): self {
325        $this->startIconClass = $startIconClass;
326
327        return $this;
328    }
329
330    /**
331     * Set the CSS class for the end icon.
332     *
333     * This method specifies the CSS class that will be applied to the end icon.
334     * The class can be used to style the icon or apply a background image.
335     *
336     * Example usage:
337     *
338     *     $textArea->setEndIconClass('icon-class-name');
339     *
340     * @since 0.1.0
341     * @param string $endIconClass The CSS class for the end icon.
342     * @return $this Returns the TextArea instance for method chaining.
343     */
344    public function setEndIconClass( string $endIconClass ): self {
345        $this->endIconClass = $endIconClass;
346
347        return $this;
348    }
349
350    /**
351     * Set the placeholder text for the textarea element.
352     *
353     * This method specifies the placeholder text that will be displayed inside the textarea
354     * when it is empty. The placeholder provides a hint to the user about the expected input.
355     *
356     * Example usage:
357     *
358     *     $textArea->setPlaceholder('Rationale...');
359     *
360     * @since 0.1.0
361     * @param string $placeholder The placeholder text for the textarea.
362     * @return $this Returns the TextArea instance for method chaining.
363     */
364    public function setPlaceholder( string $placeholder ): self {
365        $this->placeholder = $placeholder;
366
367        return $this;
368    }
369
370    /**
371     * Set the validation status for the textarea.
372     *
373     * @since 0.1.0
374     * @param string $status Current validation status.
375     * @return $this
376     */
377    public function setStatus( string $status ): self {
378        if ( !in_array( $status, self::ALLOWED_STATUSES, true ) ) {
379            throw new InvalidArgumentException( "Invalid status: $status" );
380        }
381        $this->status = $status;
382
383        return $this;
384    }
385
386    /**
387     * Build and return the TextArea component object.
388     * This method constructs the immutable TextArea object with all the properties set via the builder.
389     *
390     * @since 0.1.0
391     * @return TextArea The constructed TextArea.
392     */
393    public function build(): TextArea {
394        return new TextArea(
395            $this->id,
396            $this->name,
397            $this->value,
398            $this->textAreaAttributes,
399            $this->wrapperAttributes,
400            $this->disabled,
401            $this->readonly,
402            $this->hasStartIcon,
403            $this->hasEndIcon,
404            $this->startIconClass,
405            $this->endIconClass,
406            $this->placeholder,
407            $this->status,
408            $this->renderer
409        );
410    }
411}