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    /** @var array[] */
32    protected $options = [];
33    /** @var string|array|false */
34    protected $default = false;
35    /** @var string|array */
36    protected $tagName = 'select';
37    /** @var (string|int)[] */
38    protected $attributes = [];
39
40    public function __construct( $name = false, $id = false, $default = false ) {
41        if ( $name ) {
42            $this->setAttribute( 'name', $name );
43        }
44
45        if ( $id ) {
46            $this->setAttribute( 'id', $id );
47        }
48
49        if ( $default !== false ) {
50            $this->default = $default;
51        }
52    }
53
54    /**
55     * @param string|array $default
56     */
57    public function setDefault( $default ) {
58        $this->default = $default;
59    }
60
61    /**
62     * @param string|array $tagName
63     */
64    public function setTagName( $tagName ) {
65        $this->tagName = $tagName;
66    }
67
68    /**
69     * @param string $name
70     * @param string|int $value
71     */
72    public function setAttribute( $name, $value ) {
73        $this->attributes[$name] = $value;
74    }
75
76    /**
77     * @param string $name
78     * @return string|int|null
79     */
80    public function getAttribute( $name ) {
81        return $this->attributes[$name] ?? null;
82    }
83
84    /**
85     * @param string $label
86     * @param string|int|float|false $value If not given, assumed equal to $label
87     */
88    public function addOption( $label, $value = false ) {
89        $value = $value !== false ? $value : $label;
90        $this->options[] = [ $label => $value ];
91    }
92
93    /**
94     * This accepts an array of form
95     * label => value
96     * label => ( label => value, label => value )
97     *
98     * @param array $options
99     */
100    public function addOptions( $options ) {
101        $this->options[] = $options;
102    }
103
104    /**
105     * This accepts an array of form:
106     * label => value
107     * label => ( label => value, label => value )
108     *
109     * @param array $options
110     * @param string|array|false $default
111     * @return string
112     */
113    public static function formatOptions( $options, $default = false ) {
114        $data = '';
115
116        foreach ( $options as $label => $value ) {
117            if ( is_array( $value ) ) {
118                $contents = self::formatOptions( $value, $default );
119                $data .= Html::rawElement( 'optgroup', [ 'label' => $label ], $contents ) . "\n";
120            } else {
121                // If $default is an array, then the <select> probably has the multiple attribute,
122                // so we should check if each $value is in $default, rather than checking if
123                // $value is equal to $default.
124                $selected = is_array( $default ) ? in_array( $value, $default ) : $value === $default;
125                $data .= Xml::option( $label, $value, $selected ) . "\n";
126            }
127        }
128
129        return $data;
130    }
131
132    /**
133     * @return string
134     */
135    public function getHTML() {
136        $contents = '';
137
138        foreach ( $this->options as $options ) {
139            $contents .= self::formatOptions( $options, $this->default );
140        }
141
142        return Html::rawElement( $this->tagName, $this->attributes, rtrim( $contents ) );
143    }
144
145    /**
146     * Parse labels and values out of a comma- and colon-separated list of options, such as is used for
147     * expiry and duration lists. Documentation of the format is on translatewiki.net.
148     * @since 1.35
149     * @link https://translatewiki.net/wiki/Template:Doc-mediawiki-options-list
150     * @param string $msg The message to parse.
151     * @return string[] The options array, where keys are option labels (i.e. translations)
152     * and values are option values (i.e. untranslated).
153     */
154    public static function parseOptionsMessage( string $msg ): array {
155        $options = [];
156        foreach ( explode( ',', $msg ) as $option ) {
157            // Normalize options that only have one part.
158            if ( strpos( $option, ':' ) === false ) {
159                $option = "$option:$option";
160            }
161            // Extract the two parts.
162            [ $label, $value ] = explode( ':', $option );
163            $options[ trim( $label ) ] = trim( $value );
164        }
165        return $options;
166    }
167}
168/** @deprecated class alias since 1.43 */
169class_alias( XmlSelect::class, 'XmlSelect' );