Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
65.31% |
160 / 245 |
|
41.67% |
15 / 36 |
CRAP | |
0.00% |
0 / 1 |
Xml | |
65.57% |
160 / 244 |
|
41.67% |
15 / 36 |
412.18 | |
0.00% |
0 / 1 |
element | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
5 | |||
expandAttributes | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 | |||
elementClean | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
12 | |||
openElement | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
closeElement | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
tags | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
monthSelector | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
3 | |||
dateMenu | |
100.00% |
19 / 19 |
|
100.00% |
1 / 1 |
6 | |||
languageSelector | |
90.48% |
19 / 21 |
|
0.00% |
0 / 1 |
5.02 | |||
span | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
wrapClass | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
input | |
83.33% |
5 / 6 |
|
0.00% |
0 / 1 |
3.04 | |||
password | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
attrib | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
6 | |||
check | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
2 | |||
radio | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
label | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
inputLabel | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
inputLabelSep | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
checkLabel | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
radioLabel | |
0.00% |
0 / 3 |
|
0.00% |
0 / 1 |
2 | |||
submitButton | |
0.00% |
0 / 5 |
|
0.00% |
0 / 1 |
2 | |||
option | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
listDropdown | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
3 | |||
listDropdownOptions | |
86.36% |
19 / 22 |
|
0.00% |
0 / 1 |
11.31 | |||
listDropdownOptionsOoui | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
fieldset | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
3 | |||
textarea | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
1 | |||
encodeJsVar | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
encodeJsCall | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
isWellFormed | |
0.00% |
0 / 7 |
|
0.00% |
0 / 1 |
6 | |||
isWellFormedXmlFragment | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
2 | |||
escapeTagsOnly | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
1 | |||
buildForm | |
0.00% |
0 / 18 |
|
0.00% |
0 / 1 |
12 | |||
buildTable | |
88.24% |
15 / 17 |
|
0.00% |
0 / 1 |
6.06 | |||
buildTableRow | |
88.89% |
8 / 9 |
|
0.00% |
0 / 1 |
3.01 |
1 | <?php |
2 | /** |
3 | * Methods to generate XML. |
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 | namespace MediaWiki\Xml; |
24 | |
25 | use MediaWiki\Html\Html; |
26 | use MediaWiki\Languages\LanguageNameUtils; |
27 | use MediaWiki\MainConfigNames; |
28 | use MediaWiki\MediaWikiServices; |
29 | use MediaWiki\Message\Message; |
30 | use MediaWiki\Parser\Sanitizer; |
31 | use MediaWiki\Utils\MWTimestamp; |
32 | use UtfNormal\Validator; |
33 | |
34 | /** |
35 | * Module of static functions for generating XML |
36 | */ |
37 | class Xml { |
38 | /** |
39 | * Format an XML element with given attributes and, optionally, text content. |
40 | * Element and attribute names are assumed to be ready for literal inclusion. |
41 | * Strings are assumed to not contain XML-illegal characters; special |
42 | * characters (<, >, &) are escaped but illegals are not touched. |
43 | * |
44 | * @param string $element Element name |
45 | * @param-taint $element tainted |
46 | * @param array|null $attribs Name=>value pairs. Values will be escaped. |
47 | * @param-taint $attribs escapes_html |
48 | * @param string|null $contents Null to make an open tag only; '' for a contentless closed tag (default) |
49 | * @param-taint $contents escapes_html |
50 | * @param bool $allowShortTag Whether '' in $contents will result in a contentless closed tag |
51 | * @return string |
52 | * @return-taint escaped |
53 | */ |
54 | public static function element( $element, $attribs = null, $contents = '', |
55 | $allowShortTag = true |
56 | ) { |
57 | $out = '<' . $element; |
58 | if ( $attribs !== null ) { |
59 | $out .= self::expandAttributes( $attribs ); |
60 | } |
61 | if ( $contents === null ) { |
62 | $out .= '>'; |
63 | } elseif ( $allowShortTag && $contents === '' ) { |
64 | $out .= ' />'; |
65 | } else { |
66 | $out .= '>' . htmlspecialchars( $contents, ENT_NOQUOTES ) . "</$element>"; |
67 | } |
68 | return $out; |
69 | } |
70 | |
71 | /** |
72 | * Given an array of ('attributename' => 'value'), it generates the code |
73 | * to set the XML attributes : attributename="value". |
74 | * The values are passed to Sanitizer::encodeAttribute. |
75 | * Returns null or empty string if no attributes given. |
76 | * @param array|null $attribs Array of attributes for an XML element |
77 | * @return null|string |
78 | */ |
79 | public static function expandAttributes( ?array $attribs ) { |
80 | if ( $attribs === null ) { |
81 | return null; |
82 | } |
83 | $out = ''; |
84 | foreach ( $attribs as $name => $val ) { |
85 | $out .= " {$name}=\"" . Sanitizer::encodeAttribute( $val ) . '"'; |
86 | } |
87 | return $out; |
88 | } |
89 | |
90 | /** |
91 | * Format an XML element as with self::element(), but run text through the content language's |
92 | * normalize() validator first to ensure that no invalid UTF-8 is passed. |
93 | * |
94 | * @param string $element |
95 | * @param array|null $attribs Name=>value pairs. Values will be escaped. |
96 | * @param string|null $contents Null to make an open tag only; '' for a contentless closed tag (default) |
97 | * @return string |
98 | * @param-taint $attribs escapes_html |
99 | * @param-taint $contents escapes_html |
100 | */ |
101 | public static function elementClean( $element, $attribs = [], $contents = '' ) { |
102 | if ( $attribs ) { |
103 | $attribs = array_map( [ Validator::class, 'cleanUp' ], $attribs ); |
104 | } |
105 | if ( $contents ) { |
106 | $contents = |
107 | MediaWikiServices::getInstance()->getContentLanguage()->normalize( $contents ); |
108 | } |
109 | return self::element( $element, $attribs, $contents ); |
110 | } |
111 | |
112 | /** |
113 | * This opens an XML element |
114 | * |
115 | * @param string $element Name of the element |
116 | * @param array|null $attribs Array of attributes, see Xml::expandAttributes() |
117 | * @return string |
118 | */ |
119 | public static function openElement( $element, $attribs = null ) { |
120 | return '<' . $element . self::expandAttributes( $attribs ) . '>'; |
121 | } |
122 | |
123 | /** |
124 | * Shortcut to close an XML element |
125 | * @param string $element Element name |
126 | * @return string |
127 | */ |
128 | public static function closeElement( $element ) { |
129 | return "</$element>"; |
130 | } |
131 | |
132 | /** |
133 | * Same as Xml::element(), but does not escape contents. Handy when the |
134 | * content you have is already valid xml. |
135 | * |
136 | * @param string $element Element name |
137 | * @param-taint $element tainted |
138 | * @param array|null $attribs Array of attributes |
139 | * @param-taint $attribs escapes_html |
140 | * @param string $contents Content of the element |
141 | * @param-taint $contents tainted |
142 | * @return string |
143 | * @return-taint escaped |
144 | */ |
145 | public static function tags( $element, $attribs, $contents ) { |
146 | return self::openElement( $element, $attribs ) . $contents . "</$element>"; |
147 | } |
148 | |
149 | /** |
150 | * Create a date selector |
151 | * |
152 | * @param string|null $selected The month which should be selected, default ''. |
153 | * @param string|null $allmonths Value of a special item denoting all month. |
154 | * Null to not include (default). |
155 | * @param string $id Element identifier |
156 | * @return string Html string containing the month selector |
157 | * |
158 | * @deprecated since 1.42 |
159 | */ |
160 | public static function monthSelector( $selected = '', $allmonths = null, $id = 'month' ) { |
161 | wfDeprecated( __METHOD__, '1.42' ); |
162 | |
163 | global $wgLang; |
164 | $options = []; |
165 | |
166 | $data = new XmlSelect( 'month', $id, $selected ?? '' ); |
167 | |
168 | if ( $allmonths !== null ) { |
169 | $options[wfMessage( 'monthsall' )->text()] = $allmonths; |
170 | } |
171 | for ( $i = 1; $i < 13; $i++ ) { |
172 | $options[$wgLang->getMonthName( $i )] = $i; |
173 | } |
174 | $data->addOptions( $options ); |
175 | $data->setAttribute( 'class', 'mw-month-selector' ); |
176 | return $data->getHTML(); |
177 | } |
178 | |
179 | /** |
180 | * @param int|string $year Use '' or 0 to start with no year preselected. |
181 | * @param int|string $month A month in the 1..12 range. Use '', 0 or -1 to start with no month |
182 | * preselected. |
183 | * @return string Formatted HTML |
184 | * |
185 | * @deprecated since 1.42 |
186 | */ |
187 | public static function dateMenu( $year, $month ) { |
188 | wfDeprecated( __METHOD__, '1.42' ); |
189 | # Offset overrides year/month selection |
190 | if ( $month && $month !== -1 ) { |
191 | $encMonth = intval( $month ); |
192 | } else { |
193 | $encMonth = ''; |
194 | } |
195 | if ( $year ) { |
196 | $encYear = intval( $year ); |
197 | } elseif ( $encMonth ) { |
198 | $timestamp = MWTimestamp::getInstance(); |
199 | $thisMonth = intval( $timestamp->format( 'n' ) ); |
200 | $thisYear = intval( $timestamp->format( 'Y' ) ); |
201 | if ( $encMonth > $thisMonth ) { |
202 | $thisYear--; |
203 | } |
204 | $encYear = $thisYear; |
205 | } else { |
206 | $encYear = ''; |
207 | } |
208 | $inputAttribs = [ 'id' => 'year', 'maxlength' => 4, 'size' => 7 ]; |
209 | return self::label( wfMessage( 'year' )->text(), 'year' ) . ' ' . |
210 | Html::input( 'year', $encYear, 'number', $inputAttribs ) . ' ' . |
211 | self::label( wfMessage( 'month' )->text(), 'month' ) . ' ' . |
212 | self::monthSelector( $encMonth, '-1' ); |
213 | } |
214 | |
215 | /** |
216 | * Construct a language selector appropriate for use in a form or preferences |
217 | * |
218 | * @param string $selected The language code of the selected language |
219 | * @param bool $customisedOnly If true only languages which have some content are listed |
220 | * @param string|null $inLanguage The ISO code of the language to display the select list in |
221 | * @param array $overrideAttrs Override the attributes of the select tag (since 1.20) |
222 | * @param Message|null $msg Label message key (since 1.20) |
223 | * @return array Array containing 2 items: label HTML and select list HTML |
224 | * |
225 | * @deprecated since 1.42 |
226 | */ |
227 | public static function languageSelector( $selected, $customisedOnly = true, |
228 | $inLanguage = null, $overrideAttrs = [], ?Message $msg = null |
229 | ) { |
230 | wfDeprecated( __METHOD__, '1.42' ); |
231 | $languageCode = MediaWikiServices::getInstance()->getMainConfig() |
232 | ->get( MainConfigNames::LanguageCode ); |
233 | |
234 | $include = $customisedOnly ? LanguageNameUtils::SUPPORTED : LanguageNameUtils::DEFINED; |
235 | $languages = MediaWikiServices::getInstance() |
236 | ->getLanguageNameUtils() |
237 | ->getLanguageNames( $inLanguage, $include ); |
238 | |
239 | // Make sure the site language is in the list; |
240 | // a custom language code might not have a defined name... |
241 | if ( !array_key_exists( $languageCode, $languages ) ) { |
242 | $languages[$languageCode] = $languageCode; |
243 | // Sort the array again |
244 | ksort( $languages ); |
245 | } |
246 | |
247 | /** |
248 | * If a bogus value is set, default to the content language. |
249 | * Otherwise, no default is selected and the user ends up |
250 | * with Afrikaans since it's first in the list. |
251 | */ |
252 | $selected = isset( $languages[$selected] ) ? $selected : $languageCode; |
253 | $options = "\n"; |
254 | foreach ( $languages as $code => $name ) { |
255 | $options .= self::option( "$code - $name", $code, $code == $selected ) . "\n"; |
256 | } |
257 | |
258 | $attrs = [ 'id' => 'wpUserLanguage', 'name' => 'wpUserLanguage' ]; |
259 | $attrs = array_merge( $attrs, $overrideAttrs ); |
260 | |
261 | $msg ??= wfMessage( 'yourlanguage' ); |
262 | return [ |
263 | self::label( $msg->text(), $attrs['id'] ), |
264 | self::tags( 'select', $attrs, $options ) |
265 | ]; |
266 | } |
267 | |
268 | /** |
269 | * Shortcut to make a span element |
270 | * @param string $text Content of the element, will be escaped |
271 | * @param string $class Class name of the span element |
272 | * @param array $attribs Other attributes |
273 | * @return string |
274 | * |
275 | * @deprecated since 1.42, use {@see Html::element} instead; emiting deprecation warnings since 1.44 |
276 | */ |
277 | public static function span( $text, $class, $attribs = [] ) { |
278 | wfDeprecated( __METHOD__, '1.42' ); |
279 | |
280 | return self::element( 'span', [ 'class' => $class ] + $attribs, $text ); |
281 | } |
282 | |
283 | /** |
284 | * Shortcut to make a specific element with a class attribute |
285 | * |
286 | * @param string $text Content of the element, will be escaped |
287 | * @param string $class Class name of the span element |
288 | * @param string $tag Element name |
289 | * @param array $attribs Other attributes |
290 | * @return string |
291 | * |
292 | * @deprecated since 1.42, use {@see Xml::tags} instead |
293 | */ |
294 | public static function wrapClass( $text, $class, $tag = 'span', $attribs = [] ) { |
295 | wfDeprecated( __METHOD__, '1.42' ); |
296 | return self::tags( $tag, [ 'class' => $class ] + $attribs, $text ); |
297 | } |
298 | |
299 | /** |
300 | * Convenience function to build an HTML text input field |
301 | * @param string $name Value of the name attribute |
302 | * @param int|false $size Value of the size attribute |
303 | * @param string|false $value Value of the value attribute |
304 | * @param array $attribs Other attributes |
305 | * @return string HTML |
306 | * |
307 | * @deprecated since 1.42, use {@see Html::input} instead |
308 | */ |
309 | public static function input( $name, $size = false, $value = false, $attribs = [] ) { |
310 | $attributes = [ 'name' => $name ]; |
311 | |
312 | if ( $size ) { |
313 | $attributes['size'] = $size; |
314 | } |
315 | |
316 | if ( $value !== false ) { // maybe 0 |
317 | $attributes['value'] = $value; |
318 | } |
319 | |
320 | return self::element( 'input', $attributes + $attribs ); |
321 | } |
322 | |
323 | /** |
324 | * Convenience function to build an HTML password input field |
325 | * @param string $name Value of the name attribute |
326 | * @param int|false $size Value of the size attribute |
327 | * @param string|false $value Value of the value attribute |
328 | * @param array $attribs Other attributes |
329 | * @return string HTML |
330 | * |
331 | * @deprecated since 1.42, use {@see Html::input} instead; emiting deprecation warnings since 1.44 |
332 | */ |
333 | public static function password( $name, $size = false, $value = false, |
334 | $attribs = [] |
335 | ) { |
336 | wfDeprecated( __METHOD__, '1.42' ); |
337 | |
338 | return self::input( $name, $size, $value, |
339 | array_merge( $attribs, [ 'type' => 'password' ] ) ); |
340 | } |
341 | |
342 | /** |
343 | * Internal function for use in checkboxes and radio buttons and such. |
344 | * |
345 | * @param string $name |
346 | * @param bool $present |
347 | * |
348 | * @return array |
349 | * |
350 | * @deprecated since 1.42; only for use in methods being deprecated |
351 | */ |
352 | public static function attrib( $name, $present = true ) { |
353 | return $present ? [ $name => $name ] : []; |
354 | } |
355 | |
356 | /** |
357 | * Convenience function to build an HTML checkbox |
358 | * @param string $name Value of the name attribute |
359 | * @param bool $checked Whether the checkbox is checked or not |
360 | * @param array $attribs Array other attributes |
361 | * @return string HTML |
362 | * |
363 | * @deprecated since 1.42, use {@see Html::check} instead |
364 | */ |
365 | public static function check( $name, $checked = false, $attribs = [] ) { |
366 | return self::element( 'input', array_merge( |
367 | [ |
368 | 'name' => $name, |
369 | 'type' => 'checkbox', |
370 | 'value' => 1 ], |
371 | self::attrib( 'checked', $checked ), |
372 | $attribs ) ); |
373 | } |
374 | |
375 | /** |
376 | * Convenience function to build an HTML radio button |
377 | * @param string $name Value of the name attribute |
378 | * @param string $value Value of the value attribute |
379 | * @param bool $checked Whether the checkbox is checked or not |
380 | * @param array $attribs Other attributes |
381 | * @return string HTML |
382 | * |
383 | * @deprecated since 1.42, use {@see Html::radio} instead |
384 | */ |
385 | public static function radio( $name, $value, $checked = false, $attribs = [] ) { |
386 | return self::element( 'input', [ |
387 | 'name' => $name, |
388 | 'type' => 'radio', |
389 | 'value' => $value ] + self::attrib( 'checked', $checked ) + $attribs ); |
390 | } |
391 | |
392 | /** |
393 | * Convenience function to build an HTML form label |
394 | * @param string $label Text of the label |
395 | * @param string $id |
396 | * @param array $attribs An attribute array. This will usually be |
397 | * the same array as is passed to the corresponding input element, |
398 | * so this function will cherry-pick appropriate attributes to |
399 | * apply to the label as well; only class and title are applied. |
400 | * @return string HTML |
401 | * |
402 | * @deprecated since 1.42, use {@see Html::label} instead |
403 | */ |
404 | public static function label( $label, $id, $attribs = [] ) { |
405 | $a = [ 'for' => $id ]; |
406 | |
407 | foreach ( [ 'class', 'title' ] as $attr ) { |
408 | if ( isset( $attribs[$attr] ) ) { |
409 | $a[$attr] = $attribs[$attr]; |
410 | } |
411 | } |
412 | |
413 | return self::element( 'label', $a, $label ); |
414 | } |
415 | |
416 | /** |
417 | * Convenience function to build an HTML text input field with a label |
418 | * @param string $label Text of the label |
419 | * @param string $name Value of the name attribute |
420 | * @param string $id Id of the input |
421 | * @param int|false $size Value of the size attribute |
422 | * @param string|false $value Value of the value attribute |
423 | * @param array $attribs Other attributes |
424 | * @return string HTML |
425 | * |
426 | * @deprecated since 1.42, use {@see Html::input} and {@see Html::label} instead |
427 | */ |
428 | public static function inputLabel( $label, $name, $id, $size = false, |
429 | $value = false, $attribs = [] |
430 | ) { |
431 | [ $label, $input ] = self::inputLabelSep( $label, $name, $id, $size, $value, $attribs ); |
432 | return $label . "\u{00A0}" . $input; |
433 | } |
434 | |
435 | /** |
436 | * Same as Xml::inputLabel() but return input and label in an array |
437 | * |
438 | * @param string $label |
439 | * @param string $name |
440 | * @param string $id |
441 | * @param int|false $size |
442 | * @param string|false $value |
443 | * @param array $attribs |
444 | * @return array |
445 | * |
446 | * @deprecated since 1.42, use {@see Html::input} and {@see Html::label} instead |
447 | */ |
448 | public static function inputLabelSep( $label, $name, $id, $size = false, |
449 | $value = false, $attribs = [] |
450 | ) { |
451 | return [ |
452 | self::label( $label, $id, $attribs ), |
453 | self::input( $name, $size, $value, [ 'id' => $id ] + $attribs ) |
454 | ]; |
455 | } |
456 | |
457 | /** |
458 | * Convenience function to build an HTML checkbox with a label |
459 | * |
460 | * @param string $label |
461 | * @param string $name |
462 | * @param string $id |
463 | * @param bool $checked |
464 | * @param array $attribs |
465 | * @return string HTML |
466 | * |
467 | * @deprecated since 1.42, use {@see Html::check} and {@see Html::label} instead |
468 | */ |
469 | public static function checkLabel( $label, $name, $id, $checked = false, $attribs = [] ) { |
470 | return self::check( $name, $checked, [ 'id' => $id ] + $attribs ) . |
471 | "\u{00A0}" . |
472 | self::label( $label, $id, $attribs ); |
473 | } |
474 | |
475 | /** |
476 | * Convenience function to build an HTML radio button with a label |
477 | * |
478 | * @param string $label |
479 | * @param string $name |
480 | * @param string $value |
481 | * @param string $id |
482 | * @param bool $checked |
483 | * @param array $attribs |
484 | * @return string HTML |
485 | * |
486 | * @deprecated since 1.42, use {@see Html::radio} and {@see Html::label} instead |
487 | */ |
488 | public static function radioLabel( $label, $name, $value, $id, |
489 | $checked = false, $attribs = [] |
490 | ) { |
491 | return self::radio( $name, $value, $checked, [ 'id' => $id ] + $attribs ) . |
492 | "\u{00A0}" . |
493 | self::label( $label, $id, $attribs ); |
494 | } |
495 | |
496 | /** |
497 | * Convenience function to build an HTML submit button. |
498 | * |
499 | * @param string $value Label text for the button (unescaped) |
500 | * @param array $attribs Optional custom attributes |
501 | * @return string HTML |
502 | * |
503 | * @deprecated since 1.42, use {@see Html::submitButton} instead |
504 | */ |
505 | public static function submitButton( $value, $attribs = [] ) { |
506 | $attribs += [ |
507 | 'type' => 'submit', |
508 | 'value' => $value, |
509 | ]; |
510 | return Html::element( 'input', $attribs ); |
511 | } |
512 | |
513 | /** |
514 | * Convenience function to build an HTML drop-down list item. |
515 | * @param string $text Text for this item. Will be HTML escaped |
516 | * @param string|null $value Form submission value; if empty, use text |
517 | * @param bool $selected If true, will be the default selected item |
518 | * @param array $attribs Optional additional HTML attributes |
519 | * @return string HTML |
520 | * |
521 | * @deprecated since 1.42, use {@see Html::element} instead |
522 | */ |
523 | public static function option( $text, $value = null, $selected = false, |
524 | $attribs = [] ) { |
525 | if ( $value !== null ) { |
526 | $attribs['value'] = $value; |
527 | } |
528 | if ( $selected ) { |
529 | $attribs['selected'] = 'selected'; |
530 | } |
531 | return Html::element( 'option', $attribs, $text ); |
532 | } |
533 | |
534 | /** |
535 | * Build a drop-down box from a textual list. This is a wrapper |
536 | * for Xml::listDropdownOptions() plus the XmlSelect class. |
537 | * |
538 | * @param string $name Name and id for the drop-down |
539 | * @param string $list Correctly formatted text (newline delimited) to be |
540 | * used to generate the options. |
541 | * @param string $other Text for the "Other reasons" option |
542 | * @param string $selected Option which should be pre-selected |
543 | * @param string $class CSS classes for the drop-down |
544 | * @param int|null $tabindex Value of the tabindex attribute |
545 | * @return string |
546 | * |
547 | * @deprecated since 1.42; use the equivalent methods in Html without a wrapper |
548 | */ |
549 | public static function listDropdown( $name = '', $list = '', $other = '', |
550 | $selected = '', $class = '', $tabindex = null |
551 | ) { |
552 | $options = self::listDropdownOptions( $list, [ 'other' => $other ] ); |
553 | |
554 | $xmlSelect = new XmlSelect( $name, $name, $selected ); |
555 | $xmlSelect->addOptions( $options ); |
556 | |
557 | if ( $class ) { |
558 | $xmlSelect->setAttribute( 'class', $class ); |
559 | } |
560 | if ( $tabindex ) { |
561 | $xmlSelect->setAttribute( 'tabindex', $tabindex ); |
562 | } |
563 | |
564 | return $xmlSelect->getHTML(); |
565 | } |
566 | |
567 | /** |
568 | * Build options for a drop-down box from a textual list. |
569 | * |
570 | * The result of this function can be passed to XmlSelect::addOptions() |
571 | * (to render a plain `<select>` dropdown box) or to Xml::listDropdownOptionsOoui() |
572 | * and then OOUI\DropdownInputWidget() (to render a pretty one). |
573 | * |
574 | * @param string $list Correctly formatted text (newline delimited) to be |
575 | * used to generate the options. |
576 | * @param array $params Extra parameters: |
577 | * - string $params['other'] If set, add an option with this as text and a value of 'other' |
578 | * @return array Array keys are textual labels, values are internal values |
579 | * |
580 | * @deprecated since 1.42; use the equivalent method in Html |
581 | */ |
582 | public static function listDropdownOptions( $list, $params = [] ) { |
583 | $options = []; |
584 | |
585 | if ( isset( $params['other'] ) ) { |
586 | $options[ $params['other'] ] = 'other'; |
587 | } |
588 | |
589 | $optgroup = false; |
590 | foreach ( explode( "\n", $list ) as $option ) { |
591 | $value = trim( $option ); |
592 | if ( $value == '' ) { |
593 | continue; |
594 | } |
595 | if ( substr( $value, 0, 1 ) == '*' && substr( $value, 1, 1 ) != '*' ) { |
596 | # A new group is starting... |
597 | $value = trim( substr( $value, 1 ) ); |
598 | if ( $value !== '' && |
599 | // Do not use the value for 'other' as option group - T251351 |
600 | ( !isset( $params['other'] ) || $value !== $params['other'] ) |
601 | ) { |
602 | $optgroup = $value; |
603 | } else { |
604 | $optgroup = false; |
605 | } |
606 | } elseif ( substr( $value, 0, 2 ) == '**' ) { |
607 | # groupmember |
608 | $opt = trim( substr( $value, 2 ) ); |
609 | if ( $optgroup === false ) { |
610 | $options[$opt] = $opt; |
611 | } else { |
612 | $options[$optgroup][$opt] = $opt; |
613 | } |
614 | } else { |
615 | # groupless reason list |
616 | $optgroup = false; |
617 | $options[$option] = $option; |
618 | } |
619 | } |
620 | |
621 | return $options; |
622 | } |
623 | |
624 | /** |
625 | * Convert options for a drop-down box into a format accepted by OOUI\DropdownInputWidget etc. |
626 | * |
627 | * TODO Find a better home for this function. |
628 | * |
629 | * @param array $options Options, as returned e.g. by Xml::listDropdownOptions() |
630 | * @return array |
631 | * |
632 | * @deprecated since 1.42; use the equivalent method in Html |
633 | */ |
634 | public static function listDropdownOptionsOoui( $options ) { |
635 | $optionsOoui = []; |
636 | |
637 | foreach ( $options as $text => $value ) { |
638 | if ( is_array( $value ) ) { |
639 | $optionsOoui[] = [ 'optgroup' => (string)$text ]; |
640 | foreach ( $value as $text2 => $value2 ) { |
641 | $optionsOoui[] = [ 'data' => (string)$value2, 'label' => (string)$text2 ]; |
642 | } |
643 | } else { |
644 | $optionsOoui[] = [ 'data' => (string)$value, 'label' => (string)$text ]; |
645 | } |
646 | } |
647 | |
648 | return $optionsOoui; |
649 | } |
650 | |
651 | /** |
652 | * Shortcut for creating fieldsets. |
653 | * |
654 | * @param string|false $legend Legend of the fieldset. If evaluates to false, |
655 | * legend is not added. |
656 | * @param string|false $content Pre-escaped content for the fieldset. If false, |
657 | * only open fieldset is returned. |
658 | * @param array $attribs Any attributes to fieldset-element. |
659 | * @return string |
660 | * |
661 | * @deprecated since 1.42, use {@see Html::element} instead |
662 | */ |
663 | public static function fieldset( $legend = false, $content = false, $attribs = [] ) { |
664 | $s = self::openElement( 'fieldset', $attribs ) . "\n"; |
665 | |
666 | if ( $legend ) { |
667 | $s .= self::element( 'legend', null, $legend ) . "\n"; |
668 | } |
669 | |
670 | if ( $content !== false ) { |
671 | $s .= $content . "\n"; |
672 | $s .= self::closeElement( 'fieldset' ) . "\n"; |
673 | } |
674 | |
675 | return $s; |
676 | } |
677 | |
678 | /** |
679 | * Shortcut for creating textareas. |
680 | * |
681 | * @param string $name The 'name' for the textarea |
682 | * @param string $content Content for the textarea |
683 | * @param int $cols The number of columns for the textarea |
684 | * @param int $rows The number of rows for the textarea |
685 | * @param array $attribs Any other attributes for the textarea |
686 | * @return string |
687 | * |
688 | * @deprecated since 1.42, use {@see Html::textarea} instead |
689 | */ |
690 | public static function textarea( $name, $content, $cols = 40, $rows = 5, $attribs = [] ) { |
691 | return self::element( 'textarea', |
692 | [ |
693 | 'name' => $name, |
694 | 'id' => $name, |
695 | 'cols' => $cols, |
696 | 'rows' => $rows |
697 | ] + $attribs, |
698 | $content, false ); |
699 | } |
700 | |
701 | /** |
702 | * Encode a variable of arbitrary type to JavaScript. |
703 | * If the value is an HtmlJsCode object, pass through the object's value verbatim. |
704 | * |
705 | * @note Only use this function for generating JavaScript code. If generating output |
706 | * for a proper JSON parser, just call FormatJson::encode() directly. |
707 | * |
708 | * @param mixed $value The value being encoded. Can be any type except a resource. |
709 | * @param-taint $value escapes_html |
710 | * @param bool $pretty If true, add non-significant whitespace to improve readability. |
711 | * @return string|false String if successful; false upon failure |
712 | * @return-taint none |
713 | * |
714 | * @deprecated since 1.41, use {@see Html::encodeJsVar} instead; emiting deprecation warnings since 1.44 |
715 | */ |
716 | public static function encodeJsVar( $value, $pretty = false ) { |
717 | wfDeprecated( __METHOD__, '1.41' ); |
718 | |
719 | return Html::encodeJsVar( $value, $pretty ); |
720 | } |
721 | |
722 | /** |
723 | * Create a call to a JavaScript function. The supplied arguments will be |
724 | * encoded using Xml::encodeJsVar(). |
725 | * |
726 | * @since 1.17 |
727 | * @param string $name The name of the function to call, or a JavaScript expression |
728 | * which evaluates to a function object which is called. |
729 | * @param-taint $name tainted |
730 | * @param array $args The arguments to pass to the function. |
731 | * @param-taint $args escapes_html |
732 | * @param bool $pretty If true, add non-significant whitespace to improve readability. |
733 | * @return string|false String if successful; false upon failure |
734 | * @return-taint none |
735 | * |
736 | * @deprecated since 1.41, use {@see Html::encodeJsCall} instead; emiting deprecation warnings since 1.44 |
737 | */ |
738 | public static function encodeJsCall( $name, $args, $pretty = false ) { |
739 | wfDeprecated( __METHOD__, '1.41' ); |
740 | |
741 | return Html::encodeJsCall( $name, $args, $pretty ); |
742 | } |
743 | |
744 | /** |
745 | * Check if a string is well-formed XML. |
746 | * Must include the surrounding tag. |
747 | * This function is a DoS vector if an attacker can define |
748 | * entities in $text. |
749 | * |
750 | * @param string $text String to test. |
751 | * @return bool |
752 | * |
753 | * @todo Error position reporting return |
754 | */ |
755 | private static function isWellFormed( $text ) { |
756 | $parser = xml_parser_create( "UTF-8" ); |
757 | |
758 | # case folding violates XML standard, turn it off |
759 | xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 ); |
760 | |
761 | if ( !xml_parse( $parser, $text, true ) ) { |
762 | // $err = xml_error_string( xml_get_error_code( $parser ) ); |
763 | // $position = xml_get_current_byte_index( $parser ); |
764 | // $fragment = $this->extractFragment( $html, $position ); |
765 | // $this->mXmlError = "$err at byte $position:\n$fragment"; |
766 | xml_parser_free( $parser ); |
767 | return false; |
768 | } |
769 | |
770 | xml_parser_free( $parser ); |
771 | |
772 | return true; |
773 | } |
774 | |
775 | /** |
776 | * Check if a string is a well-formed XML fragment. |
777 | * Wraps fragment in an \<html\> bit and doctype, so it can be a fragment |
778 | * and can use HTML named entities. |
779 | * |
780 | * @param string $text |
781 | * @return bool |
782 | */ |
783 | public static function isWellFormedXmlFragment( $text ) { |
784 | $html = |
785 | Sanitizer::hackDocType() . |
786 | '<html>' . |
787 | $text . |
788 | '</html>'; |
789 | |
790 | return self::isWellFormed( $html ); |
791 | } |
792 | |
793 | /** |
794 | * Replace " > and < with their respective HTML entities ( ", |
795 | * >, <) |
796 | * |
797 | * @param string $in Text that might contain HTML tags. |
798 | * @return string Escaped string |
799 | */ |
800 | public static function escapeTagsOnly( $in ) { |
801 | return str_replace( |
802 | [ '"', '>', '<' ], |
803 | [ '"', '>', '<' ], |
804 | $in ); |
805 | } |
806 | |
807 | /** |
808 | * Generate a form (without the opening form element). |
809 | * Output optionally includes a submit button. |
810 | * @param array $fields Associative array, key is the name of a message that |
811 | * contains a description for the field, value is an HTML string |
812 | * containing the appropriate input. |
813 | * @param string|null $submitLabel The name of a message containing a label for |
814 | * the submit button. |
815 | * @param array $submitAttribs The attributes to add to the submit button |
816 | * @return string HTML form. |
817 | * |
818 | * @deprecated since 1.42, use OOUI or Codex widgets instead |
819 | */ |
820 | public static function buildForm( $fields, $submitLabel = null, $submitAttribs = [] ) { |
821 | $form = ''; |
822 | $form .= "<table><tbody>"; |
823 | |
824 | foreach ( $fields as $labelmsg => $input ) { |
825 | $id = "mw-$labelmsg"; |
826 | $form .= self::openElement( 'tr', [ 'id' => $id ] ); |
827 | |
828 | // TODO use a <label> here for accessibility purposes - will need |
829 | // to either not use a table to build the form, or find the ID of |
830 | // the input somehow. |
831 | |
832 | $form .= self::tags( 'td', [ 'class' => 'mw-label' ], wfMessage( $labelmsg )->parse() ); |
833 | $form .= self::openElement( 'td', [ 'class' => 'mw-input' ] ) |
834 | . $input . self::closeElement( 'td' ); |
835 | $form .= self::closeElement( 'tr' ); |
836 | } |
837 | |
838 | if ( $submitLabel ) { |
839 | $form .= self::openElement( 'tr' ); |
840 | $form .= self::tags( 'td', [], '' ); |
841 | $form .= self::openElement( 'td', [ 'class' => 'mw-submit' ] ) |
842 | . self::submitButton( wfMessage( $submitLabel )->text(), $submitAttribs ) |
843 | . self::closeElement( 'td' ); |
844 | $form .= self::closeElement( 'tr' ); |
845 | } |
846 | |
847 | $form .= "</tbody></table>"; |
848 | |
849 | return $form; |
850 | } |
851 | |
852 | /** |
853 | * @param string[][] $rows |
854 | * @param array|null $attribs An array of attributes to apply to the table tag |
855 | * @param array|null $headers An array of strings to use as table headers |
856 | * @return string |
857 | * |
858 | * @deprecated since 1.42; use OOUI or Codex widgets instead; emiting deprecation warnings since 1.44 |
859 | */ |
860 | public static function buildTable( $rows, $attribs = [], $headers = null ) { |
861 | wfDeprecated( __METHOD__, '1.42' ); |
862 | |
863 | $s = self::openElement( 'table', $attribs ); |
864 | |
865 | if ( is_array( $headers ) ) { |
866 | $s .= self::openElement( 'thead', $attribs ); |
867 | |
868 | foreach ( $headers as $id => $header ) { |
869 | $attribs = []; |
870 | |
871 | if ( is_string( $id ) ) { |
872 | $attribs['id'] = $id; |
873 | } |
874 | |
875 | $s .= self::element( 'th', $attribs, $header ); |
876 | } |
877 | $s .= self::closeElement( 'thead' ); |
878 | } |
879 | |
880 | foreach ( $rows as $id => $row ) { |
881 | $attribs = []; |
882 | |
883 | if ( is_string( $id ) ) { |
884 | $attribs['id'] = $id; |
885 | } |
886 | |
887 | $s .= self::buildTableRow( $attribs, $row ); |
888 | } |
889 | |
890 | $s .= self::closeElement( 'table' ); |
891 | |
892 | return $s; |
893 | } |
894 | |
895 | /** |
896 | * Build a row for a table |
897 | * @param array|null $attribs An array of attributes to apply to the tr tag |
898 | * @param string[] $cells An array of strings to put in <td> |
899 | * @return string |
900 | * |
901 | * @deprecated since 1.42; use OOUI or Codex widgets instead; emiting deprecation warnings since 1.44 |
902 | */ |
903 | public static function buildTableRow( $attribs, $cells ) { |
904 | wfDeprecated( __METHOD__, '1.42' ); |
905 | |
906 | $s = self::openElement( 'tr', $attribs ); |
907 | |
908 | foreach ( $cells as $id => $cell ) { |
909 | $attribs = []; |
910 | |
911 | if ( is_string( $id ) ) { |
912 | $attribs['id'] = $id; |
913 | } |
914 | |
915 | $s .= self::element( 'td', $attribs, $cell ); |
916 | } |
917 | |
918 | $s .= self::closeElement( 'tr' ); |
919 | |
920 | return $s; |
921 | } |
922 | } |
923 | /** @deprecated class alias since 1.43 */ |
924 | class_alias( Xml::class, 'Xml' ); |