Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
TabsBuilder
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 6
156
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
 setCallbacks
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 setTab
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
12
 setAttributes
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 / 14
0.00% covered (danger)
0.00%
0 / 1
20
1<?php
2/**
3 * TabsBuilder.php
4 *
5 * This file is part of the Codex design system, the official design system
6 * for Wikimedia projects. It provides the `Tabs` class, a builder for constructing
7 * tabs components using the Codex design system.
8 *
9 * Tabs consist of two or more tab items created for navigating between different sections of content.
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\Tab;
23use Wikimedia\Codex\Component\Tabs;
24use Wikimedia\Codex\Contract\IWebRequestCallbacks;
25use Wikimedia\Codex\Renderer\TabsRenderer;
26
27/**
28 * TabsBuilder
29 *
30 * This class implements the builder pattern to construct instances of Tabs.
31 * It provides a fluent interface for setting various properties and building the
32 * final immutable object with predefined configurations and immutability.
33 *
34 * @category Builder
35 * @package  Codex\Builder
36 * @since    0.1.0
37 * @author   Doğu Abaris <abaris@null.net>
38 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
39 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
40 */
41class TabsBuilder {
42
43    /**
44     * The ID for the tabs.
45     */
46    protected string $id = '';
47
48    /**
49     * An array of Tab objects representing each tab in the component.
50     */
51    private array $tabs = [];
52
53    /**
54     * Additional MarkupHandler attributes for the `<form>` element.
55     */
56    protected array $attributes = [];
57
58    /**
59     * The IWebRequestCallbacks implementation used for request handling.
60     */
61    protected IWebRequestCallbacks $callbacks;
62
63    /**
64     * The renderer instance used to render the tabs.
65     */
66    protected TabsRenderer $renderer;
67
68    /**
69     * Constructor for the Tabs class.
70     *
71     * @param TabsRenderer $renderer The renderer to use for rendering the tabs.
72     */
73    public function __construct( TabsRenderer $renderer ) {
74        $this->renderer = $renderer;
75    }
76
77    /**
78     * Set the Tabs HTML ID attribute.
79     *
80     * @since 0.1.0
81     * @param string $id The ID for the Tabs element.
82     * @return $this
83     */
84    public function setId( string $id ): self {
85        $this->id = $id;
86
87        return $this;
88    }
89
90    /**
91     * Set the IWebRequestCallbacks implementation for request handling.
92     *
93     * @param IWebRequestCallbacks $callbacks The IWebRequestCallbacks implementation.
94     *
95     * @return $this
96     */
97    public function setCallbacks( IWebRequestCallbacks $callbacks ): self {
98        $this->callbacks = $callbacks;
99
100        return $this;
101    }
102
103    /**
104     * Add one or more tabs to the tabs component.
105     *
106     * This method allows the addition of one or more `Tab` objects to the tabs component.
107     * Each tab's properties, such as label, content, selected state, and disabled state,
108     * are used to construct and configure the tabs.
109     *
110     * Example usage:
111     *
112     *     $tabs->setTab($tab1)
113     *         ->setTab([$tab2, $tab3]);
114     *
115     * @since 0.1.0
116     * @param TabBuilder|array $tab A `Tab` object or an array of `Tab` objects to add.
117     * @return $this Returns the Tabs instance for method chaining.
118     */
119    public function setTab( $tab ): self {
120        if ( is_array( $tab ) ) {
121            foreach ( $tab as $t ) {
122                $this->tabs[] = $t;
123            }
124        } else {
125            $this->tabs[] = $tab;
126        }
127
128        return $this;
129    }
130
131    /**
132     * Set additional HTML attributes for the `<form>` element.
133     *
134     * This method allows custom HTML attributes to be added to the `<form>` element that wraps the tabs,
135     * such as `id`, `data-*`, `aria-*`, or any other valid attributes. These attributes can be used
136     * to enhance accessibility or integrate with JavaScript.
137     *
138     * Example usage:
139     *
140     *     $tabs->setAttributes([
141     *         'id' => 'tabs-form',
142     *         'data-category' => 'navigation',
143     *     ]);
144     *
145     * @since 0.1.0
146     * @param array $attributes An associative array of HTML attributes.
147     * @return $this Returns the Tabs instance for method chaining.
148     */
149    public function setAttributes( array $attributes ): self {
150        foreach ( $attributes as $key => $value ) {
151            $this->attributes[$key] = $value;
152        }
153        return $this;
154    }
155
156    /**
157     * Build and return the Tabs component object.
158     * This method constructs the immutable Tabs object with all the properties set via the builder.
159     *
160     * @since 0.1.0
161     * @return Tabs The constructed Tabs.
162     */
163    public function build(): Tabs {
164        $tabComponents = [];
165        foreach ( $this->tabs as $tab ) {
166            if ( $tab instanceof TabBuilder ) {
167                $tabComponents[] = $tab->build();
168            } elseif ( $tab instanceof Tab ) {
169                $tabComponents[] = $tab;
170            } else {
171                throw new InvalidArgumentException( 'All tabs must be instances of TabBuilder or Tab' );
172            }
173        }
174
175        return new Tabs(
176            $this->id,
177            $tabComponents,
178            $this->attributes,
179            $this->callbacks,
180            $this->renderer
181        );
182    }
183}