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 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
TabsRenderer
0.00% covered (danger)
0.00%
0 / 47
0.00% covered (danger)
0.00%
0 / 2
56
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 render
0.00% covered (danger)
0.00%
0 / 43
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2/**
3 * TabsRenderer.php
4 *
5 * This file is part of the Codex PHP library, which provides a PHP-based interface for creating
6 * UI components consistent with the Codex design system.
7 *
8 * The `TabsRenderer` class leverages the `TemplateParser` and `Sanitizer` utilities to ensure the
9 * component object is rendered according to Codex design system standards.
10 *
11 * @category Renderer
12 * @package  Codex\Renderer
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\Renderer;
20
21use InvalidArgumentException;
22use UnexpectedValueException;
23use Wikimedia\Codex\Component\Tab;
24use Wikimedia\Codex\Component\Tabs;
25use Wikimedia\Codex\Contract\Renderer\IRenderer;
26use Wikimedia\Codex\ParamValidator\ParamDefinitions;
27use Wikimedia\Codex\ParamValidator\ParamValidator;
28use Wikimedia\Codex\ParamValidator\ParamValidatorCallbacks;
29use Wikimedia\Codex\Parser\TemplateParser;
30use Wikimedia\Codex\Traits\AttributeResolver;
31use Wikimedia\Codex\Utility\Sanitizer;
32
33/**
34 * TabsRenderer is responsible for rendering the HTML markup
35 * for a Tabs component using a Mustache template.
36 *
37 * This class uses the `TemplateParser` and `Sanitizer` utilities to manage
38 * the template rendering process, ensuring that the component object's HTML
39 * output adheres to the Codex design system's standards.
40 *
41 * @category Renderer
42 * @package  Codex\Renderer
43 * @since    0.1.0
44 * @author   Doğu Abaris <abaris@null.net>
45 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
46 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
47 */
48class TabsRenderer implements IRenderer {
49
50    /**
51     * Use the AttributeResolver trait
52     */
53    use AttributeResolver;
54
55    /**
56     * The sanitizer instance used for content sanitization.
57     */
58    private Sanitizer $sanitizer;
59
60    /**
61     * The template parser instance.
62     */
63    private TemplateParser $templateParser;
64
65    /**
66     * The param validator.
67     */
68    protected ParamValidator $paramValidator;
69
70    /**
71     * The param validator callbacks.
72     */
73    protected ParamValidatorCallbacks $paramValidatorCallbacks;
74
75    /**
76     * Constructor to initialize the TabsRenderer with necessary dependencies.
77     *
78     * @since 0.1.0
79     * @param Sanitizer $sanitizer The sanitizer instance used to sanitize text and attributes.
80     * @param TemplateParser $templateParser The template parser instance for rendering Mustache templates.
81     * @param ParamValidator $paramValidator The parameter validator instance for validating component parameters.
82     * @param ParamValidatorCallbacks $paramValidatorCallbacks The callbacks for accessing validated parameter values.
83     */
84    public function __construct(
85        Sanitizer $sanitizer,
86        TemplateParser $templateParser,
87        ParamValidator $paramValidator,
88        ParamValidatorCallbacks $paramValidatorCallbacks
89    ) {
90        $this->sanitizer = $sanitizer;
91        $this->templateParser = $templateParser;
92        $this->paramValidator = $paramValidator;
93        $this->paramValidatorCallbacks = $paramValidatorCallbacks;
94    }
95
96    /**
97     * Renders the HTML for a tabs component.
98     *
99     * Uses the provided Tabs component to generate HTML markup adhering to the Codex design system.
100     *
101     * @since 0.1.0
102     * @param Tabs $component The Tabs object to render.
103     * @return string The rendered HTML string for the component.
104     */
105    public function render( $component ): string {
106        if ( !$component instanceof Tabs ) {
107            throw new InvalidArgumentException( "Expected instance of Tabs, got " . get_class( $component ) );
108        }
109
110        $definitions = ParamDefinitions::getDefinitionsForContext( 'tabs' );
111
112        foreach ( $definitions as $param => $rules ) {
113            try {
114                $this->paramValidator->validateValue(
115                    $param,
116                    $this->paramValidatorCallbacks->getValue(
117                        $param,
118                        $rules[ParamValidator::PARAM_DEFAULT],
119                        []
120                    ),
121                    $rules
122                );
123            } catch ( UnexpectedValueException $e ) {
124                throw new InvalidArgumentException( "Invalid value for parameter '$param': " . $e->getMessage() );
125            }
126        }
127
128        $currentTabName = $this->paramValidatorCallbacks->getValue(
129            'tab',
130            $component->getTabs()[0]->getName(),
131            []
132        );
133
134        $tabsData = [];
135
136        foreach ( $component->getTabs() as $tab ) {
137            if ( !$tab instanceof Tab ) {
138                throw new InvalidArgumentException( "All tabs must be instances of Tab Component" );
139            }
140
141            $isSelected = $tab->getName() === $currentTabName;
142            $isHidden = !$isSelected;
143
144            $tabsData[] = [
145                'id' => $this->sanitizer->sanitizeText( $tab->getId() ),
146                'name' => $this->sanitizer->sanitizeText( $tab->getName() ),
147                'label' => $this->sanitizer->sanitizeText( $tab->getLabel() ),
148                'content-html' => $tab->getContent(),
149                'isSelected' => $isSelected,
150                'isHidden' => $isHidden,
151                'disabled' => $tab->isDisabled(),
152            ];
153        }
154
155        $data = [
156            'id' => $this->sanitizer->sanitizeText( $component->getId() ),
157            'tabs' => $tabsData,
158            'attributes' => $this->resolve(
159                $this->sanitizer->sanitizeAttributes( $component->getAttributes() )
160            ),
161        ];
162
163        return $this->templateParser->processTemplate( 'tabs', $data );
164    }
165}