Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
TabBuilder
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 8
110
0.00% covered (danger)
0.00%
0 / 1
 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 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 setLabel
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 setContentText
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setContentHtml
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setSelected
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
 build
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * TabBuilder.php
4 *
5 * This file is part of the Codex design system, the official design system
6 * for Wikimedia projects. It provides the `Tab` class, a builder for constructing
7 * individual tab items within the `Tabs` component using the Codex design system.
8 *
9 * Tabs consist of two or more tab items created for navigating between different sections of content.
10 * The `Tab` class allows for easy and flexible creation of these individual tab items.
11 *
12 * @category Builder
13 * @package  Codex\Builder
14 * @since    0.1.0
15 * @author   Doğu Abaris <abaris@null.net>
16 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
17 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
18 */
19
20namespace Wikimedia\Codex\Builder;
21
22use InvalidArgumentException;
23use Wikimedia\Codex\Component\HtmlSnippet;
24use Wikimedia\Codex\Component\Tab;
25
26/**
27 * TabBuilder
28 *
29 * This class implements the builder pattern to construct instances of Tab.
30 * It provides a fluent interface for setting various properties and building the
31 * final immutable object with predefined configurations and immutability.
32 *
33 * @category Builder
34 * @package  Codex\Builder
35 * @since    0.1.0
36 * @author   Doğu Abaris <abaris@null.net>
37 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
38 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
39 */
40class TabBuilder {
41
42    /**
43     * The ID for the tab.
44     */
45    protected string $id = '';
46
47    /**
48     * The unique name of the tab, used for programmatic selection.
49     */
50    protected string $name = '';
51
52    /**
53     * The text label displayed for the tab in the Tabs component's header.
54     */
55    protected string $label = '';
56
57    /**
58     * The HTML content associated with the tab, displayed when the tab is selected.
59     */
60    protected string $content = '';
61
62    /**
63     * Indicates whether the tab is selected by default.
64     */
65    protected bool $selected = false;
66
67    /**
68     * Indicates whether the tab is disabled, preventing interaction and navigation.
69     */
70    protected bool $disabled = false;
71
72    /**
73     * Set the tab HTML ID attribute.
74     *
75     * @since 0.1.0
76     * @param string $id The ID for the tab element.
77     * @return $this
78     */
79    public function setId( string $id ): self {
80        $this->id = $id;
81
82        return $this;
83    }
84
85    /**
86     * Set the name for the tab.
87     *
88     * The name is used for programmatic selection and it also serves as the default label if none is provided.
89     *
90     * @since 0.1.0
91     * @param string $name The unique name of the tab, used for programmatic selection.
92     * @return $this Returns the Tab instance for method chaining.
93     */
94    public function setName( string $name ): self {
95        if ( trim( $name ) === '' ) {
96            throw new InvalidArgumentException( 'Tab name cannot be empty.' );
97        }
98        $this->name = $name;
99
100        return $this;
101    }
102
103    /**
104     * Set the label for the tab.
105     *
106     * The label corresponds to the text displayed in the Tabs component's header for this tab.
107     * If not set, the label will default to the name of the tab.
108     *
109     * @since 0.1.0
110     * @param string $label The label text to be displayed in the Tabs component's header.
111     * @return $this Returns the Tab instance for method chaining.
112     */
113    public function setLabel( string $label ): self {
114        if ( trim( $label ) === '' ) {
115            throw new InvalidArgumentException( 'Tab label cannot be empty.' );
116        }
117        $this->label = $label;
118
119        return $this;
120    }
121
122    /**
123     * Set the content of the tab as plain text.
124     *
125     * This method sets the content of the tab as plain text, ensuring that the content is properly escaped
126     * to prevent any potential security risks.
127     *
128     * @since 0.1.0
129     * @param string $content The plain text content to be displayed inside the tab.
130     * @param-taint $content escapes_html
131     * @return $this Returns the Tab instance for method chaining.
132     */
133    public function setContentText( string $content ): self {
134        $this->content = $content;
135
136        return $this;
137    }
138
139    /**
140     * Set the content of the tab as HTML.
141     *
142     * This method accepts an `HtmlSnippet` object for safely passing HTML content to the tab.
143     *
144     * @since 0.1.0
145     * @param HtmlSnippet $content The HTML content to be displayed inside the tab.
146     * @param-taint $content exec_html
147     * @return $this Returns the Tab instance for method chaining.
148     */
149    public function setContentHtml( HtmlSnippet $content ): self {
150        $this->content = (string)$content;
151
152        return $this;
153    }
154
155    /**
156     * Set whether the tab should be selected by default.
157     *
158     * @since 0.1.0
159     * @param bool $selected Whether this tab should be selected by default.
160     * @return $this Returns the Tab instance for method chaining.
161     */
162    public function setSelected( bool $selected ): self {
163        $this->selected = $selected;
164
165        return $this;
166    }
167
168    /**
169     * Set the disabled state for the tab.
170     *
171     * Disabled tabs cannot be accessed via label clicks or keyboard navigation.
172     *
173     * @since 0.1.0
174     * @param bool $disabled Whether or not the tab is disabled.
175     * @return $this Returns the Tab instance for method chaining.
176     */
177    public function setDisabled( bool $disabled ): self {
178        $this->disabled = $disabled;
179
180        return $this;
181    }
182
183    /**
184     * Build and return the Tab component object.
185     * This method constructs the immutable Tab object with all the properties set via the builder.
186     *
187     * @since 0.1.0
188     * @return Tab The constructed Tab.
189     */
190    public function build(): Tab {
191        return new Tab(
192            $this->id,
193            $this->name,
194            $this->label,
195            $this->content,
196            $this->selected,
197            $this->disabled,
198        );
199    }
200}