17 protected $mLabel; # String label, as HTML. Set on construction.
87 public function msg( $key, ...$params ) {
88 if ( $this->mParent ) {
89 return $this->mParent->msg( $key, ...$params );
121 while ( preg_match(
'/^(.+)\[([^\]]+)\]$/', $tmp, $m ) ) {
122 array_unshift( $thisKeys, $m[2] );
125 if ( substr( $tmp, 0, 2 ) ==
'wp' &&
126 !array_key_exists( $tmp, $alldata ) &&
127 array_key_exists( substr( $tmp, 2 ), $alldata )
130 $tmp = substr( $tmp, 2 );
132 array_unshift( $thisKeys, $tmp );
136 while ( preg_match(
'/^(.+)\[([^\]]+)\]$/', $tmp, $m ) ) {
137 array_unshift( $nameKeys, $m[2] );
140 array_unshift( $nameKeys, $tmp );
143 for ( $i = count( $thisKeys ) - 1; $i >= 0; $i-- ) {
144 $keys = array_merge( array_slice( $thisKeys, 0, $i ), $nameKeys );
146 foreach (
$keys as $key ) {
147 if ( !is_array( $data ) || !array_key_exists( $key, $data ) ) {
152 $testValue = (string)$data;
168 $origParams = $params;
169 $op = array_shift( $params );
174 foreach ( $params as $i => $p ) {
175 if ( !is_array( $p ) ) {
177 "Expected array, found " . gettype( $p ) .
" at index $i"
187 foreach ( $params as $i => $p ) {
188 if ( !is_array( $p ) ) {
190 "Expected array, found " . gettype( $p ) .
" at index $i"
200 foreach ( $params as $i => $p ) {
201 if ( !is_array( $p ) ) {
203 "Expected array, found " . gettype( $p ) .
" at index $i"
213 foreach ( $params as $i => $p ) {
214 if ( !is_array( $p ) ) {
216 "Expected array, found " . gettype( $p ) .
" at index $i"
226 if ( count( $params ) !== 1 ) {
227 throw new MWException(
"NOT takes exactly one parameter" );
230 if ( !is_array( $p ) ) {
232 "Expected array, found " . gettype( $p ) .
" at index 0"
239 if ( count( $params ) !== 2 ) {
240 throw new MWException(
"$op takes exactly two parameters" );
242 list( $field, $value ) = $params;
243 if ( !is_string( $field ) || !is_string( $value ) ) {
244 throw new MWException(
"Parameters for $op must be strings" );
249 return ( $value === $testValue );
251 return ( $value !== $testValue );
257 }
catch ( Exception $ex ) {
259 "Invalid hide-if specification for $this->mName: " .
260 $ex->getMessage() .
" in " . var_export( $origParams,
true ),
275 if ( !$this->mHideIf ) {
310 if ( $this->
isHidden( $alldata ) ) {
314 if ( isset( $this->mParams[
'required'] )
315 && $this->mParams[
'required'] !==
false
318 return $this->
msg(
'htmlform-required' );
321 if ( isset( $this->mValidationCallback ) ) {
322 return ( $this->mValidationCallback )( $value, $alldata, $this->mParent );
336 public function filter( $value, $alldata ) {
337 if ( isset( $this->mFilterCallback ) ) {
338 $value = ( $this->mFilterCallback )( $value, $alldata, $this->mParent );
365 $this->mShowEmptyLabels = $show;
379 return $request->
getCheck(
'wpEditToken' ) || $request->
getCheck(
'wpFormIdentifier' );
391 if ( $request->getCheck( $this->mName ) ) {
392 return $request->getText( $this->mName );
408 $this->mParams = $params;
410 if ( isset( $params[
'parent'] ) && $params[
'parent'] instanceof
HTMLForm ) {
411 $this->mParent = $params[
'parent'];
414 # Generate the label from a message, if possible
415 if ( isset( $params[
'label-message'] ) ) {
416 $this->mLabel = $this->
getMessage( $params[
'label-message'] )->parse();
417 } elseif ( isset( $params[
'label'] ) ) {
418 if ( $params[
'label'] ===
' ' || $params[
'label'] ===
"\u{00A0}" ) {
420 $this->mLabel =
"\u{00A0}";
422 $this->mLabel = htmlspecialchars( $params[
'label'] );
424 } elseif ( isset( $params[
'label-raw'] ) ) {
425 $this->mLabel = $params[
'label-raw'];
428 $this->mName =
"wp{$params['fieldname']}";
429 if ( isset( $params[
'name'] ) ) {
430 $this->mName = $params[
'name'];
433 if ( isset( $params[
'dir'] ) ) {
434 $this->mDir = $params[
'dir'];
437 $validName = urlencode( $this->mName );
438 $validName = str_replace( [
'%5B',
'%5D' ], [
'[',
']' ], $validName );
439 if ( $this->mName != $validName && !isset( $params[
'nodata'] ) ) {
440 throw new MWException(
"Invalid name '{$this->mName}' passed to " . __METHOD__ );
443 $this->mID =
"mw-input-{$this->mName}";
445 if ( isset( $params[
'default'] ) ) {
446 $this->mDefault = $params[
'default'];
449 if ( isset( $params[
'id'] ) ) {
451 $validId = urlencode( $id );
453 if ( $id != $validId ) {
454 throw new MWException(
"Invalid id '$id' passed to " . __METHOD__ );
460 if ( isset( $params[
'cssclass'] ) ) {
461 $this->mClass = $params[
'cssclass'];
464 if ( isset( $params[
'csshelpclass'] ) ) {
465 $this->mHelpClass = $params[
'csshelpclass'];
468 if ( isset( $params[
'validation-callback'] ) ) {
469 $this->mValidationCallback = $params[
'validation-callback'];
472 if ( isset( $params[
'filter-callback'] ) ) {
473 $this->mFilterCallback = $params[
'filter-callback'];
476 if ( isset( $params[
'hidelabel'] ) ) {
477 $this->mShowEmptyLabels =
false;
480 if ( isset( $params[
'hide-if'] ) ) {
481 $this->mHideIf = $params[
'hide-if'];
499 $cellAttributes = [];
503 if ( !empty( $this->mParams[
'vertical-label'] ) ) {
504 $cellAttributes[
'colspan'] = 2;
505 $verticalLabel =
true;
507 $verticalLabel =
false;
512 $field = Html::rawElement(
514 [
'class' =>
'mw-input' ] + $cellAttributes,
515 $inputHtml .
"\n$errors"
518 if ( $this->mHideIf ) {
519 $rowAttributes[
'data-hide-if'] = FormatJson::encode( $this->mHideIf );
520 $rowClasses .=
' mw-htmlform-hide-if';
523 if ( $verticalLabel ) {
524 $html = Html::rawElement(
'tr',
525 $rowAttributes + [
'class' =>
"mw-htmlform-vertical-label $rowClasses" ], $label );
526 $html .= Html::rawElement(
'tr',
528 'class' =>
"mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
533 Html::rawElement(
'tr',
535 'class' =>
"mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
540 return $html . $helptext;
558 $cellAttributes = [];
563 'mw-htmlform-nolabel' => ( $label ===
'' )
566 $horizontalLabel = $this->mParams[
'horizontal-label'] ??
false;
568 if ( $horizontalLabel ) {
569 $field =
"\u{00A0}" . $inputHtml .
"\n$errors";
571 $field = Html::rawElement(
574 [
'class' => $outerDivClass ] + $cellAttributes,
575 $inputHtml .
"\n$errors"
578 $divCssClasses = [
"mw-htmlform-field-$fieldType",
579 $this->mClass, $this->mVFormClass, $errorClass ];
581 $wrapperAttributes = [
582 'class' => $divCssClasses,
584 if ( $this->mHideIf ) {
585 $wrapperAttributes[
'data-hide-if'] = FormatJson::encode( $this->mHideIf );
586 $wrapperAttributes[
'class'][] =
' mw-htmlform-hide-if';
588 $html = Html::rawElement(
'div', $wrapperAttributes, $label . $field );
606 if ( !$inputField ) {
611 new OOUI\Widget( [
'content' =>
new OOUI\HtmlSnippet( $this->
getDiv( $value ) ) ] ),
617 if ( is_string( $inputField ) ) {
621 $inputField =
new OOUI\Widget( [
'content' =>
new OOUI\HtmlSnippet( $inputField ) ] );
628 foreach ( $errors as &$error ) {
629 $error =
new OOUI\HtmlSnippet( $error );
633 'classes' => [
"mw-htmlform-field-$fieldType", $this->mClass ],
635 'help' => (
$help !==
null &&
$help !==
'' ) ?
new OOUI\HtmlSnippet(
$help ) :
null,
637 'infusable' => $infusable,
641 $preloadModules =
false;
644 $preloadModules =
true;
645 $config[
'classes'][] =
'mw-htmlform-field-autoinfuse';
650 if ( $label && $label !==
"\u{00A0}" && $label !==
' ' ) {
651 $config[
'label'] =
new OOUI\HtmlSnippet( $label );
654 if ( $this->mHideIf ) {
655 $preloadModules =
true;
656 $config[
'hideIf'] = $this->mHideIf;
661 if ( $preloadModules ) {
662 $this->mParent->getOutput()->addModules(
'mediawiki.htmlform.ooui' );
663 $this->mParent->getOutput()->addModules( $this->
getOOUIModules() );
677 $name = explode(
'\\', static::class );
698 if ( isset( $this->mClassWithButton ) ) {
699 $buttonWidget = $this->mClassWithButton->getInputOOUI(
'' );
743 $cellAttributes = [];
765 $this->mVFormClass =
' mw-ui-vform-field';
766 return $this->
getDiv( $value );
780 $cellAttributes = [];
783 $html =
"\n" . $errors .
784 $label .
"\u{00A0}" .
799 if ( $helptext ===
null ) {
804 if ( $this->mHideIf ) {
805 $rowAttributes[
'data-hide-if'] = FormatJson::encode( $this->mHideIf );
806 $rowAttributes[
'class'] =
'mw-htmlform-hide-if';
809 $tdClasses = [
'htmlform-tip' ];
810 if ( $this->mHelpClass !==
false ) {
811 $tdClasses[] = $this->mHelpClass;
813 $row = Html::rawElement(
'td', [
'colspan' => 2,
'class' => $tdClasses ], $helptext );
814 $row = Html::rawElement(
'tr', $rowAttributes, $row );
828 if ( $helptext ===
null ) {
832 $wrapperAttributes = [
833 'class' =>
'htmlform-tip',
835 if ( $this->mHelpClass !==
false ) {
836 $wrapperAttributes[
'class'] .=
" {$this->mHelpClass}";
838 if ( $this->mHideIf ) {
839 $wrapperAttributes[
'data-hide-if'] = FormatJson::encode( $this->mHideIf );
840 $wrapperAttributes[
'class'] .=
' mw-htmlform-hide-if';
842 $div = Html::rawElement(
'div', $wrapperAttributes, $helptext );
867 if ( isset( $this->mParams[
'help-message'] ) ) {
868 $this->mParams[
'help-messages'] = [ $this->mParams[
'help-message'] ];
871 if ( isset( $this->mParams[
'help-messages'] ) ) {
872 foreach ( $this->mParams[
'help-messages'] as $msg ) {
875 if ( $msg->exists() ) {
876 if ( $helptext ===
null ) {
879 $helptext .= $this->
msg(
'word-separator' )->escaped();
881 $helptext .= $msg->parse();
884 } elseif ( isset( $this->mParams[
'help'] ) ) {
885 $helptext = $this->mParams[
'help'];
900 return $this->mParams[
'help-inline'] ??
true;
916 $errors = $this->
validate( $value, $this->mParent->mFieldData );
918 if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
922 $errors = self::formatErrors( $errors );
923 $errorClass =
'mw-htmlform-invalid-input';
926 return [ $errors, $errorClass ];
937 $errors = $this->
validate( $value, $this->mParent->mFieldData );
939 if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
943 if ( !is_array( $errors ) ) {
944 $errors = [ $errors ];
946 foreach ( $errors as &$error ) {
947 if ( $error instanceof
Message ) {
948 $error = $error->parse();
960 return $this->mLabel ??
'';
970 # Don't output a for= attribute for labels with no associated input.
971 # Kind of hacky here, possibly we don't want these to be <label>s at all.
975 $for[
'for'] = $this->mID;
978 $labelValue = trim( $this->
getLabel() );
980 if ( $labelValue !==
"\u{00A0}" && $labelValue !==
' ' && $labelValue !==
'' ) {
984 $displayFormat = $this->mParent->getDisplayFormat();
986 $horizontalLabel = $this->mParams[
'horizontal-label'] ??
false;
988 if ( $displayFormat ===
'table' ) {
990 Html::rawElement(
'td',
991 [
'class' =>
'mw-label' ] + $cellAttributes,
992 Html::rawElement(
'label', $for, $labelValue ) );
993 } elseif ( $hasLabel || $this->mShowEmptyLabels ) {
994 if ( $displayFormat ===
'div' && !$horizontalLabel ) {
996 Html::rawElement(
'div',
997 [
'class' =>
'mw-label' ] + $cellAttributes,
998 Html::rawElement(
'label', $for, $labelValue ) );
1000 $html = Html::rawElement(
'label', $for, $labelValue );
1012 return $this->mDefault ??
null;
1021 if ( empty( $this->mParams[
'tooltip'] ) ) {
1034 if ( empty( $this->mParams[
'tooltip'] ) ) {
1052 static $boolAttribs = [
'disabled',
'required',
'autofocus',
'multiple',
'readonly' ];
1055 foreach ( $list as $key ) {
1056 if ( in_array( $key, $boolAttribs ) ) {
1057 if ( !empty( $this->mParams[$key] ) ) {
1060 } elseif ( isset( $this->mParams[$key] ) ) {
1061 $ret[$key] = $this->mParams[$key];
1077 foreach ( $options as $key => $value ) {
1078 $key = $this->
msg( $key )->plain();
1079 $ret[$key] = is_array( $value )
1094 if ( is_array( $array ) ) {
1095 return array_map( [ __CLASS__,
'forceToStringRecursive' ], $array );
1097 return strval( $array );
1108 if ( $this->mOptions ===
false ) {
1109 if ( array_key_exists(
'options-messages', $this->mParams ) ) {
1110 $this->mOptions = $this->
lookupOptionsKeys( $this->mParams[
'options-messages'] );
1111 } elseif ( array_key_exists(
'options', $this->mParams ) ) {
1112 $this->mOptionsLabelsNotFromMessage =
true;
1113 $this->mOptions = self::forceToStringRecursive( $this->mParams[
'options'] );
1114 } elseif ( array_key_exists(
'options-message', $this->mParams ) ) {
1115 $message = $this->
getMessage( $this->mParams[
'options-message'] )->inContentLanguage()->plain();
1116 $this->mOptions = Xml::listDropDownOptions( $message );
1118 $this->mOptions =
null;
1122 return $this->mOptions;
1133 if ( $oldoptions ===
null ) {
1137 return Xml::listDropDownOptionsOoui( $oldoptions );
1150 foreach ( $options as $value ) {
1151 if ( is_array( $value ) ) {
1152 $flatOpts = array_merge( $flatOpts, self::flattenOptions( $value ) );
1154 $flatOpts[] = $value;
1178 if ( is_array( $errors ) && count( $errors ) === 1 ) {
1179 $errors = array_shift( $errors );
1182 if ( is_array( $errors ) ) {
1184 foreach ( $errors as $error ) {
1185 if ( $error instanceof
Message ) {
1186 $lines[] = Html::rawElement(
'li', [], $error->parse() );
1188 $lines[] = Html::rawElement(
'li', [], $error );
1192 $errors = Html::rawElement(
'ul', [], implode(
"\n",
$lines ) );
1194 if ( $errors instanceof
Message ) {
1195 $errors = $errors->parse();
1199 return Html::rawElement(
'div', [
'class' =>
'errorbox' ], $errors );
1211 if ( $this->mParent ) {
1212 $message->setContext( $this->mParent );
1226 return !empty( $this->mParams[
'nodata'] );
1237 if ( $this->mHideIf ) {
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
static titleAttrib( $name, $options=null, array $msgParams=[])
Given the id of an interface element, constructs the appropriate title attribute from the system mess...
static accesskey( $name)
Given the id of an interface element, constructs the appropriate accesskey attribute from the system ...
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null)
Returns the attributes for the tooltip and access key.
The Message class deals with fetching and processing of interface message into a variety of formats.
static newFromSpecifier( $value)
Transform a MessageSpecifier or a primitive value used interchangeably with specifiers (a message key...
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
getCheck( $name)
Return true if the named value is set in the input, whatever that value is (even "0").
if(!file_exists( $CREDITS)) $lines