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