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