Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
63.64% covered (warning)
63.64%
21 / 33
60.00% covered (warning)
60.00%
6 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
XmlSelect
65.62% covered (warning)
65.62%
21 / 32
60.00% covered (warning)
60.00%
6 / 10
36.25
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 setDefault
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setTagName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 setAttribute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAttribute
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addOption
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 addOptions
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 formatOptions
75.00% covered (warning)
75.00%
6 / 8
0.00% covered (danger)
0.00%
0 / 1
4.25
 getHTML
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 parseOptionsMessage
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
1<?php
2/**
3 * Class for generating HTML <select> elements.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 */
22
23namespace MediaWiki\Xml;
24
25use MediaWiki\Html\Html;
26
27/**
28 * Class for generating HTML <select> or <datalist> elements.
29 */
30class XmlSelect {
31    protected $options = [];
32    protected $default = false;
33    protected $tagName = 'select';
34    protected $attributes = [];
35
36    public function __construct( $name = false, $id = false, $default = false ) {
37        if ( $name ) {
38            $this->setAttribute( 'name', $name );
39        }
40
41        if ( $id ) {
42            $this->setAttribute( 'id', $id );
43        }
44
45        if ( $default !== false ) {
46            $this->default = $default;
47        }
48    }
49
50    /**
51     * @param string|array $default
52     */
53    public function setDefault( $default ) {
54        $this->default = $default;
55    }
56
57    /**
58     * @param string|array $tagName
59     */
60    public function setTagName( $tagName ) {
61        $this->tagName = $tagName;
62    }
63
64    /**
65     * @param string $name
66     * @param string|int $value
67     */
68    public function setAttribute( $name, $value ) {
69        $this->attributes[$name] = $value;
70    }
71
72    /**
73     * @param string $name
74     * @return string|int|null
75     */
76    public function getAttribute( $name ) {
77        return $this->attributes[$name] ?? null;
78    }
79
80    /**
81     * @param string $label
82     * @param string|int|float|false $value If not given, assumed equal to $label
83     */
84    public function addOption( $label, $value = false ) {
85        $value = $value !== false ? $value : $label;
86        $this->options[] = [ $label => $value ];
87    }
88
89    /**
90     * This accepts an array of form
91     * label => value
92     * label => ( label => value, label => value )
93     *
94     * @param array $options
95     */
96    public function addOptions( $options ) {
97        $this->options[] = $options;
98    }
99
100    /**
101     * This accepts an array of form:
102     * label => value
103     * label => ( label => value, label => value )
104     *
105     * @param array $options
106     * @param string|array|false $default
107     * @return string
108     */
109    public static function formatOptions( $options, $default = false ) {
110        $data = '';
111
112        foreach ( $options as $label => $value ) {
113            if ( is_array( $value ) ) {
114                $contents = self::formatOptions( $value, $default );
115                $data .= Html::rawElement( 'optgroup', [ 'label' => $label ], $contents ) . "\n";
116            } else {
117                // If $default is an array, then the <select> probably has the multiple attribute,
118                // so we should check if each $value is in $default, rather than checking if
119                // $value is equal to $default.
120                $selected = is_array( $default ) ? in_array( $value, $default ) : $value === $default;
121                $data .= Xml::option( $label, $value, $selected ) . "\n";
122            }
123        }
124
125        return $data;
126    }
127
128    /**
129     * @return string
130     */
131    public function getHTML() {
132        $contents = '';
133
134        foreach ( $this->options as $options ) {
135            $contents .= self::formatOptions( $options, $this->default );
136        }
137
138        return Html::rawElement( $this->tagName, $this->attributes, rtrim( $contents ) );
139    }
140
141    /**
142     * Parse labels and values out of a comma- and colon-separated list of options, such as is used for
143     * expiry and duration lists. Documentation of the format is on translatewiki.net.
144     * @since 1.35
145     * @link https://translatewiki.net/wiki/Template:Doc-mediawiki-options-list
146     * @param string $msg The message to parse.
147     * @return string[] The options array, where keys are option labels (i.e. translations)
148     * and values are option values (i.e. untranslated).
149     */
150    public static function parseOptionsMessage( string $msg ): array {
151        $options = [];
152        foreach ( explode( ',', $msg ) as $option ) {
153            // Normalize options that only have one part.
154            if ( strpos( $option, ':' ) === false ) {
155                $option = "$option:$option";
156            }
157            // Extract the two parts.
158            [ $label, $value ] = explode( ':', $option );
159            $options[ trim( $label ) ] = trim( $value );
160        }
161        return $options;
162    }
163}
164/** @deprecated class alias since 1.43 */
165class_alias( XmlSelect::class, 'XmlSelect' );