MediaWiki master
HTMLSelectAndOtherField.php
Go to the documentation of this file.
1<?php
2
4
5use HTMLTextField;
6use InvalidArgumentException;
10
24 private const FIELD_CLASS = 'mw-htmlform-select-and-other-field';
26 private $mFlatOptions;
27
32 public function __construct( $params ) {
33 if ( array_key_exists( 'other', $params ) ) {
34 // Do nothing
35 } elseif ( array_key_exists( 'other-message', $params ) ) {
36 $params['other'] = $this->getMessage( $params['other-message'] )->plain();
37 } else {
38 $params['other'] = $this->msg( 'htmlform-selectorother-other' )->plain();
39 }
40
41 parent::__construct( $params );
42
43 if ( $this->getOptions() === null ) {
44 throw new InvalidArgumentException( 'HTMLSelectAndOtherField called without any options' );
45 }
46 if ( !in_array( 'other', $this->mOptions, true ) ) {
47 // Have 'other' always as first element
48 $this->mOptions = [ $params['other'] => 'other' ] + $this->mOptions;
49 }
50 $this->mFlatOptions = self::flattenOptions( $this->getOptions() );
51 }
52
53 public function getInputHTML( $value ) {
54 $select = parent::getInputHTML( $value[1] );
55
56 $textAttribs = [
57 'size' => $this->getSize(),
58 ];
59
60 if ( isset( $this->mParams['maxlength-unit'] ) ) {
61 $textAttribs['data-mw-maxlength-unit'] = $this->mParams['maxlength-unit'];
62 }
63
64 $allowedParams = [
65 'required',
66 'autofocus',
67 'multiple',
68 'disabled',
69 'tabindex',
70 'maxlength', // gets dynamic with javascript, see mediawiki.htmlform.js
71 'maxlength-unit', // 'bytes' or 'codepoints', see mediawiki.htmlform.js
72 ];
73
74 $textAttribs += $this->getAttributes( $allowedParams );
75
76 $textbox = Html::input( $this->mName . '-other', $value[2], 'text', $textAttribs );
77
78 $wrapperAttribs = [
79 'id' => $this->mID,
80 'class' => self::FIELD_CLASS
81 ];
82 if ( $this->mClass !== '' ) {
83 $wrapperAttribs['class'] .= ' ' . $this->mClass;
84 }
85 return Html::rawElement(
86 'div',
87 $wrapperAttribs,
88 "$select<br />\n$textbox"
89 );
90 }
91
92 protected function getOOUIModules() {
93 return [ 'mediawiki.widgets.SelectWithInputWidget' ];
94 }
95
96 public function getInputOOUI( $value ) {
97 $this->mParent->getOutput()->addModuleStyles( 'mediawiki.widgets.SelectWithInputWidget.styles' );
98
99 # TextInput
100 $textAttribs = [
101 'name' => $this->mName . '-other',
102 'value' => $value[2],
103 ];
104
105 $allowedParams = [
106 'required',
107 'autofocus',
108 'multiple',
109 'disabled',
110 'tabindex',
111 'maxlength',
112 ];
113
114 $textAttribs += \OOUI\Element::configFromHtmlAttributes(
115 $this->getAttributes( $allowedParams )
116 );
117
118 # DropdownInput
119 $dropdownInputAttribs = [
120 'name' => $this->mName,
121 'options' => $this->getOptionsOOUI(),
122 'value' => $value[1],
123 ];
124
125 $allowedParams = [
126 'tabindex',
127 'disabled',
128 ];
129
130 $dropdownInputAttribs += \OOUI\Element::configFromHtmlAttributes(
131 $this->getAttributes( $allowedParams )
132 );
133
134 $disabled = false;
135 if ( isset( $this->mParams[ 'disabled' ] ) && $this->mParams[ 'disabled' ] ) {
136 $disabled = true;
137 }
138
139 $inputClasses = [ self::FIELD_CLASS ];
140 if ( $this->mClass !== '' ) {
141 $inputClasses = array_merge( $inputClasses, explode( ' ', $this->mClass ) );
142 }
143 return $this->getInputWidget( [
144 'id' => $this->mID,
145 'disabled' => $disabled,
146 'textinput' => $textAttribs,
147 'dropdowninput' => $dropdownInputAttribs,
148 'or' => false,
149 'required' => $this->mParams[ 'required' ] ?? false,
150 'classes' => $inputClasses,
151 'data' => [
152 'maxlengthUnit' => $this->mParams['maxlength-unit'] ?? 'bytes'
153 ],
154 ] );
155 }
156
162 public function getInputWidget( $params ) {
163 return new SelectWithInputWidget( $params );
164 }
165
166 public function getInputCodex( $value, $hasErrors ) {
167 $select = parent::getInputCodex( $value[1], $hasErrors );
168
169 // Set up attributes for the text input.
170 $textInputAttribs = [
171 'size' => $this->getSize(),
172 'name' => $this->mName . '-other'
173 ];
174
175 if ( isset( $this->mParams['maxlength-unit'] ) ) {
176 $textInputAttribs['data-mw-maxlength-unit'] = $this->mParams['maxlength-unit'];
177 }
178
179 $allowedParams = [
180 'required',
181 'autofocus',
182 'multiple',
183 'disabled',
184 'tabindex',
185 'maxlength', // gets dynamic with javascript, see mediawiki.htmlform.js
186 'maxlength-unit', // 'bytes' or 'codepoints', see mediawiki.htmlform.js
187 ];
188
189 $textInputAttribs += $this->getAttributes( $allowedParams );
190
191 // Get text input HTML.
193 $value[2],
194 $hasErrors,
195 'text',
196 $this->mName . '-other',
197 $textInputAttribs
198 );
199
200 // Set up the wrapper element and return the entire component.
201 $wrapperAttribs = [
202 'id' => $this->mID,
203 'class' => [ self::FIELD_CLASS ]
204 ];
205 if ( $this->mClass !== '' ) {
206 $wrapperAttribs['class'][] = $this->mClass;
207 }
208 return Html::rawElement(
209 'div',
210 $wrapperAttribs,
211 "$select<br />\n$textInput"
212 );
213 }
214
218 public function getDefault() {
219 $default = parent::getDefault();
220
221 // Default values of empty form
222 $final = '';
223 $list = 'other';
224 $text = '';
225
226 if ( $default !== null ) {
227 $final = $default;
228 // Assume the default is a text value, with the 'other' option selected.
229 // Then check if that assumption is correct, and update $list and $text if not.
230 $text = $final;
231 foreach ( $this->mFlatOptions as $option ) {
232 $match = $option . $this->msg( 'colon-separator' )->inContentLanguage()->text();
233 if ( str_starts_with( $final, $match ) ) {
234 $list = $option;
235 $text = substr( $final, strlen( $match ) );
236 break;
237 }
238 }
239 }
240
241 return [ $final, $list, $text ];
242 }
243
249 public function loadDataFromRequest( $request ) {
250 if ( $request->getCheck( $this->mName ) ) {
251 $list = $request->getText( $this->mName );
252 $text = $request->getText( $this->mName . '-other' );
253
254 // Should be built the same as in mediawiki.htmlform.js
255 if ( $list == 'other' ) {
256 $final = $text;
257 } elseif ( !in_array( $list, $this->mFlatOptions, true ) ) {
258 # User has spoofed the select form to give an option which wasn't
259 # in the original offer. Sulk...
260 $final = $text;
261 } elseif ( $text == '' ) {
262 $final = $list;
263 } else {
264 $final = $list . $this->msg( 'colon-separator' )->inContentLanguage()->text() . $text;
265 }
266 return [ $final, $list, $text ];
267 }
268 return $this->getDefault();
269 }
270
271 public function getSize() {
272 return $this->mParams['size'] ?? 45;
273 }
274
275 public function validate( $value, $alldata ) {
276 # HTMLSelectField forces $value to be one of the options in the select
277 # field, which is not useful here. But we do want the validation further up
278 # the chain
279 $p = parent::validate( $value[1], $alldata );
280
281 if ( $p !== true ) {
282 return $p;
283 }
284
285 if ( isset( $this->mParams['required'] )
286 && $this->mParams['required'] !== false
287 && $value[0] === ''
288 ) {
289 return $this->msg( 'htmlform-required' );
290 }
291
292 return true;
293 }
294}
295
297class_alias( HTMLSelectAndOtherField::class, 'HTMLSelectAndOtherField' );
array $params
The job parameters.
Double field with a dropdown list constructed from a system message in the format.
getInputCodex( $value, $hasErrors)
Same as getInputHTML, but for Codex.
getInputHTML( $value)
This function must be implemented to return the HTML to generate the input object itself....
validate( $value, $alldata)
Override this function to add specific validation checks on the field input.Don't forget to call pare...
getOOUIModules()
Get the list of extra ResourceLoader modules which must be loaded client-side before it's possible to...
getInputOOUI( $value)
Same as getInputHTML, but returns an OOUI object.Defaults to false, which getOOUI will interpret as "...
static buildCodexComponent( $value, $hasErrors, $type, $name, $inputAttribs)
Build the markup of the Codex component.
getMessage( $value)
Turns a *-message parameter (which could be a MessageSpecifier, or a message name,...
getOptionsOOUI()
Get options and make them into arrays suitable for OOUI.
static flattenOptions( $options)
flatten an array of options to a single array, for instance, a set of "<options>" inside "<optgroups>...
getOptions()
Fetch the array of options from the field's parameters.
getAttributes(array $list)
Returns the given attributes from the parameters.
msg( $key,... $params)
Get a translated interface message.
This class is a collection of static functions that serve two purposes:
Definition Html.php:56
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...