MediaWiki master
Xml.php
Go to the documentation of this file.
1<?php
9namespace MediaWiki\Xml;
10
14use UtfNormal\Validator;
15
19class Xml {
36 public static function element( $element, $attribs = null, $contents = '',
37 $allowShortTag = true
38 ) {
39 $out = '<' . $element;
40 if ( $attribs !== null ) {
41 $out .= self::expandAttributes( $attribs );
42 }
43 if ( $contents === null ) {
44 $out .= '>';
45 } elseif ( $allowShortTag && $contents === '' ) {
46 $out .= ' />';
47 } else {
48 // @phan-suppress-next-line PhanTypeMismatchArgumentNullableInternal $contents is non-nullable
49 $out .= '>' . htmlspecialchars( $contents, ENT_NOQUOTES ) . "</$element>";
50 }
51 return $out;
52 }
53
62 public static function expandAttributes( ?array $attribs ) {
63 if ( $attribs === null ) {
64 return null;
65 }
66 $out = '';
67 foreach ( $attribs as $name => $val ) {
68 $out .= " {$name}=\"" . Sanitizer::encodeAttribute( $val ) . '"';
69 }
70 return $out;
71 }
72
84 public static function elementClean( $element, $attribs = [], $contents = '' ) {
85 if ( $attribs ) {
86 $attribs = array_map( Validator::cleanUp( ... ), $attribs );
87 }
88 if ( $contents ) {
89 $contents =
90 MediaWikiServices::getInstance()->getContentLanguage()->normalize( $contents );
91 }
92 return self::element( $element, $attribs, $contents );
93 }
94
102 public static function openElement( $element, $attribs = null ) {
103 return '<' . $element . self::expandAttributes( $attribs ) . '>';
104 }
105
111 public static function closeElement( $element ) {
112 return "</$element>";
113 }
114
128 public static function tags( $element, $attribs, $contents ) {
129 return self::openElement( $element, $attribs ) . $contents . "</$element>";
130 }
131
142 public static function attrib( $name, $present = true ) {
143 wfDeprecated( __METHOD__, '1.42' );
144
145 return $present ? [ $name => $name ] : [];
146 }
147
160 public static function label( $label, $id, $attribs = [] ) {
161 wfDeprecated( __METHOD__, '1.42' );
162
163 $a = [ 'for' => $id ];
164
165 foreach ( [ 'class', 'title' ] as $attr ) {
166 if ( isset( $attribs[$attr] ) ) {
167 $a[$attr] = $attribs[$attr];
168 }
169 }
170
171 return self::element( 'label', $a, $label );
172 }
173
184 public static function option( $text, $value = null, $selected = false,
185 $attribs = [] ) {
186 wfDeprecated( __METHOD__, '1.42' );
187
188 if ( $value !== null ) {
189 $attribs['value'] = $value;
190 }
191 if ( $selected ) {
192 $attribs['selected'] = 'selected';
193 }
194 return Html::element( 'option', $attribs, $text );
195 }
196
212 public static function listDropdown( $name = '', $list = '', $other = '',
213 $selected = '', $class = '', $tabindex = null
214 ) {
215 wfDeprecated( __METHOD__, '1.42' );
216
217 $options = self::listDropdownOptions( $list, [ 'other' => $other ] );
218
219 $xmlSelect = new XmlSelect( $name, $name, $selected );
220 $xmlSelect->addOptions( $options );
221
222 if ( $class ) {
223 $xmlSelect->setAttribute( 'class', $class );
224 }
225 if ( $tabindex ) {
226 $xmlSelect->setAttribute( 'tabindex', $tabindex );
227 }
228
229 return $xmlSelect->getHTML();
230 }
231
247 public static function listDropdownOptions( $list, $params = [] ) {
248 wfDeprecated( __METHOD__, '1.42' );
249
250 $options = [];
251
252 if ( isset( $params['other'] ) ) {
253 $options[ $params['other'] ] = 'other';
254 }
255
256 $optgroup = false;
257 foreach ( explode( "\n", $list ) as $option ) {
258 $value = trim( $option );
259 if ( $value == '' ) {
260 continue;
261 }
262 if ( str_starts_with( $value, '*' ) && substr( $value, 1, 1 ) != '*' ) {
263 # A new group is starting...
264 $value = trim( substr( $value, 1 ) );
265 if ( $value !== '' &&
266 // Do not use the value for 'other' as option group - T251351
267 ( !isset( $params['other'] ) || $value !== $params['other'] )
268 ) {
269 $optgroup = $value;
270 } else {
271 $optgroup = false;
272 }
273 } elseif ( str_starts_with( $value, '**' ) ) {
274 # groupmember
275 $opt = trim( substr( $value, 2 ) );
276 if ( $optgroup === false ) {
277 $options[$opt] = $opt;
278 } else {
279 $options[$optgroup][$opt] = $opt;
280 }
281 } else {
282 # groupless reason list
283 $optgroup = false;
284 $options[$option] = $option;
285 }
286 }
287
288 return $options;
289 }
290
301 public static function listDropdownOptionsOoui( $options ) {
302 wfDeprecated( __METHOD__, '1.42' );
303
304 $optionsOoui = [];
305
306 foreach ( $options as $text => $value ) {
307 if ( is_array( $value ) ) {
308 $optionsOoui[] = [ 'optgroup' => (string)$text ];
309 foreach ( $value as $text2 => $value2 ) {
310 $optionsOoui[] = [ 'data' => (string)$value2, 'label' => (string)$text2 ];
311 }
312 } else {
313 $optionsOoui[] = [ 'data' => (string)$value, 'label' => (string)$text ];
314 }
315 }
316
317 return $optionsOoui;
318 }
319
332 public static function fieldset( $legend = false, $content = false, $attribs = [] ) {
333 wfDeprecated( __METHOD__, '1.42' );
334
335 $s = self::openElement( 'fieldset', $attribs ) . "\n";
336
337 if ( $legend ) {
338 $s .= self::element( 'legend', null, $legend ) . "\n";
339 }
340
341 if ( $content !== false ) {
342 $s .= $content . "\n";
343 $s .= self::closeElement( 'fieldset' ) . "\n";
344 }
345
346 return $s;
347 }
348
360 private static function isWellFormed( $text ) {
361 $parser = xml_parser_create( "UTF-8" );
362
363 # case folding violates XML standard, turn it off
364 xml_parser_set_option( $parser, XML_OPTION_CASE_FOLDING, 0 );
365
366 if ( !xml_parse( $parser, $text, true ) ) {
367 return false;
368 }
369 return true;
370 }
371
380 public static function isWellFormedXmlFragment( $text ) {
381 $html =
382 Sanitizer::hackDocType() .
383 '<html>' .
384 $text .
385 '</html>';
386
387 return self::isWellFormed( $html );
388 }
389
397 public static function escapeTagsOnly( $in ) {
398 return str_replace(
399 [ '"', '>', '<' ],
400 [ '&quot;', '&gt;', '&lt;' ],
401 $in );
402 }
403
417 public static function buildForm( $fields, $submitLabel = null, $submitAttribs = [] ) {
418 wfDeprecated( __METHOD__, '1.42' );
419
420 $form = '';
421 $form .= "<table><tbody>";
422
423 foreach ( $fields as $labelmsg => $input ) {
424 $id = "mw-$labelmsg";
425 $form .= self::openElement( 'tr', [ 'id' => $id ] );
426
427 // TODO use a <label> here for accessibility purposes - will need
428 // to either not use a table to build the form, or find the ID of
429 // the input somehow.
430
431 $form .= self::tags( 'td', [ 'class' => 'mw-label' ], wfMessage( $labelmsg )->parse() );
432 $form .= self::tags( 'td', [ 'class' => 'mw-input' ], $input );
433 $form .= self::closeElement( 'tr' );
434 }
435
436 if ( $submitLabel ) {
437 $form .= self::openElement( 'tr' );
438 $form .= self::tags( 'td', [], '' );
439 $form .= self::openElement( 'td', [ 'class' => 'mw-submit' ] )
441 'input',
442 $submitAttribs + [
443 'type' => 'submit',
444 'value' => wfMessage( $submitLabel )->text(),
445 ]
446 )
447 . self::closeElement( 'td' );
448 $form .= self::closeElement( 'tr' );
449 }
450
451 $form .= "</tbody></table>";
452
453 return $form;
454 }
455}
457class_alias( Xml::class, 'Xml' );
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
This class is a collection of static functions that serve two purposes:
Definition Html.php:44
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:32
Class for generating HTML <select> or <datalist> elements.
Definition XmlSelect.php:16
Module of static functions for generating XML.
Definition Xml.php:19
static escapeTagsOnly( $in)
Replace " > and < with their respective HTML entities ( ", >, <)
Definition Xml.php:397
static elementClean( $element, $attribs=[], $contents='')
Format an XML element as with self::element(), but run text through the content language's normalize(...
Definition Xml.php:84
static attrib( $name, $present=true)
Internal function for use in checkboxes and radio buttons and such.
Definition Xml.php:142
static isWellFormedXmlFragment( $text)
Check if a string is a well-formed XML fragment.
Definition Xml.php:380
static element( $element, $attribs=null, $contents='', $allowShortTag=true)
Format an XML element with given attributes and, optionally, text content.
Definition Xml.php:36
static label( $label, $id, $attribs=[])
Convenience function to build an HTML form label.
Definition Xml.php:160
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition Xml.php:128
static expandAttributes(?array $attribs)
Given an array of ('attributename' => 'value'), it generates the code to set the XML attributes : att...
Definition Xml.php:62
static buildForm( $fields, $submitLabel=null, $submitAttribs=[])
Generate a form (without the opening form element).
Definition Xml.php:417
static openElement( $element, $attribs=null)
This opens an XML element.
Definition Xml.php:102
static option( $text, $value=null, $selected=false, $attribs=[])
Convenience function to build an HTML drop-down list item.
Definition Xml.php:184
static listDropdown( $name='', $list='', $other='', $selected='', $class='', $tabindex=null)
Build a drop-down box from a textual list.
Definition Xml.php:212
static listDropdownOptionsOoui( $options)
Convert options for a drop-down box into a format accepted by OOUI\DropdownInputWidget etc.
Definition Xml.php:301
static closeElement( $element)
Shortcut to close an XML element.
Definition Xml.php:111
static fieldset( $legend=false, $content=false, $attribs=[])
Shortcut for creating fieldsets.
Definition Xml.php:332
static listDropdownOptions( $list, $params=[])
Build options for a drop-down box from a textual list.
Definition Xml.php:247
element(SerializerNode $parent, SerializerNode $node, $contents)