Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
SelectRenderer
0.00% covered (danger)
0.00%
0 / 36
0.00% covered (danger)
0.00%
0 / 4
90
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 render
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
6
 prepareOptions
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
20
 prepareOptGroups
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2declare( strict_types = 1 );
3
4/**
5 * SelectRenderer.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 `SelectRenderer` 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 Wikimedia\Codex\Component\Select;
25use Wikimedia\Codex\Contract\Component;
26use Wikimedia\Codex\Contract\Renderer;
27use Wikimedia\Codex\Parser\TemplateParser;
28use Wikimedia\Codex\Utility\Sanitizer;
29
30/**
31 * SelectRenderer is responsible for rendering the HTML markup
32 * for a Select component using a Mustache template.
33 *
34 * This class uses the `TemplateParser` and `Sanitizer` utilities to manage
35 * the template rendering process, ensuring that the component object's HTML
36 * output adheres to the Codex design system's standards.
37 *
38 * @category Renderer
39 * @package  Codex\Renderer
40 * @since    0.1.0
41 * @author   Doğu Abaris <abaris@null.net>
42 * @license  https://www.gnu.org/copyleft/gpl.html GPL-2.0-or-later
43 * @link     https://doc.wikimedia.org/codex/main/ Codex Documentation
44 */
45class SelectRenderer extends Renderer {
46
47    /**
48     * The template parser instance.
49     */
50    private TemplateParser $templateParser;
51
52    /**
53     * Constructor to initialize the SelectRenderer with a sanitizer and a template parser.
54     *
55     * @since 0.1.0
56     * @param Sanitizer $sanitizer The sanitizer instance used for content sanitization.
57     * @param TemplateParser $templateParser The template parser instance.
58     */
59    public function __construct( Sanitizer $sanitizer, TemplateParser $templateParser ) {
60        parent::__construct( $sanitizer );
61        $this->templateParser = $templateParser;
62    }
63
64    /**
65     * Renders the HTML for a select dropdown component.
66     *
67     * Uses the provided Select component to generate HTML markup adhering to the Codex design system.
68     *
69     * @since 0.1.0
70     * @param Component $component The Select object to render.
71     * @return string The rendered HTML string for the component.
72     */
73    public function render( Component $component ): string {
74        if ( !$component instanceof Select ) {
75            throw new InvalidArgumentException( "Expected instance of Select, got " . get_class( $component ) );
76        }
77
78        $selectData = [
79            'id' => $component->getId(),
80            'isDisabled' => $component->isDisabled(),
81            'selectedOption' => $component->getSelectedOption(),
82            'extraClasses' => $this->getExtraClasses( $component->getAttributes() ),
83            'attributes' => $this->getOtherAttributes( $component->getAttributes() ),
84            'options' => $this->prepareOptions( $component->getOptions() ),
85            'optGroups' => $this->prepareOptGroups( $component->getOptGroups() ),
86        ];
87
88        return $this->templateParser->processTemplate( 'select', $selectData );
89    }
90
91    /**
92     * Prepare options for rendering.
93     *
94     * @since 0.1.0
95     * @param array $options An array of options, like from Select::getOptions()
96     * @return array An array of normalized option data for rendering.
97     */
98    private function prepareOptions( array $options ): array {
99        $newOptions = [];
100        foreach ( $options as $key => $option ) {
101            if ( is_string( $key ) ) {
102                $newOptions[] = [
103                    'value' => $key,
104                    'text' => $option,
105                    'selected' => false,
106                ];
107            } elseif ( is_array( $option ) ) {
108                $newOptions[] = [
109                    'value' => $option['value'],
110                    'text' => $option['text'],
111                    'selected' => $option['selected'] ?? false,
112                ];
113            }
114        }
115
116        return $newOptions;
117    }
118
119    /**
120     * Prepare optGroups for rendering.
121     *
122     * @since 0.1.0
123     * @param array $optGroups Array of option groups, from Select::getOptGroups()
124     * @return array Prepared array of optGroups with their respective options for rendering.
125     */
126    private function prepareOptGroups( array $optGroups ): array {
127        $newOptGroups = [];
128        foreach ( $optGroups as $label => $groupOptions ) {
129            $newOptGroups[] = [
130                'label' => $label,
131                'options' => $this->prepareOptions( $groupOptions ),
132            ];
133        }
134
135        return $newOptGroups;
136    }
137}