17 protected $mLabel; # String label, as HTML. Set on construction.
31 protected $mCondState = [];
38 protected $mShowEmptyLabels =
true;
91 public function msg( $key, ...$params ) {
92 if ( $this->mParent ) {
93 return $this->mParent->msg( $key, ...$params );
132 if ( isset( $this->mParams[
'cloner'] ) ) {
133 $field = $this->mParams[
'cloner']->findNearestField( $this, $name );
139 if ( $backCompat && substr( $name, 0, 2 ) ===
'wp' &&
140 !$this->mParent->hasField( $name )
143 return $this->mParent->getField( substr( $name, 2 ) );
145 return $this->mParent->getField( $name );
162 if ( isset( $field->mParams[
'cloner'] ) ) {
163 $value = $field->mParams[
'cloner']->extractFieldData( $field, $alldata );
168 $value = $alldata[$field->mParams[
'fieldname']] ?? $field->getDefault();
172 if ( $asDisplay && $field instanceof
HTMLCheckField && ( $field->mParams[
'invert'] ??
false ) ) {
201 $origParams = $params;
202 $op = array_shift( $params );
207 if ( count( $params ) !== 1 ) {
208 throw new MWException(
"NOT takes exactly one parameter" );
216 foreach ( $params as $i => $p ) {
217 if ( !is_array( $p ) ) {
218 $type = gettype( $p );
219 throw new MWException(
"Expected array, found $type at index $i" );
227 if ( count( $params ) !== 2 ) {
228 throw new MWException(
"$op takes exactly two parameters" );
230 list( $name, $value ) = $params;
231 if ( !is_string( $name ) || !is_string( $value ) ) {
232 throw new MWException(
"Parameters for $op must be strings" );
241 "Invalid hide-if or disable-if specification for $this->mName: " .
242 $ex->getMessage() .
" in " . var_export( $origParams,
true ),
257 $origParams = $params;
258 $op = array_shift( $params );
259 $valueChk = [
'AND' =>
false,
'OR' =>
true,
'NAND' =>
false,
'NOR' =>
true ];
260 $valueRet = [
'AND' =>
true,
'OR' =>
false,
'NAND' =>
false,
'NOR' =>
true ];
267 foreach ( $params as $i => $p ) {
269 return !$valueRet[$op];
272 return $valueRet[$op];
279 list( $field, $value ) = $params;
283 return ( $value === $testValue );
285 return ( $value !== $testValue );
299 $origParams = $params;
300 $op = array_shift( $params );
308 foreach ( $params as $i => $p ) {
318 list( $name, $value ) = $params;
320 return [ $op, $field->getName(), $value ];
331 foreach ( $this->mCondState as
$type => $params ) {
346 if ( !( $this->mCondState && isset( $this->mCondState[
'hide'] ) ) ) {
362 if ( $this->mParams[
'disabled'] ??
false ) {
365 $hidden = $this->
isHidden( $alldata );
366 if ( !$this->mCondState || !isset( $this->mCondState[
'disable'] ) ) {
370 return $hidden || $this->
checkStateRecurse( $alldata, $this->mCondState[
'disable'] );
401 if ( $this->
isHidden( $alldata ) ) {
405 if ( isset( $this->mParams[
'required'] )
406 && $this->mParams[
'required'] !==
false
407 && ( $value ===
'' || $value ===
false )
409 return $this->
msg(
'htmlform-required' );
412 if ( isset( $this->mValidationCallback ) ) {
413 return ( $this->mValidationCallback )( $value, $alldata, $this->mParent );
427 public function filter( $value, $alldata ) {
428 if ( isset( $this->mFilterCallback ) ) {
429 $value = ( $this->mFilterCallback )( $value, $alldata, $this->mParent );
456 $this->mShowEmptyLabels = $show;
474 || $request->
getCheck(
'wpFormIdentifier' );
486 if ( $request->getCheck( $this->mName ) ) {
487 return $request->getText( $this->mName );
503 $this->mParams = $params;
505 if ( isset( $params[
'parent'] ) && $params[
'parent'] instanceof
HTMLForm ) {
506 $this->mParent = $params[
'parent'];
509 # Generate the label from a message, if possible
510 if ( isset( $params[
'label-message'] ) ) {
511 $this->mLabel = $this->
getMessage( $params[
'label-message'] )->parse();
512 } elseif ( isset( $params[
'label'] ) ) {
513 if ( $params[
'label'] ===
' ' || $params[
'label'] ===
"\u{00A0}" ) {
515 $this->mLabel =
"\u{00A0}";
517 $this->mLabel = htmlspecialchars( $params[
'label'] );
519 } elseif ( isset( $params[
'label-raw'] ) ) {
520 $this->mLabel = $params[
'label-raw'];
523 $this->mName =
"wp{$params['fieldname']}";
524 if ( isset( $params[
'name'] ) ) {
525 $this->mName = $params[
'name'];
528 if ( isset( $params[
'dir'] ) ) {
529 $this->mDir = $params[
'dir'];
532 $this->mID =
"mw-input-{$this->mName}";
534 if ( isset( $params[
'default'] ) ) {
535 $this->mDefault = $params[
'default'];
538 if ( isset( $params[
'id'] ) ) {
539 $this->mID = $params[
'id'];
542 if ( isset( $params[
'cssclass'] ) ) {
543 $this->mClass = $params[
'cssclass'];
546 if ( isset( $params[
'csshelpclass'] ) ) {
547 $this->mHelpClass = $params[
'csshelpclass'];
550 if ( isset( $params[
'validation-callback'] ) ) {
551 $this->mValidationCallback = $params[
'validation-callback'];
554 if ( isset( $params[
'filter-callback'] ) ) {
555 $this->mFilterCallback = $params[
'filter-callback'];
558 if ( isset( $params[
'hidelabel'] ) ) {
559 $this->mShowEmptyLabels =
false;
562 if ( isset( $params[
'hide-if'] ) && $params[
'hide-if'] ) {
564 $this->mCondState[
'hide'] = $params[
'hide-if'];
565 $this->mCondStateClass[] =
'mw-htmlform-hide-if';
567 if ( !( isset( $params[
'disabled'] ) && $params[
'disabled'] ) &&
568 isset( $params[
'disable-if'] ) && $params[
'disable-if']
571 $this->mCondState[
'disable'] = $params[
'disable-if'];
572 $this->mCondStateClass[] =
'mw-htmlform-disable-if';
590 $cellAttributes = [];
594 if ( !empty( $this->mParams[
'vertical-label'] ) ) {
595 $cellAttributes[
'colspan'] = 2;
596 $verticalLabel =
true;
598 $verticalLabel =
false;
603 $field = Html::rawElement(
605 [
'class' =>
'mw-input' ] + $cellAttributes,
606 $inputHtml .
"\n$errors"
609 if ( $this->mCondState ) {
611 $rowClasses .= implode(
' ', $this->mCondStateClass );
614 if ( $verticalLabel ) {
615 $html = Html::rawElement(
'tr',
616 $rowAttributes + [
'class' =>
"mw-htmlform-vertical-label $rowClasses" ], $label );
617 $html .= Html::rawElement(
'tr',
619 'class' =>
"mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
623 $html = Html::rawElement(
'tr',
625 'class' =>
"mw-htmlform-field-$fieldType {$this->mClass} $errorClass $rowClasses"
630 return $html . $helptext;
648 $cellAttributes = [];
653 'mw-htmlform-nolabel' => ( $label ===
'' )
656 $horizontalLabel = $this->mParams[
'horizontal-label'] ??
false;
658 if ( $horizontalLabel ) {
659 $field =
"\u{00A0}" . $inputHtml .
"\n$errors";
661 $field = Html::rawElement(
664 [
'class' => $outerDivClass ] + $cellAttributes,
665 $inputHtml .
"\n$errors"
668 $divCssClasses = [
"mw-htmlform-field-$fieldType",
669 $this->mClass, $this->mVFormClass, $errorClass ];
671 $wrapperAttributes = [
672 'class' => $divCssClasses,
674 if ( $this->mCondState ) {
676 $wrapperAttributes[
'class'] = array_merge( $wrapperAttributes[
'class'], $this->mCondStateClass );
678 $html = Html::rawElement(
'div', $wrapperAttributes, $label . $field );
696 if ( !$inputField ) {
701 new OOUI\Widget( [
'content' =>
new OOUI\HtmlSnippet( $this->
getDiv( $value ) ) ] ),
707 if ( is_string( $inputField ) ) {
711 $inputField =
new OOUI\Widget( [
'content' =>
new OOUI\HtmlSnippet( $inputField ) ] );
718 foreach ( $errors as &$error ) {
719 $error =
new OOUI\HtmlSnippet( $error );
723 'classes' => [
"mw-htmlform-field-$fieldType" ],
725 'help' => (
$help !==
null &&
$help !==
'' ) ?
new OOUI\HtmlSnippet(
$help ) :
null,
727 'infusable' => $infusable,
730 if ( $this->mClass !==
'' ) {
731 $config[
'classes'][] = $this->mClass;
734 $preloadModules =
false;
737 $preloadModules =
true;
738 $config[
'classes'][] =
'mw-htmlform-autoinfuse';
740 if ( $this->mCondState ) {
741 $config[
'classes'] = array_merge( $config[
'classes'], $this->mCondStateClass );
746 if ( $label && $label !==
"\u{00A0}" && $label !==
' ' ) {
747 $config[
'label'] =
new OOUI\HtmlSnippet( $label );
750 if ( $this->mCondState ) {
751 $preloadModules =
true;
757 if ( $preloadModules ) {
758 $this->mParent->getOutput()->addModules(
'mediawiki.htmlform.ooui' );
759 $this->mParent->getOutput()->addModules( $this->
getOOUIModules() );
773 $name = explode(
'\\', static::class );
834 $cellAttributes = [];
856 $this->mVFormClass =
' mw-ui-vform-field';
857 return $this->
getDiv( $value );
871 $cellAttributes = [];
874 $html =
"\n" . $errors .
875 $label .
"\u{00A0}" .
890 if ( $helptext ===
null ) {
895 if ( $this->mCondState ) {
897 $rowAttributes[
'class'] = $this->mCondStateClass;
900 $tdClasses = [
'htmlform-tip' ];
901 if ( $this->mHelpClass !==
false ) {
902 $tdClasses[] = $this->mHelpClass;
904 $row = Html::rawElement(
'td', [
'colspan' => 2,
'class' => $tdClasses ], $helptext );
905 $row = Html::rawElement(
'tr', $rowAttributes, $row );
919 if ( $helptext ===
null ) {
923 $wrapperAttributes = [
924 'class' => [
'htmlform-tip' ],
926 if ( $this->mHelpClass !==
false ) {
927 $wrapperAttributes[
'class'][] = $this->mHelpClass;
929 if ( $this->mCondState ) {
931 $wrapperAttributes[
'class'] = array_merge( $wrapperAttributes[
'class'], $this->mCondStateClass );
933 $div = Html::rawElement(
'div', $wrapperAttributes, $helptext );
958 if ( isset( $this->mParams[
'help-message'] ) ) {
959 $this->mParams[
'help-messages'] = [ $this->mParams[
'help-message'] ];
962 if ( isset( $this->mParams[
'help-messages'] ) ) {
963 foreach ( $this->mParams[
'help-messages'] as $msg ) {
966 if ( $msg->exists() ) {
967 if ( $helptext ===
null ) {
970 $helptext .= $this->
msg(
'word-separator' )->escaped();
972 $helptext .= $msg->parse();
975 } elseif ( isset( $this->mParams[
'help'] ) ) {
976 $helptext = $this->mParams[
'help'];
991 return $this->mParams[
'help-inline'] ??
true;
1007 $errors = $this->
validate( $value, $this->mParent->mFieldData );
1009 if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
1013 $errors = self::formatErrors( $errors );
1014 $errorClass =
'mw-htmlform-invalid-input';
1017 return [ $errors, $errorClass ];
1028 $errors = $this->
validate( $value, $this->mParent->mFieldData );
1030 if ( is_bool( $errors ) || !$this->mParent->wasSubmitted() ) {
1034 if ( !is_array( $errors ) ) {
1035 $errors = [ $errors ];
1037 foreach ( $errors as &$error ) {
1038 if ( $error instanceof
Message ) {
1039 $error = $error->parse();
1051 return $this->mLabel ??
'';
1061 # Don't output a for= attribute for labels with no associated input.
1062 # Kind of hacky here, possibly we don't want these to be <label>s at all.
1066 $for[
'for'] = $this->mID;
1069 $labelValue = trim( $this->
getLabel() );
1071 if ( $labelValue !==
"\u{00A0}" && $labelValue !==
' ' && $labelValue !==
'' ) {
1075 $displayFormat = $this->mParent->getDisplayFormat();
1077 $horizontalLabel = $this->mParams[
'horizontal-label'] ??
false;
1079 if ( $displayFormat ===
'table' ) {
1081 Html::rawElement(
'td',
1082 [
'class' =>
'mw-label' ] + $cellAttributes,
1083 Html::rawElement(
'label', $for, $labelValue ) );
1084 } elseif ( $hasLabel || $this->mShowEmptyLabels ) {
1085 if ( $displayFormat ===
'div' && !$horizontalLabel ) {
1087 Html::rawElement(
'div',
1088 [
'class' =>
'mw-label' ] + $cellAttributes,
1089 Html::rawElement(
'label', $for, $labelValue ) );
1091 $html = Html::rawElement(
'label', $for, $labelValue );
1103 return $this->mDefault ??
null;
1112 if ( empty( $this->mParams[
'tooltip'] ) ) {
1125 if ( empty( $this->mParams[
'tooltip'] ) ) {
1143 static $boolAttribs = [
'disabled',
'required',
'autofocus',
'multiple',
'readonly' ];
1146 foreach ( $list as $key ) {
1147 if ( in_array( $key, $boolAttribs ) ) {
1148 if ( !empty( $this->mParams[$key] ) ) {
1151 } elseif ( isset( $this->mParams[$key] ) ) {
1152 $ret[$key] = $this->mParams[$key];
1168 private function lookupOptionsKeys( $options, $needsParse ) {
1170 foreach ( $options as $key => $value ) {
1171 $msg = $this->msg( $key );
1172 $key = $needsParse ? $msg->parse() : $msg->plain();
1173 $ret[$key] = is_array( $value )
1174 ? $this->lookupOptionsKeys( $value, $needsParse )
1188 if ( is_array( $array ) ) {
1189 return array_map( [ __CLASS__,
'forceToStringRecursive' ], $array );
1191 return strval( $array );
1202 if ( $this->mOptions ===
false ) {
1203 if ( array_key_exists(
'options-messages', $this->mParams ) ) {
1204 $needsParse = $this->mParams[
'options-messages-parse'] ??
false;
1205 if ( $needsParse ) {
1206 $this->mOptionsLabelsNotFromMessage =
true;
1208 $this->mOptions = $this->lookupOptionsKeys( $this->mParams[
'options-messages'], $needsParse );
1209 } elseif ( array_key_exists(
'options', $this->mParams ) ) {
1210 $this->mOptionsLabelsNotFromMessage =
true;
1211 $this->mOptions = self::forceToStringRecursive( $this->mParams[
'options'] );
1212 } elseif ( array_key_exists(
'options-message', $this->mParams ) ) {
1213 $message = $this->
getMessage( $this->mParams[
'options-message'] )->inContentLanguage()->plain();
1214 $this->mOptions = Xml::listDropDownOptions( $message );
1216 $this->mOptions =
null;
1220 return $this->mOptions;
1231 if ( $oldoptions ===
null ) {
1235 return Xml::listDropDownOptionsOoui( $oldoptions );
1248 foreach ( $options as $value ) {
1249 if ( is_array( $value ) ) {
1250 $flatOpts = array_merge( $flatOpts, self::flattenOptions( $value ) );
1252 $flatOpts[] = $value;
1273 if ( is_array( $errors ) && count( $errors ) === 1 ) {
1274 $errors = array_shift( $errors );
1277 if ( is_array( $errors ) ) {
1279 foreach ( $errors as $error ) {
1280 if ( $error instanceof
Message ) {
1281 $lines[] = Html::rawElement(
'li', [], $error->parse() );
1283 $lines[] = Html::rawElement(
'li', [], $error );
1287 $errors = Html::rawElement(
'ul', [], implode(
"\n",
$lines ) );
1289 if ( $errors instanceof
Message ) {
1290 $errors = $errors->parse();
1294 return Html::errorBox( $errors );
1306 if ( $this->mParent ) {
1307 $message->setContext( $this->mParent );
1321 return !empty( $this->mParams[
'nodata'] );
1332 if ( $this->mCondState ) {
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
static accesskey( $name, $localizer=null)
Given the id of an interface element, constructs the appropriate accesskey attribute from the system ...
static titleAttrib( $name, $options=null, array $msgParams=[], $localizer=null)
Given the id of an interface element, constructs the appropriate title attribute from the system mess...
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[], $options=null, $localizer=null, $user=null, $config=null, $relevantTitle=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").
wasPosted()
Returns true if the present request was reached by a POST operation, false otherwise (GET,...
if(!file_exists( $CREDITS)) $lines