5use InvalidArgumentException;
33 protected $mValidationCallback;
35 protected $mFilterCallback;
138 public function msg( $key, ...$params ) {
139 return $this->mParent->msg( $key, ...$params );
176 $cloner = $this->mParams[
'cloner'] ??
null;
178 $field = $cloner->findNearestField( $this, $name );
184 if ( $backCompat && str_starts_with( $name,
'wp' ) &&
185 !$this->mParent->hasField( $name )
188 return $this->mParent->getField( substr( $name, 2 ) );
190 return $this->mParent->getField( $name );
207 $cloner = $field->mParams[
'cloner'] ??
null;
209 $value = $cloner->extractFieldData( $field, $alldata );
214 $value = $alldata[$field->mParams[
'fieldname']] ?? $field->getDefault();
218 if ( $asDisplay && $field instanceof
HTMLCheckField && ( $field->mParams[
'invert'] ??
false ) ) {
246 $origParams = $params;
247 $op = array_shift( $params );
249 $makeException =
function (
string $details ) use ( $origParams ): InvalidArgumentException {
250 return new InvalidArgumentException(
251 "Invalid hide-if or disable-if specification for $this->mName: " .
252 $details .
" in " . var_export( $origParams,
true )
258 if ( count( $params ) !== 1 ) {
259 throw $makeException(
"NOT takes exactly one parameter" );
267 foreach ( $params as $i => $p ) {
268 if ( !is_array( $p ) ) {
269 $type = get_debug_type( $p );
270 throw $makeException(
"Expected array, found $type at index $i" );
279 if ( count( $params ) !== 2 ) {
280 throw $makeException(
"$op takes exactly two parameters" );
282 [ $name, $value ] = $params;
283 if ( !is_string( $name ) || !is_string( $value ) ) {
284 throw $makeException(
"Parameters for $op must be strings" );
289 throw $makeException(
"Unknown operation" );
301 $op = array_shift( $params );
302 $valueChk = [
'AND' =>
false,
'OR' =>
true,
'NAND' =>
false,
'NOR' => true ];
303 $valueRet = [
'AND' =>
true,
'OR' =>
false,
'NAND' =>
false,
'NOR' => true ];
310 foreach ( $params as $p ) {
312 return !$valueRet[$op];
315 return $valueRet[$op];
323 [ $field, $value ] = $params;
327 return ( $value === (
string)$testValue );
329 return ( $value !== (
string)$testValue );
331 return in_array( $value, $testValue,
true );
345 $op = array_shift( $params );
353 foreach ( $params as $p ) {
364 [ $name, $value ] = $params;
366 return [ $op, $field->getName(), $value ];
377 foreach ( $this->mCondState as $type => $params ) {
379 if ( in_array( $type, [
'hide',
'disable' ],
true ) ) {
385 $parsed[
'alwaysDisabled'] = ( $this->mParams[
'disabled'] ?? false );
398 return isset( $this->mCondState[
'hide'] ) &&
410 return isset( $this->mCondState[
'hide-nojs'] ) &&
423 return ( $this->mParams[
'disabled'] ??
false ) ||
425 ( isset( $this->mCondState[
'disable'] )
438 return ( $this->mParams[
'disabled'] ??
false ) ||
440 ( isset( $this->mCondState[
'disable-nojs'] )
472 if ( $this->
isHidden( $alldata ) ) {
476 if ( isset( $this->mParams[
'required'] )
477 && $this->mParams[
'required'] !==
false
478 && ( $value ===
'' || $value ===
false || $value ===
null )
480 return $this->
msg(
'htmlform-required' );
483 if ( $this->mValidationCallback ===
null ) {
487 $p = ( $this->mValidationCallback )( $value, $alldata, $this->mParent );
490 $language = $this->mParent->getLanguage();
492 return $p->isGood() ? true : Status::wrap( $p )->getHTML(
false,
false, $language );
506 public function filter( $value, $alldata ) {
507 if ( $this->mFilterCallback !==
null ) {
508 $value = ( $this->mFilterCallback )( $value, $alldata, $this->mParent );
535 $this->mShowEmptyLabels = $show;
553 ||
$request->getCheck(
'wpFormIdentifier' );
565 if (
$request->getCheck( $this->mName ) ) {
566 return $request->getText( $this->mName );
581 $this->mParams = $params;
583 if ( !( isset( $params[
'parent'] ) && $params[
'parent'] instanceof
HTMLForm ) ) {
584 throw new RuntimeException(
"Parent must be set." );
586 $this->mParent = $params[
'parent'];
588 # Generate the label from a message, if possible
589 if ( isset( $params[
'label-message'] ) ) {
590 $this->mLabel = $this->
getMessage( $params[
'label-message'] )->parse();
591 } elseif ( isset( $params[
'label'] ) ) {
592 if ( $params[
'label'] ===
' ' || $params[
'label'] ===
"\u{00A0}" ) {
594 $this->mLabel =
"\u{00A0}";
596 $this->mLabel = htmlspecialchars( $params[
'label'] );
598 } elseif ( isset( $params[
'label-raw'] ) ) {
599 $this->mLabel = $params[
'label-raw'];
602 $this->mName = $params[
'name'] ??
'wp' . $params[
'fieldname'];
604 if ( isset( $params[
'dir'] ) ) {
605 $this->mDir = $params[
'dir'];
608 $this->mID =
"mw-input-{$this->mName}";
610 if ( isset( $params[
'default'] ) ) {
611 $this->mDefault = $params[
'default'];
614 if ( isset( $params[
'id'] ) ) {
615 $this->mID = $params[
'id'];
618 if ( isset( $params[
'cssclass'] ) ) {
619 $this->mClass = $params[
'cssclass'];
622 if ( isset( $params[
'csshelpclass'] ) ) {
623 $this->mHelpClass = $params[
'csshelpclass'];
626 if ( isset( $params[
'validation-callback'] ) ) {
627 $this->mValidationCallback = $params[
'validation-callback'];
630 if ( isset( $params[
'filter-callback'] ) ) {
631 $this->mFilterCallback = $params[
'filter-callback'];
634 if ( isset( $params[
'hidelabel'] ) ) {
635 $this->mShowEmptyLabels =
false;
637 if ( isset( $params[
'notices'] ) ) {
638 $this->mNotices = $params[
'notices'];
641 if ( isset( $params[
'hide-if'] ) && $params[
'hide-if'] ) {
643 $this->mCondState[
'hide'] = $params[
'hide-if'];
645 if ( isset( $params[
'hide-if-nojs'] ) && $params[
'hide-if-nojs'] ) {
647 $this->mCondState[
'hide-nojs'] = $params[
'hide-if-nojs'];
650 $this->mCondState[
'hide'] = isset( $this->mCondState[
'hide'] ) ?
651 [
'OR', $this->mCondState[
'hide'], $params[
'hide-if-nojs'] ] :
652 $params[
'hide-if-nojs'];
654 if ( isset( $this->mCondState[
'hide'] ) ) {
655 $this->mCondStateClass[] =
'mw-htmlform-hide-if';
658 if ( !( isset( $params[
'disabled'] ) && $params[
'disabled'] ) &&
659 isset( $params[
'disable-if'] ) && $params[
'disable-if']
662 $this->mCondState[
'disable'] = $params[
'disable-if'];
664 if ( !( isset( $params[
'disabled'] ) && $params[
'disabled'] ) &&
665 isset( $params[
'disable-if-nojs'] ) && $params[
'disable-if-nojs']
668 $this->mCondState[
'disable-nojs'] = $params[
'disable-if-nojs'];
671 $this->mCondState[
'disable'] = isset( $this->mCondState[
'disable'] ) ?
672 [
'OR', $this->mCondState[
'disable'], $params[
'disable-if-nojs'] ] :
673 $params[
'disable-if-nojs'];
675 if ( isset( $this->mCondState[
'disable'] ) ) {
676 $this->mCondStateClass[] =
'mw-htmlform-disable-if';
694 $cellAttributes = [];
698 if ( !empty( $this->mParams[
'vertical-label'] ) ) {
699 $cellAttributes[
'colspan'] = 2;
700 $verticalLabel =
true;
702 $verticalLabel =
false;
707 $field = Html::rawElement(
709 [
'class' =>
'mw-input' ] + $cellAttributes,
710 $inputHtml .
"\n$errors"
713 if ( $this->mCondState ) {
715 $rowClasses .= implode(
' ', $this->mCondStateClass );
716 if ( $this->
isHiddenNoJs( $this->mParent->mFieldData ) ) {
717 $rowClasses .=
' mw-htmlform-hide-if-hidden-nojs';
718 } elseif ( $this->
isHidden( $this->mParent->mFieldData ) ) {
719 $rowClasses .=
' mw-htmlform-hide-if-hidden';
723 if ( $verticalLabel ) {
724 $html = Html::rawElement(
'tr',
725 $rowAttributes + [
'class' =>
"mw-htmlform-vertical-label $rowClasses" ], $label );
726 $html .= Html::rawElement(
'tr',
728 'class' =>
"mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
732 $html = Html::rawElement(
'tr',
734 'class' =>
"mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
739 return $html . $helptext;
757 $cellAttributes = [];
762 'mw-htmlform-nolabel' => ( $label ===
'' )
765 $horizontalLabel = $this->mParams[
'horizontal-label'] ??
false;
767 if ( $horizontalLabel ) {
768 $field =
"\u{00A0}" . $inputHtml .
"\n$errors";
770 $field = Html::rawElement(
773 [
'class' => $outerDivClass ] + $cellAttributes,
774 $inputHtml .
"\n$errors"
778 $wrapperAttributes = [
'class' => [
779 "mw-htmlform-field-$fieldType",
783 if ( $this->mCondState ) {
785 $wrapperAttributes[
'class'] = array_merge( $wrapperAttributes[
'class'], $this->mCondStateClass );
786 if ( $this->
isHiddenNoJs( $this->mParent->mFieldData ) ) {
787 $wrapperAttributes[
'class'][] =
'mw-htmlform-hide-if-hidden-nojs';
788 } elseif ( $this->
isHidden( $this->mParent->mFieldData ) ) {
789 $wrapperAttributes[
'class'][] =
'mw-htmlform-hide-if-hidden';
792 return Html::rawElement(
'div', $wrapperAttributes, $label . $field ) .
806 if ( $this->getDescriptionMessages() !== [] ) {
807 throw new InvalidArgumentException(
808 "OOUIHTMLForm does not support the descriptions for fields. Please use Codex"
813 if ( !$inputField ) {
818 new \OOUI\Widget( [
'content' =>
new \OOUI\HtmlSnippet( $this->
getDiv( $value ) ) ] ),
824 if ( is_string( $inputField ) ) {
828 $inputField = new \OOUI\Widget( [
'content' =>
new \OOUI\HtmlSnippet( $inputField ) ] );
835 foreach ( $errors as &$error ) {
836 $error = new \OOUI\HtmlSnippet( $error );
840 'classes' => [
"mw-htmlform-field-$fieldType" ],
842 'help' => ( $help !==
null && $help !==
'' ) ?
new \OOUI\HtmlSnippet( $help ) :
null,
844 'infusable' => $infusable,
846 'notices' => $this->mNotices ?: [],
848 if ( $this->mClass !==
'' ) {
852 $preloadModules =
false;
855 $preloadModules =
true;
856 $config[
'classes'][] =
'mw-htmlform-autoinfuse';
858 if ( $this->mCondState ) {
859 $config[
'classes'] = array_merge( $config[
'classes'], $this->mCondStateClass );
860 if ( $this->
isHiddenNoJs( $this->mParent->mFieldData ) ) {
861 $config[
'classes'][] =
'mw-htmlform-hide-if-hidden-nojs';
862 } elseif ( $this->
isHidden( $this->mParent->mFieldData ) ) {
863 $config[
'classes'][] =
'mw-htmlform-hide-if-hidden';
869 if ( $label && $label !==
"\u{00A0}" && $label !==
' ' ) {
870 $config[
'label'] = new \OOUI\HtmlSnippet( $label );
873 if ( $this->mCondState ) {
874 $preloadModules =
true;
880 if ( $preloadModules ) {
881 $this->mParent->getOutput()->addModules(
'mediawiki.htmlform.ooui' );
882 $this->mParent->getOutput()->addModules( $this->
getOOUIModules() );
896 $isDisabled = ( $this->mParams[
'disabled'] ?? false );
900 $labelValue = trim( $this->
getLabel() );
903 if ( $labelValue !==
'' && $labelValue !==
"\u{00A0}" && $labelValue !==
' ' ) {
905 $labelClasses = [
'cdx-label' ];
907 $labelClasses[] =
'cdx-label--disabled';
911 [
'cdx-label__description' ]
914 if ( $this->showOptionalFlag() ) {
915 $messageKey = $this->mParams[
'optional-message'] ??
'htmlform-optional-flag';
916 $optionalHtml = Html::rawElement(
918 [
'class' =>
'cdx-label__label__optional-flag' ],
919 ' ' . $this->
getMessage( $messageKey )->parse(),
923 $labelDiv = Html::rawElement(
'div', [
'class' => $labelClasses ],
925 Html::rawElement(
'label', [
'class' =>
'cdx-label__label' ] + $labelFor,
927 Html::rawElement(
'span', [
'class' =>
'cdx-label__label__text' ],
930 ) . $descriptionHtml,
942 $validationMessage =
'';
944 if ( $errors !==
'' ) {
945 $validationMessage = Html::rawElement(
'div', [
'class' =>
'cdx-field__validation-message' ],
953 $controlClasses = [
'cdx-field__control' ];
955 $controlClasses[] =
'cdx-field__control--has-help-text';
957 $control = Html::rawElement(
'div', [
'class' => $controlClasses ], $inputHtml );
961 "mw-htmlform-field-{$this->getClassName()}",
967 $fieldClasses[] =
'cdx-field--disabled';
969 $fieldAttributes = [];
971 if ( $this->mCondState ) {
973 $fieldClasses = array_merge( $fieldClasses, $this->mCondStateClass );
974 if ( $this->
isHiddenNoJs( $this->mParent->mFieldData ) ) {
975 $fieldClasses[] =
'mw-htmlform-hide-if-hidden-nojs';
976 } elseif ( $this->
isHidden( $this->mParent->mFieldData ) ) {
977 $fieldClasses[] =
'mw-htmlform-hide-if-hidden';
981 return Html::rawElement(
'div', [
'class' => $fieldClasses ] + $fieldAttributes,
982 $labelDiv . $control . $helptext . $validationMessage
986 private function showOptionalFlag(): bool {
987 $shouldShowOptionalFlag = $this->mParams[
'show-optional-flag'] ?? false;
988 if ( !$shouldShowOptionalFlag ) {
992 $isRequired = $this->mParams[
'required'] ??
false;
995 throw new \InvalidArgumentException(
'A field cannot be both optional and required.' );
1008 $name = explode(
'\\', static::class );
1009 return end( $name );
1041 return !$this->isHelpInline() && $this->getHelpMessages();
1066 [ $errors, ] = $this->getErrorsAndErrorClass( $value );
1067 return "\n" . $errors .
1068 $this->getLabelHtml() .
1069 $this->getInputHTML( $value ) .
1070 $this->getHelpTextHtmlRaw( $this->getHelpText() );
1081 [ $errors, ] = $this->getErrorsAndErrorClass( $value );
1082 return "\n" . $errors .
1083 $this->getLabelHtml() .
1085 $this->getInputHTML( $value ) .
1086 $this->getHelpTextHtmlDiv( $this->getHelpText() );
1097 if ( $helptext ===
null ) {
1101 $rowAttributes = [];
1102 if ( $this->mCondState ) {
1103 $rowAttributes[
'data-cond-state'] = FormatJson::encode( $this->parseCondStateForClient() );
1104 $rowAttributes[
'class'] = $this->mCondStateClass;
1107 $tdClasses = [
'htmlform-tip' ];
1108 if ( $this->mHelpClass !==
false ) {
1109 $tdClasses[] = $this->mHelpClass;
1111 return Html::rawElement(
'tr', $rowAttributes,
1112 Html::rawElement(
'td', [
'colspan' => 2,
'class' => $tdClasses ], $helptext )
1126 if ( $helptext ===
null ) {
1130 $wrapperAttributes = [
1131 'class' => array_merge( $cssClasses, [
'htmlform-tip' ] ),
1133 if ( $this->mHelpClass !==
false ) {
1134 $wrapperAttributes[
'class'][] = $this->mHelpClass;
1136 if ( $this->mCondState ) {
1137 $wrapperAttributes[
'data-cond-state'] = FormatJson::encode( $this->parseCondStateForClient() );
1138 $wrapperAttributes[
'class'] = array_merge( $wrapperAttributes[
'class'], $this->mCondStateClass );
1140 return Html::rawElement(
'div', $wrapperAttributes, $helptext );
1144 if ( $descriptionHtml === null ) {
1148 return Html::rawElement(
'span', [
'class' => $cssClasses ], $descriptionHtml );
1159 return $this->getHelpTextHtmlDiv( $helptext );
1162 private function getHelpMessages(): array {
1163 if ( isset( $this->mParams[
'help-message'] ) ) {
1164 return [ $this->mParams[
'help-message'] ];
1165 } elseif ( isset( $this->mParams[
'help-messages'] ) ) {
1166 return $this->mParams[
'help-messages'];
1167 } elseif ( isset( $this->mParams[
'help-raw'] ) ) {
1168 return [
new HtmlArmor( $this->mParams[
'help-raw'] ) ];
1169 } elseif ( isset( $this->mParams[
'help'] ) ) {
1171 return [
new HtmlArmor( $this->mParams[
'help'] ) ];
1186 foreach ( $this->getHelpMessages() as $msg ) {
1188 $html[] = HtmlArmor::getHtml( $msg );
1190 $msg = $this->getMessage( $msg );
1191 if ( $msg->exists() ) {
1192 $html[] = $msg->parse();
1197 return $html ? implode( $this->msg(
'word-separator' )->escaped(), $html ) :
null;
1200 private function getDescriptionMessages(): array {
1201 if ( isset( $this->mParams[
'description-message'] ) ) {
1202 return [ $this->mParams[
'description-message'] ];
1205 if ( isset( $this->mParams[
'description-messages'] ) ) {
1206 return $this->mParams[
'description-messages'];
1209 if ( isset( $this->mParams[
'description-raw'] ) ) {
1210 return [
new HtmlArmor( $this->mParams[
'description-raw'] ) ];
1225 foreach ( $this->getDescriptionMessages() as $msg ) {
1227 $html[] = HtmlArmor::getHtml( $msg );
1229 $msg = $this->getMessage( $msg );
1230 if ( $msg->exists() ) {
1231 $html[] = $msg->parse();
1236 return $html ? implode( $this->msg(
'word-separator' )->escaped(), $html ) : null;
1248 return $this->mParams[
'help-inline'] ??
true;
1264 $errors = $this->validate( $value, $this->mParent->mFieldData );
1266 if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
1270 return [ self::formatErrors( $errors ),
'mw-htmlform-invalid-input' ];
1281 $errors = $this->validate( $value, $this->mParent->mFieldData );
1283 if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
1287 if ( !is_array( $errors ) ) {
1288 $errors = [ $errors ];
1290 foreach ( $errors as &$error ) {
1291 if ( $error instanceof
Message ) {
1292 $error = $error->parse();
1304 return $this->mLabel ??
'';
1314 # Don't output a for= attribute for labels with no associated input.
1315 # Kind of hacky here, possibly we don't want these to be <label>s at all.
1316 $for = $this->needsLabel() ? [
'for' => $this->mID ] : [];
1318 $labelValue = trim( $this->getLabel() );
1319 $hasLabel = $labelValue !==
'' && $labelValue !==
"\u{00A0}" && $labelValue !==
' ';
1321 $displayFormat = $this->mParent->getDisplayFormat();
1322 $horizontalLabel = $this->mParams[
'horizontal-label'] ??
false;
1324 if ( $displayFormat ===
'table' ) {
1325 return Html::rawElement(
'td',
1326 [
'class' =>
'mw-label' ] + $cellAttributes,
1327 Html::rawElement(
'label', $for, $labelValue ) );
1328 } elseif ( $hasLabel || $this->mShowEmptyLabels ) {
1329 if ( $displayFormat ===
'div' && !$horizontalLabel ) {
1330 return Html::rawElement(
'div',
1331 [
'class' =>
'mw-label' ] + $cellAttributes,
1332 Html::rawElement(
'label', $for, $labelValue ) );
1334 return Html::rawElement(
'label', $for, $labelValue );
1346 return $this->mDefault ??
null;
1355 if ( empty( $this->mParams[
'tooltip'] ) ) {
1359 return Linker::tooltipAndAccesskeyAttribs( $this->mParams[
'tooltip'] );
1368 if ( empty( $this->mParams[
'tooltip'] ) ) {
1373 'title' => Linker::titleAttrib( $this->mParams[
'tooltip'] ),
1374 'accessKey' => Linker::accesskey( $this->mParams[
'tooltip'] ),
1386 static $boolAttribs = [
'disabled',
'required',
'autofocus',
'multiple',
'readonly' ];
1389 foreach ( $list as $key ) {
1390 if ( $key ===
'disabled' ) {
1391 if ( $this->isDisabledNoJs( $this->mParent->mFieldData ) ) {
1394 } elseif ( in_array( $key, $boolAttribs ) ) {
1395 if ( !empty( $this->mParams[$key] ) ) {
1398 } elseif ( isset( $this->mParams[$key] ) ) {
1399 $ret[$key] = $this->mParams[$key];
1415 private function lookupOptionsKeys( $options, $needsParse ) {
1417 $langCode = $this->mParent->getLanguageCode()->toBcp47Code();
1418 foreach ( $options as $key => $value ) {
1419 $msg = $this->msg( $key );
1420 $msgAsText = $needsParse ? $msg->parse() : $msg->plain();
1421 if ( array_key_exists( $msgAsText, $ret ) ) {
1422 LoggerFactory::getInstance(
'translation-problem' )->error(
1423 'The option that uses the message key {msg_key_one} has the same translation as ' .
1424 'another option in {lang}. This means that {msg_key_one} will not be used as an option.',
1426 'msg_key_one' => $key,
1427 'lang' => $langCode,
1432 $ret[$msgAsText] = is_array( $value )
1433 ? $this->lookupOptionsKeys( $value, $needsParse )
1447 if ( is_array( $array ) ) {
1448 return array_map( self::forceToStringRecursive( ... ), $array );
1450 return strval( $array );
1461 if ( $this->mOptions ===
false ) {
1462 if ( array_key_exists(
'options-messages', $this->mParams ) ) {
1463 $needsParse = $this->mParams[
'options-messages-parse'] ??
false;
1464 if ( $needsParse ) {
1465 $this->mOptionsLabelsNotFromMessage =
true;
1467 $this->mOptions = $this->lookupOptionsKeys( $this->mParams[
'options-messages'], $needsParse );
1468 } elseif ( array_key_exists(
'options', $this->mParams ) ) {
1469 $this->mOptionsLabelsNotFromMessage =
true;
1470 $this->mOptions = self::forceToStringRecursive( $this->mParams[
'options'] );
1471 } elseif ( array_key_exists(
'options-message', $this->mParams ) ) {
1472 $message = $this->getMessage( $this->mParams[
'options-message'] )->inContentLanguage()->plain();
1473 $this->mOptions = Html::listDropdownOptions( $message );
1475 $this->mOptions =
null;
1479 return $this->mOptions;
1488 $oldoptions = $this->getOptions();
1490 if ( $oldoptions ===
null ) {
1494 return Html::listDropdownOptionsOoui( $oldoptions );
1507 foreach ( $options as $value ) {
1508 if ( is_array( $value ) ) {
1509 $flatOpts = array_merge( $flatOpts, self::flattenOptions( $value ) );
1511 $flatOpts[] = $value;
1532 if ( is_array( $errors ) && count( $errors ) === 1 ) {
1533 $errors = array_shift( $errors );
1536 if ( is_array( $errors ) ) {
1537 foreach ( $errors as &$error ) {
1538 $error = Html::rawElement(
'li', [],
1542 $errors = Html::rawElement(
'ul', [], implode(
"\n", $errors ) );
1543 } elseif ( $errors instanceof
Message ) {
1544 $errors = $errors->parse();
1547 return Html::errorBox( $errors );
1557 $message = Message::newFromSpecifier( $value );
1558 $message->setContext( $this->mParent );
1570 return !empty( $this->mParams[
'nodata'] );
1582 return (
bool)$this->mCondState;
1597 return $this->mOptionsLabelsNotFromMessage
1598 ? $label : htmlspecialchars( $label, ENT_NOQUOTES );
1613 return $this->mOptionsLabelsNotFromMessage
1614 ? new \OOUI\HtmlSnippet( $label ) : $label;
1619class_alias( HTMLFormField::class,
'HTMLFormField' );
if(!defined('MW_SETUP_CALLBACK'))
Generic operation result class Has warning/error list, boolean status and arbitrary value.