MediaWiki 1.41.2
HTMLForm.php
Go to the documentation of this file.
1<?php
2
24use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
34
158class HTMLForm extends ContextSource {
159 use ProtectedHookAccessorTrait;
160
162 public static $typeMappings = [
163 'api' => HTMLApiField::class,
164 'text' => HTMLTextField::class,
165 'textwithbutton' => HTMLTextFieldWithButton::class,
166 'textarea' => HTMLTextAreaField::class,
167 'select' => HTMLSelectField::class,
168 'combobox' => HTMLComboboxField::class,
169 'radio' => HTMLRadioField::class,
170 'multiselect' => HTMLMultiSelectField::class,
171 'limitselect' => HTMLSelectLimitField::class,
172 'check' => HTMLCheckField::class,
173 'toggle' => HTMLCheckField::class,
174 'int' => HTMLIntField::class,
175 'file' => HTMLFileField::class,
176 'float' => HTMLFloatField::class,
177 'info' => HTMLInfoField::class,
178 'selectorother' => HTMLSelectOrOtherField::class,
179 'selectandother' => HTMLSelectAndOtherField::class,
180 'namespaceselect' => HTMLSelectNamespace::class,
181 'namespaceselectwithbutton' => HTMLSelectNamespaceWithButton::class,
182 'tagfilter' => HTMLTagFilter::class,
183 'sizefilter' => HTMLSizeFilterField::class,
184 'submit' => HTMLSubmitField::class,
185 'hidden' => HTMLHiddenField::class,
186 'edittools' => HTMLEditTools::class,
187 'checkmatrix' => HTMLCheckMatrix::class,
188 'cloner' => HTMLFormFieldCloner::class,
189 'autocompleteselect' => HTMLAutoCompleteSelectField::class,
190 'language' => HTMLSelectLanguageField::class,
191 'date' => HTMLDateTimeField::class,
192 'time' => HTMLDateTimeField::class,
193 'datetime' => HTMLDateTimeField::class,
194 'expiry' => HTMLExpiryField::class,
195 'timezone' => HTMLTimezoneField::class,
196 // HTMLTextField will output the correct type="" attribute automagically.
197 // There are about four zillion other HTML5 input types, like range, but
198 // we don't use those at the moment, so no point in adding all of them.
199 'email' => HTMLTextField::class,
200 'password' => HTMLTextField::class,
201 'url' => HTMLTextField::class,
202 'title' => HTMLTitleTextField::class,
203 'user' => HTMLUserTextField::class,
204 'tagmultiselect' => HTMLTagMultiselectField::class,
205 'usersmultiselect' => HTMLUsersMultiselectField::class,
206 'titlesmultiselect' => HTMLTitlesMultiselectField::class,
207 'namespacesmultiselect' => HTMLNamespacesMultiselectField::class,
208 ];
209
211
213
215 protected $mFlatFields = [];
216 protected $mFieldTree = [];
217 protected $mShowReset = false;
218 protected $mShowSubmit = true;
220 protected $mSubmitFlags = [ 'primary', 'progressive' ];
221 protected $mShowCancel = false;
222 protected $mCancelTarget;
223
230
231 protected $mPre = '';
232 protected $mHeader = '';
233 protected $mFooter = '';
234 protected $mSectionHeaders = [];
235 protected $mSectionFooters = [];
236 protected $mPost = '';
237 protected $mId;
238 protected $mName;
239 protected $mTableId = '';
240
241 protected $mSubmitID;
242 protected $mSubmitName;
243 protected $mSubmitText;
245
247 protected $mSingleForm = false;
248
250 protected $mTitle;
251 protected $mMethod = 'post';
252 protected $mWasSubmitted = false;
253
259 protected $mAction = false;
260
266 protected $mCollapsible = false;
267
273 protected $mCollapsed = false;
274
280 protected $mAutocomplete = null;
281
282 protected $mUseMultipart = false;
287 protected $mHiddenFields = [];
292 protected $mButtons = [];
293
294 protected $mWrapperLegend = false;
295 protected $mWrapperAttributes = [];
296
301 protected $mTokenSalt = '';
302
311 protected $mSubSectionBeforeFields = true;
312
318 protected $displayFormat = 'table';
319
324 protected $availableDisplayFormats = [
325 'table',
326 'div',
327 'raw',
328 'inline',
329 ];
330
335 protected $availableSubclassDisplayFormats = [
336 'vform',
337 'codex',
338 'ooui',
339 ];
340
345 private $hiddenTitleAddedToForm = false;
346
360 public static function factory(
361 $displayFormat, $descriptor, IContextSource $context, $messagePrefix = ''
362 ) {
363 switch ( $displayFormat ) {
364 case 'codex':
365 return new CodexHTMLForm( $descriptor, $context, $messagePrefix );
366 case 'vform':
367 return new VFormHTMLForm( $descriptor, $context, $messagePrefix );
368 case 'ooui':
369 return new OOUIHTMLForm( $descriptor, $context, $messagePrefix );
370 default:
371 $form = new self( $descriptor, $context, $messagePrefix );
372 $form->setDisplayFormat( $displayFormat );
373 return $form;
374 }
375 }
376
388 public function __construct(
389 $descriptor, IContextSource $context, $messagePrefix = ''
390 ) {
391 $this->setContext( $context );
392 $this->mMessagePrefix = $messagePrefix;
393
394 // Evil hack for mobile :(
395 if (
396 !$this->getConfig()->get( MainConfigNames::HTMLFormAllowTableFormat )
397 && $this->displayFormat === 'table'
398 ) {
399 $this->displayFormat = 'div';
400 }
401
402 $this->addFields( $descriptor );
403 }
404
414 public function addFields( $descriptor ) {
415 $loadedDescriptor = [];
416
417 foreach ( $descriptor as $fieldname => $info ) {
418 $section = $info['section'] ?? '';
419
420 if ( isset( $info['type'] ) && $info['type'] === 'file' ) {
421 $this->mUseMultipart = true;
422 }
423
424 $field = static::loadInputFromParameters( $fieldname, $info, $this );
425
426 $setSection =& $loadedDescriptor;
427 if ( $section ) {
428 foreach ( explode( '/', $section ) as $newName ) {
429 $setSection[$newName] ??= [];
430 $setSection =& $setSection[$newName];
431 }
432 }
433
434 $setSection[$fieldname] = $field;
435 $this->mFlatFields[$fieldname] = $field;
436 }
437
438 $this->mFieldTree = array_merge_recursive( $this->mFieldTree, $loadedDescriptor );
439
440 return $this;
441 }
442
447 public function hasField( $fieldname ) {
448 return isset( $this->mFlatFields[$fieldname] );
449 }
450
456 public function getField( $fieldname ) {
457 if ( !$this->hasField( $fieldname ) ) {
458 throw new DomainException( __METHOD__ . ': no field named ' . $fieldname );
459 }
460 return $this->mFlatFields[$fieldname];
461 }
462
473 public function setDisplayFormat( $format ) {
474 if (
475 in_array( $format, $this->availableSubclassDisplayFormats, true ) ||
476 in_array( $this->displayFormat, $this->availableSubclassDisplayFormats, true )
477 ) {
478 throw new MWException( 'Cannot change display format after creation, ' .
479 'use HTMLForm::factory() instead' );
480 }
481
482 if ( !in_array( $format, $this->availableDisplayFormats, true ) ) {
483 throw new MWException( 'Display format must be one of ' .
484 print_r(
485 array_merge(
486 $this->availableDisplayFormats,
487 $this->availableSubclassDisplayFormats
488 ),
489 true
490 ) );
491 }
492
493 // Evil hack for mobile :(
494 if ( !$this->getConfig()->get( MainConfigNames::HTMLFormAllowTableFormat ) &&
495 $format === 'table' ) {
496 $format = 'div';
497 }
498
499 $this->displayFormat = $format;
500
501 return $this;
502 }
503
509 public function getDisplayFormat() {
510 return $this->displayFormat;
511 }
512
530 public static function getClassFromDescriptor( $fieldname, &$descriptor ) {
531 if ( isset( $descriptor['class'] ) ) {
532 $class = $descriptor['class'];
533 } elseif ( isset( $descriptor['type'] ) ) {
534 $class = static::$typeMappings[$descriptor['type']];
535 $descriptor['class'] = $class;
536 } else {
537 $class = null;
538 }
539
540 if ( !$class ) {
541 throw new MWException( "Descriptor with no class for $fieldname: "
542 . print_r( $descriptor, true ) );
543 }
544
545 return $class;
546 }
547
561 public static function loadInputFromParameters( $fieldname, $descriptor,
562 HTMLForm $parent = null
563 ) {
564 $class = static::getClassFromDescriptor( $fieldname, $descriptor );
565
566 $descriptor['fieldname'] = $fieldname;
567 if ( $parent ) {
568 $descriptor['parent'] = $parent;
569 }
570
571 # @todo This will throw a fatal error whenever someone try to use
572 # 'class' to feed a CSS class instead of 'cssclass'. Would be
573 # great to avoid the fatal error and show a nice error.
574 return new $class( $descriptor );
575 }
576
586 public function prepareForm() {
587 # Load data from the request.
588 if (
589 $this->mFormIdentifier === null ||
590 $this->getRequest()->getVal( 'wpFormIdentifier' ) === $this->mFormIdentifier ||
591 $this->mSingleForm && $this->getMethod() === 'get'
592 ) {
593 $this->loadFieldData();
594 } else {
595 $this->mFieldData = [];
596 }
597
598 return $this;
599 }
600
605 public function tryAuthorizedSubmit() {
606 $result = false;
607
608 if ( $this->mFormIdentifier === null ) {
609 $identOkay = true;
610 } else {
611 $identOkay = $this->getRequest()->getVal( 'wpFormIdentifier' ) === $this->mFormIdentifier;
612 }
613
614 $tokenOkay = false;
615 if ( $this->getMethod() !== 'post' ) {
616 $tokenOkay = true; // no session check needed
617 } elseif ( $this->getRequest()->wasPosted() ) {
618 $editToken = $this->getRequest()->getVal( 'wpEditToken' );
619 if ( $this->getUser()->isRegistered() || $editToken !== null ) {
620 // Session tokens for logged-out users have no security value.
621 // However, if the user gave one, check it in order to give a nice
622 // "session expired" error instead of "permission denied" or such.
623 $tokenOkay = $this->getUser()->matchEditToken( $editToken, $this->mTokenSalt );
624 } else {
625 $tokenOkay = true;
626 }
627 }
628
629 if ( $tokenOkay && $identOkay ) {
630 $this->mWasSubmitted = true;
631 $result = $this->trySubmit();
632 }
633
634 return $result;
635 }
636
644 public function show() {
645 $this->prepareForm();
646
647 $result = $this->tryAuthorizedSubmit();
648 if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) {
649 return $result;
650 }
651
652 $this->displayForm( $result );
653
654 return false;
655 }
656
662 public function showAlways() {
663 $this->prepareForm();
664
665 $result = $this->tryAuthorizedSubmit();
666
667 $this->displayForm( $result );
668
669 return $result;
670 }
671
684 public function trySubmit() {
685 $valid = true;
686 $hoistedErrors = Status::newGood();
687 if ( $this->mValidationErrorMessage ) {
688 foreach ( $this->mValidationErrorMessage as $error ) {
689 $hoistedErrors->fatal( ...$error );
690 }
691 } else {
692 $hoistedErrors->fatal( 'htmlform-invalid-input' );
693 }
694
695 $this->mWasSubmitted = true;
696
697 # Check for cancelled submission
698 foreach ( $this->mFlatFields as $fieldname => $field ) {
699 if ( !array_key_exists( $fieldname, $this->mFieldData ) ) {
700 continue;
701 }
702 if ( $field->cancelSubmit( $this->mFieldData[$fieldname], $this->mFieldData ) ) {
703 $this->mWasSubmitted = false;
704 return false;
705 }
706 }
707
708 # Check for validation
709 $hasNonDefault = false;
710 foreach ( $this->mFlatFields as $fieldname => $field ) {
711 if ( !array_key_exists( $fieldname, $this->mFieldData ) ) {
712 continue;
713 }
714 $hasNonDefault = $hasNonDefault || $this->mFieldData[$fieldname] !== $field->getDefault();
715 if ( $field->isDisabled( $this->mFieldData ) ) {
716 continue;
717 }
718 $res = $field->validate( $this->mFieldData[$fieldname], $this->mFieldData );
719 if ( $res !== true ) {
720 $valid = false;
721 if ( $res !== false && !$field->canDisplayErrors() ) {
722 if ( is_string( $res ) ) {
723 $hoistedErrors->fatal( 'rawmessage', $res );
724 } else {
725 $hoistedErrors->fatal( $res );
726 }
727 }
728 }
729 }
730
731 if ( !$valid ) {
732 // Treat as not submitted if got nothing from the user on GET forms.
733 if ( !$hasNonDefault && $this->getMethod() === 'get' &&
734 ( $this->mFormIdentifier === null ||
735 $this->getRequest()->getCheck( 'wpFormIdentifier' ) )
736 ) {
737 $this->mWasSubmitted = false;
738 return false;
739 }
740 return $hoistedErrors;
741 }
742
743 $callback = $this->mSubmitCallback;
744 if ( !is_callable( $callback ) ) {
745 throw new MWException( 'HTMLForm: no submit callback provided. Use ' .
746 'setSubmitCallback() to set one.' );
747 }
748
749 $data = $this->filterDataForSubmit( $this->mFieldData );
750
751 $res = call_user_func( $callback, $data, $this );
752 if ( $res === false ) {
753 $this->mWasSubmitted = false;
754 } elseif ( $res instanceof StatusValue ) {
755 // DWIM - callbacks are not supposed to return a StatusValue but it's easy to mix up.
756 $res = Status::wrap( $res );
757 }
758
759 return $res;
760 }
761
773 public function wasSubmitted() {
774 return $this->mWasSubmitted;
775 }
776
787 public function setSubmitCallback( $cb ) {
788 $this->mSubmitCallback = $cb;
789
790 return $this;
791 }
792
802 public function setValidationErrorMessage( $msg ) {
803 $this->mValidationErrorMessage = $msg;
804
805 return $this;
806 }
807
816 public function setIntro( $msg ) {
817 return $this->setPreHtml( $msg );
818 }
819
828 public function setPreHtml( $html ) {
829 $this->mPre = $html;
830
831 return $this;
832 }
833
842 public function addPreHtml( $html ) {
843 $this->mPre .= $html;
844
845 return $this;
846 }
847
854 public function getPreHtml() {
855 return $this->mPre;
856 }
857
866 public function setPreText( $msg ) {
867 return $this->setPreHtml( $msg );
868 }
869
878 public function addPreText( $msg ) {
879 return $this->addPreHtml( $msg );
880 }
881
889 public function getPreText() {
890 return $this->getPreHtml();
891 }
892
902 public function addHeaderHtml( $html, $section = null ) {
903 if ( $section === null ) {
904 $this->mHeader .= $html;
905 } else {
906 $this->mSectionHeaders[$section] ??= '';
907 $this->mSectionHeaders[$section] .= $html;
908 }
909
910 return $this;
911 }
912
922 public function setHeaderHtml( $html, $section = null ) {
923 if ( $section === null ) {
924 $this->mHeader = $html;
925 } else {
926 $this->mSectionHeaders[$section] = $html;
927 }
928
929 return $this;
930 }
931
940 public function getHeaderHtml( $section = null ) {
941 return $section ? $this->mSectionHeaders[$section] ?? '' : $this->mHeader;
942 }
943
953 public function addHeaderText( $msg, $section = null ) {
954 return $this->addHeaderHtml( $msg, $section );
955 }
956
967 public function setHeaderText( $msg, $section = null ) {
968 return $this->setHeaderHtml( $msg, $section );
969 }
970
980 public function getHeaderText( $section = null ) {
981 return $this->getHeaderHtml( $section );
982 }
983
993 public function addFooterHtml( $html, $section = null ) {
994 if ( $section === null ) {
995 $this->mFooter .= $html;
996 } else {
997 $this->mSectionFooters[$section] ??= '';
998 $this->mSectionFooters[$section] .= $html;
999 }
1000
1001 return $this;
1002 }
1003
1013 public function setFooterHtml( $html, $section = null ) {
1014 if ( $section === null ) {
1015 $this->mFooter = $html;
1016 } else {
1017 $this->mSectionFooters[$section] = $html;
1018 }
1019
1020 return $this;
1021 }
1022
1030 public function getFooterHtml( $section = null ) {
1031 return $section ? $this->mSectionFooters[$section] ?? '' : $this->mFooter;
1032 }
1033
1043 public function addFooterText( $msg, $section = null ) {
1044 return $this->addFooterHtml( $msg, $section );
1045 }
1046
1057 public function setFooterText( $msg, $section = null ) {
1058 return $this->setFooterHtml( $msg, $section );
1059 }
1060
1069 public function getFooterText( $section = null ) {
1070 return $this->getFooterHtml( $section );
1071 }
1072
1081 public function addPostHtml( $html ) {
1082 $this->mPost .= $html;
1083
1084 return $this;
1085 }
1086
1095 public function setPostHtml( $html ) {
1096 $this->mPost = $html;
1097
1098 return $this;
1099 }
1100
1107 public function getPostHtml() {
1108 return $this->mPost;
1109 }
1110
1119 public function addPostText( $msg ) {
1120 return $this->addPostHtml( $msg );
1121 }
1122
1131 public function setPostText( $msg ) {
1132 return $this->setPostHtml( $msg );
1133 }
1134
1145 public function addHiddenField( $name, $value, array $attribs = [] ) {
1146 if ( !is_array( $value ) ) {
1147 // Per WebRequest::getVal: Array values are discarded for security reasons.
1148 $attribs += [ 'name' => $name ];
1149 $this->mHiddenFields[] = [ $value, $attribs ];
1150 }
1151
1152 return $this;
1153 }
1154
1166 public function addHiddenFields( array $fields ) {
1167 foreach ( $fields as $name => $value ) {
1168 if ( is_array( $value ) ) {
1169 // Per WebRequest::getVal: Array values are discarded for security reasons.
1170 continue;
1171 }
1172 $this->mHiddenFields[] = [ $value, [ 'name' => $name ] ];
1173 }
1174
1175 return $this;
1176 }
1177
1201 public function addButton( $data ) {
1202 if ( !is_array( $data ) ) {
1203 $args = func_get_args();
1204 if ( count( $args ) < 2 || count( $args ) > 4 ) {
1205 throw new InvalidArgumentException(
1206 'Incorrect number of arguments for deprecated calling style'
1207 );
1208 }
1209 $data = [
1210 'name' => $args[0],
1211 'value' => $args[1],
1212 'id' => $args[2] ?? null,
1213 'attribs' => $args[3] ?? null,
1214 ];
1215 } else {
1216 if ( !isset( $data['name'] ) ) {
1217 throw new InvalidArgumentException( 'A name is required' );
1218 }
1219 if ( !isset( $data['value'] ) ) {
1220 throw new InvalidArgumentException( 'A value is required' );
1221 }
1222 }
1223 $this->mButtons[] = $data + [
1224 'id' => null,
1225 'attribs' => null,
1226 'flags' => null,
1227 'framed' => true,
1228 ];
1229
1230 return $this;
1231 }
1232
1242 public function setTokenSalt( $salt ) {
1243 $this->mTokenSalt = $salt;
1244
1245 return $this;
1246 }
1247
1262 public function displayForm( $submitResult ) {
1263 $this->getOutput()->addHTML( $this->getHTML( $submitResult ) );
1264 }
1265
1270 private function getHiddenTitle(): string {
1271 if ( $this->hiddenTitleAddedToForm ) {
1272 return '';
1273 }
1274
1275 $html = '';
1276 if ( $this->getMethod() === 'post' ||
1277 $this->getAction() === $this->getConfig()->get( MainConfigNames::Script )
1278 ) {
1279 $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
1280 }
1281 $this->hiddenTitleAddedToForm = true;
1282 return $html;
1283 }
1284
1295 public function getHTML( $submitResult ) {
1296 # For good measure (it is the default)
1297 $this->getOutput()->setPreventClickjacking( true );
1298 $this->getOutput()->addModules( 'mediawiki.htmlform' );
1299 $this->getOutput()->addModuleStyles( 'mediawiki.htmlform.styles' );
1300
1301 if ( $this->mCollapsible ) {
1302 // Preload jquery.makeCollapsible for mediawiki.htmlform
1303 $this->getOutput()->addModules( 'jquery.makeCollapsible' );
1304 }
1305
1306 $html = $this->getErrorsOrWarnings( $submitResult, 'error' )
1307 . $this->getErrorsOrWarnings( $submitResult, 'warning' )
1308 . $this->getHeaderText()
1309 . $this->getHiddenTitle()
1310 . $this->getBody()
1311 . $this->getHiddenFields()
1312 . $this->getButtons()
1313 . $this->getFooterText();
1314
1315 return $this->mPre . $this->wrapForm( $html ) . $this->mPost;
1316 }
1317
1325 public function setCollapsibleOptions( $collapsedByDefault = false ) {
1326 $this->mCollapsible = true;
1327 $this->mCollapsed = $collapsedByDefault;
1328 return $this;
1329 }
1330
1336 protected function getFormAttributes() {
1337 # Use multipart/form-data
1338 $encType = $this->mUseMultipart
1339 ? 'multipart/form-data'
1340 : 'application/x-www-form-urlencoded';
1341 # Attributes
1342 $attribs = [
1343 'class' => 'mw-htmlform',
1344 'action' => $this->getAction(),
1345 'method' => $this->getMethod(),
1346 'enctype' => $encType,
1347 ];
1348 if ( $this->mId ) {
1349 $attribs['id'] = $this->mId;
1350 }
1351 if ( is_string( $this->mAutocomplete ) ) {
1352 $attribs['autocomplete'] = $this->mAutocomplete;
1353 }
1354 if ( $this->mName ) {
1355 $attribs['name'] = $this->mName;
1356 }
1357 if ( $this->needsJSForHtml5FormValidation() ) {
1358 $attribs['novalidate'] = true;
1359 }
1360 return $attribs;
1361 }
1362
1370 public function wrapForm( $html ) {
1371 # Include a <fieldset> wrapper for style, if requested.
1372 if ( $this->mWrapperLegend !== false ) {
1373 $legend = is_string( $this->mWrapperLegend ) ? $this->mWrapperLegend : false;
1374 $html = Xml::fieldset( $legend, $html, $this->mWrapperAttributes );
1375 }
1376
1377 return Html::rawElement(
1378 'form',
1379 $this->getFormAttributes(),
1380 $html
1381 );
1382 }
1383
1388 public function getHiddenFields() {
1389 $html = '';
1390
1391 // add the title as a hidden file if it hasn't been added yet and if it is necessary
1392 // added for backward compatibility with the previous version of this public method
1393 $html .= $this->getHiddenTitle();
1394
1395 if ( $this->mFormIdentifier !== null ) {
1396 $html .= Html::hidden(
1397 'wpFormIdentifier',
1398 $this->mFormIdentifier
1399 ) . "\n";
1400 }
1401 if ( $this->getMethod() === 'post' ) {
1402 $html .= Html::hidden(
1403 'wpEditToken',
1404 $this->getUser()->getEditToken( $this->mTokenSalt ),
1405 [ 'id' => 'wpEditToken' ]
1406 ) . "\n";
1407 }
1408
1409 foreach ( $this->mHiddenFields as [ $value, $attribs ] ) {
1410 $html .= Html::hidden( $attribs['name'], $value, $attribs ) . "\n";
1411 }
1412
1413 return $html;
1414 }
1415
1421 public function getButtons() {
1422 $buttons = '';
1423 $useMediaWikiUIEverywhere =
1424 $this->getConfig()->get( MainConfigNames::UseMediaWikiUIEverywhere );
1425
1426 if ( $this->mShowSubmit ) {
1427 $attribs = [];
1428
1429 if ( isset( $this->mSubmitID ) ) {
1430 $attribs['id'] = $this->mSubmitID;
1431 }
1432
1433 if ( isset( $this->mSubmitName ) ) {
1434 $attribs['name'] = $this->mSubmitName;
1435 }
1436
1437 if ( isset( $this->mSubmitTooltip ) ) {
1438 $attribs += Linker::tooltipAndAccesskeyAttribs( $this->mSubmitTooltip );
1439 }
1440
1441 $attribs['class'] = [ 'mw-htmlform-submit' ];
1442
1443 if ( $useMediaWikiUIEverywhere ) {
1444 foreach ( $this->mSubmitFlags as $flag ) {
1445 $attribs['class'][] = 'mw-ui-' . $flag;
1446 }
1447 $attribs['class'][] = 'mw-ui-button';
1448 }
1449
1450 $buttons .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n";
1451 }
1452
1453 if ( $this->mShowReset ) {
1454 $buttons .= Html::element(
1455 'input',
1456 [
1457 'type' => 'reset',
1458 'value' => $this->msg( 'htmlform-reset' )->text(),
1459 'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button' : null,
1460 ]
1461 ) . "\n";
1462 }
1463
1464 if ( $this->mShowCancel ) {
1465 $target = $this->getCancelTargetURL();
1466 $buttons .= Html::element(
1467 'a',
1468 [
1469 'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button' : null,
1470 'href' => $target,
1471 ],
1472 $this->msg( 'cancel' )->text()
1473 ) . "\n";
1474 }
1475
1476 foreach ( $this->mButtons as $button ) {
1477 $attrs = [
1478 'type' => 'submit',
1479 'name' => $button['name'],
1480 'value' => $button['value']
1481 ];
1482
1483 if ( isset( $button['label-message'] ) ) {
1484 $label = $this->getMessage( $button['label-message'] )->parse();
1485 } elseif ( isset( $button['label'] ) ) {
1486 $label = htmlspecialchars( $button['label'] );
1487 } elseif ( isset( $button['label-raw'] ) ) {
1488 $label = $button['label-raw'];
1489 } else {
1490 $label = htmlspecialchars( $button['value'] );
1491 }
1492
1493 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset Always set in self::addButton
1494 if ( $button['attribs'] ) {
1495 // @phan-suppress-next-line PhanTypePossiblyInvalidDimOffset Always set in self::addButton
1496 $attrs += $button['attribs'];
1497 }
1498
1499 if ( isset( $button['id'] ) ) {
1500 $attrs['id'] = $button['id'];
1501 }
1502
1503 if ( $useMediaWikiUIEverywhere ) {
1504 $attrs['class'] = (array)( $attrs['class'] ?? [] );
1505 $attrs['class'][] = 'mw-ui-button';
1506 }
1507
1508 $buttons .= Html::rawElement( 'button', $attrs, $label ) . "\n";
1509 }
1510
1511 if ( !$buttons ) {
1512 return '';
1513 }
1514
1515 return Html::rawElement( 'span',
1516 [ 'class' => 'mw-htmlform-submit-buttons' ], "\n$buttons" ) . "\n";
1517 }
1518
1524 public function getBody() {
1525 return $this->displaySection( $this->mFieldTree, $this->mTableId );
1526 }
1527
1537 public function getErrorsOrWarnings( $elements, $elementsType ) {
1538 if ( !in_array( $elementsType, [ 'error', 'warning' ], true ) ) {
1539 throw new DomainException( $elementsType . ' is not a valid type.' );
1540 }
1541 $elementstr = false;
1542 if ( $elements instanceof Status ) {
1543 [ $errorStatus, $warningStatus ] = $elements->splitByErrorType();
1544 $status = $elementsType === 'error' ? $errorStatus : $warningStatus;
1545 if ( $status->isGood() ) {
1546 $elementstr = '';
1547 } else {
1548 $elementstr = $status
1549 ->getMessage()
1550 ->setContext( $this )
1551 ->setInterfaceMessageFlag( true )
1552 ->parse();
1553 }
1554 } elseif ( $elementsType === 'error' ) {
1555 if ( is_array( $elements ) ) {
1556 $elementstr = $this->formatErrors( $elements );
1557 } elseif ( $elements && $elements !== true ) {
1558 $elementstr = (string)$elements;
1559 }
1560 }
1561
1562 if ( !$elementstr ) {
1563 return '';
1564 } elseif ( $elementsType === 'error' ) {
1565 return Html::errorBox( $elementstr );
1566 } else { // $elementsType can only be 'warning'
1567 return Html::warningBox( $elementstr );
1568 }
1569 }
1570
1578 public function formatErrors( $errors ) {
1579 $errorstr = '';
1580
1581 foreach ( $errors as $error ) {
1582 $errorstr .= Html::rawElement(
1583 'li',
1584 [],
1585 $this->getMessage( $error )->parse()
1586 );
1587 }
1588
1589 return Html::rawElement( 'ul', [], $errorstr );
1590 }
1591
1599 public function setSubmitText( $t ) {
1600 $this->mSubmitText = $t;
1601
1602 return $this;
1603 }
1604
1611 public function setSubmitDestructive() {
1612 $this->mSubmitFlags = [ 'destructive', 'primary' ];
1613
1614 return $this;
1615 }
1616
1625 public function setSubmitTextMsg( $msg ) {
1626 if ( !$msg instanceof Message ) {
1627 $msg = $this->msg( $msg );
1628 }
1629 $this->setSubmitText( $msg->text() );
1630
1631 return $this;
1632 }
1633
1638 public function getSubmitText() {
1639 return $this->mSubmitText ?: $this->msg( 'htmlform-submit' )->text();
1640 }
1641
1647 public function setSubmitName( $name ) {
1648 $this->mSubmitName = $name;
1649
1650 return $this;
1651 }
1652
1658 public function setSubmitTooltip( $name ) {
1659 $this->mSubmitTooltip = $name;
1660
1661 return $this;
1662 }
1663
1672 public function setSubmitID( $t ) {
1673 $this->mSubmitID = $t;
1674
1675 return $this;
1676 }
1677
1696 public function setFormIdentifier( string $ident, bool $single = false ) {
1697 $this->mFormIdentifier = $ident;
1698 $this->mSingleForm = $single;
1699
1700 return $this;
1701 }
1702
1713 public function suppressDefaultSubmit( $suppressSubmit = true ) {
1714 $this->mShowSubmit = !$suppressSubmit;
1715
1716 return $this;
1717 }
1718
1725 public function showCancel( $show = true ) {
1726 $this->mShowCancel = $show;
1727 return $this;
1728 }
1729
1736 public function setCancelTarget( $target ) {
1737 if ( $target instanceof PageReference ) {
1738 $target = TitleValue::castPageToLinkTarget( $target );
1739 }
1740
1741 $this->mCancelTarget = $target;
1742 return $this;
1743 }
1744
1749 protected function getCancelTargetURL() {
1750 if ( is_string( $this->mCancelTarget ) ) {
1751 return $this->mCancelTarget;
1752 } else {
1753 // TODO: use a service to get the local URL for a LinkTarget, see T282283
1754 $target = Title::castFromLinkTarget( $this->mCancelTarget ) ?: Title::newMainPage();
1755 return $target->getLocalURL();
1756 }
1757 }
1758
1768 public function setTableId( $id ) {
1769 $this->mTableId = $id;
1770
1771 return $this;
1772 }
1773
1779 public function setId( $id ) {
1780 $this->mId = $id;
1781
1782 return $this;
1783 }
1784
1789 public function setName( $name ) {
1790 $this->mName = $name;
1791
1792 return $this;
1793 }
1794
1806 public function setWrapperLegend( $legend ) {
1807 $this->mWrapperLegend = $legend;
1808
1809 return $this;
1810 }
1811
1819 public function setWrapperAttributes( $attributes ) {
1820 $this->mWrapperAttributes = $attributes;
1821
1822 return $this;
1823 }
1824
1834 public function setWrapperLegendMsg( $msg ) {
1835 if ( !$msg instanceof Message ) {
1836 $msg = $this->msg( $msg );
1837 }
1838 $this->setWrapperLegend( $msg->text() );
1839
1840 return $this;
1841 }
1842
1852 public function setMessagePrefix( $p ) {
1853 $this->mMessagePrefix = $p;
1854
1855 return $this;
1856 }
1857
1865 public function setTitle( $t ) {
1866 // TODO: make mTitle a PageReference when we have a better way to get URLs, see T282283.
1867 $this->mTitle = Title::castFromPageReference( $t );
1868
1869 return $this;
1870 }
1871
1875 public function getTitle() {
1876 return $this->mTitle ?: $this->getContext()->getTitle();
1877 }
1878
1886 public function setMethod( $method = 'post' ) {
1887 $this->mMethod = strtolower( $method );
1888
1889 return $this;
1890 }
1891
1895 public function getMethod() {
1896 return $this->mMethod;
1897 }
1898
1909 protected function wrapFieldSetSection( $legend, $section, $attributes, $isRoot ) {
1910 return Xml::fieldset( $legend, $section, $attributes ) . "\n";
1911 }
1912
1930 public function displaySection( $fields,
1931 $sectionName = '',
1932 $fieldsetIDPrefix = '',
1933 &$hasUserVisibleFields = false
1934 ) {
1935 if ( $this->mFieldData === null ) {
1936 throw new LogicException( 'HTMLForm::displaySection() called on uninitialized field data. '
1937 . 'You probably called displayForm() without calling prepareForm() first.' );
1938 }
1939
1940 $html = [];
1941 $subsectionHtml = '';
1942 $hasLabel = false;
1943
1944 foreach ( $fields as $key => $value ) {
1945 if ( $value instanceof HTMLFormField ) {
1946 $v = array_key_exists( $key, $this->mFieldData )
1947 ? $this->mFieldData[$key]
1948 : $value->getDefault();
1949
1950 $retval = $this->formatField( $value, $v ?? '' );
1951
1952 // check, if the form field should be added to
1953 // the output.
1954 if ( $value->hasVisibleOutput() ) {
1955 $html[] = $retval;
1956
1957 $labelValue = trim( $value->getLabel() );
1958 if ( $labelValue !== "\u{00A0}" && $labelValue !== '&#160;' && $labelValue !== '' ) {
1959 $hasLabel = true;
1960 }
1961
1962 $hasUserVisibleFields = true;
1963 }
1964 } elseif ( is_array( $value ) ) {
1965 $subsectionHasVisibleFields = false;
1966 $section =
1967 $this->displaySection( $value,
1968 "mw-htmlform-$key",
1969 "$fieldsetIDPrefix$key-",
1970 $subsectionHasVisibleFields );
1971
1972 if ( $subsectionHasVisibleFields === true ) {
1973 // Display the section with various niceties.
1974 $hasUserVisibleFields = true;
1975
1976 $legend = $this->getLegend( $key );
1977
1978 $section = $this->getHeaderText( $key ) .
1979 $section .
1980 $this->getFooterText( $key );
1981
1982 $attributes = [];
1983 if ( $fieldsetIDPrefix ) {
1984 $attributes['id'] = Sanitizer::escapeIdForAttribute( "$fieldsetIDPrefix$key" );
1985 }
1986 $subsectionHtml .= $this->wrapFieldSetSection(
1987 $legend, $section, $attributes, $fields === $this->mFieldTree
1988 );
1989 } else {
1990 // Just return the inputs, nothing fancy.
1991 $subsectionHtml .= $section;
1992 }
1993 }
1994 }
1995
1996 $html = $this->formatSection( $html, $sectionName, $hasLabel );
1997
1998 if ( $subsectionHtml ) {
1999 if ( $this->mSubSectionBeforeFields ) {
2000 return $subsectionHtml . "\n" . $html;
2001 } else {
2002 return $html . "\n" . $subsectionHtml;
2003 }
2004 } else {
2005 return $html;
2006 }
2007 }
2008
2017 protected function formatField( HTMLFormField $field, $value ) {
2018 $displayFormat = $this->getDisplayFormat();
2019 switch ( $displayFormat ) {
2020 case 'table':
2021 return $field->getTableRow( $value );
2022 case 'div':
2023 return $field->getDiv( $value );
2024 case 'raw':
2025 return $field->getRaw( $value );
2026 case 'inline':
2027 return $field->getInline( $value );
2028 default:
2029 throw new LogicException( 'Not implemented' );
2030 }
2031 }
2032
2041 protected function formatSection( array $fieldsHtml, $sectionName, $anyFieldHasLabel ) {
2042 if ( !$fieldsHtml ) {
2043 // Do not generate any wrappers for empty sections. Sections may be empty if they only have
2044 // subsections, but no fields. A legend will still be added in wrapFieldSetSection().
2045 return '';
2046 }
2047
2048 $displayFormat = $this->getDisplayFormat();
2049 $html = implode( '', $fieldsHtml );
2050
2051 if ( $displayFormat === 'raw' ) {
2052 return $html;
2053 }
2054
2055 // Avoid strange spacing when no labels exist
2056 $attribs = $anyFieldHasLabel ? [] : [ 'class' => 'mw-htmlform-nolabel' ];
2057
2058 if ( $sectionName ) {
2059 $attribs['id'] = Sanitizer::escapeIdForAttribute( $sectionName );
2060 }
2061
2062 if ( $displayFormat === 'table' ) {
2063 return Html::rawElement( 'table',
2064 $attribs,
2065 Html::rawElement( 'tbody', [], "\n$html\n" ) ) . "\n";
2066 } elseif ( $displayFormat === 'inline' ) {
2067 return Html::rawElement( 'span', $attribs, "\n$html\n" );
2068 } else {
2069 return Html::rawElement( 'div', $attribs, "\n$html\n" );
2070 }
2071 }
2072
2076 public function loadData() {
2077 $this->prepareForm();
2078 }
2079
2083 protected function loadFieldData() {
2084 $fieldData = [];
2085 $request = $this->getRequest();
2086
2087 foreach ( $this->mFlatFields as $fieldname => $field ) {
2088 if ( $field->skipLoadData( $request ) ) {
2089 continue;
2090 }
2091 if ( $field->mParams['disabled'] ?? false ) {
2092 $fieldData[$fieldname] = $field->getDefault();
2093 } else {
2094 $fieldData[$fieldname] = $field->loadDataFromRequest( $request );
2095 }
2096 }
2097
2098 // Reset to default for fields that are supposed to be disabled.
2099 // FIXME: Handle dependency chains, fields that a field checks on may need a reset too.
2100 foreach ( $fieldData as $name => &$value ) {
2101 $field = $this->mFlatFields[$name];
2102 if ( $field->isDisabled( $fieldData ) ) {
2103 $value = $field->getDefault();
2104 }
2105 }
2106
2107 # Filter data.
2108 foreach ( $fieldData as $name => &$value ) {
2109 $field = $this->mFlatFields[$name];
2110 $value = $field->filter( $value, $fieldData );
2111 }
2112
2113 $this->mFieldData = $fieldData;
2114 }
2115
2123 public function suppressReset( $suppressReset = true ) {
2124 $this->mShowReset = !$suppressReset;
2125
2126 return $this;
2127 }
2128
2139 public function filterDataForSubmit( $data ) {
2140 return $data;
2141 }
2142
2152 public function getLegend( $key ) {
2153 return $this->msg( $this->mMessagePrefix ? "{$this->mMessagePrefix}-$key" : $key )->text();
2154 }
2155
2166 public function setAction( $action ) {
2167 $this->mAction = $action;
2168
2169 return $this;
2170 }
2171
2179 public function getAction() {
2180 // If an action is already provided, return it
2181 if ( $this->mAction !== false ) {
2182 return $this->mAction;
2183 }
2184
2185 $articlePath = $this->getConfig()->get( MainConfigNames::ArticlePath );
2186 // Check whether we are in GET mode and the ArticlePath contains a "?"
2187 // meaning that getLocalURL() would return something like "index.php?title=...".
2188 // As browser remove the query string before submitting GET forms,
2189 // it means that the title would be lost. In such case use script path instead
2190 // and put title in a hidden field (see getHiddenFields()).
2191 if ( str_contains( $articlePath, '?' ) && $this->getMethod() === 'get' ) {
2192 return $this->getConfig()->get( MainConfigNames::Script );
2193 }
2194
2195 return $this->getTitle()->getLocalURL();
2196 }
2197
2208 public function setAutocomplete( $autocomplete ) {
2209 $this->mAutocomplete = $autocomplete;
2210
2211 return $this;
2212 }
2213
2220 protected function getMessage( $value ) {
2221 return Message::newFromSpecifier( $value )->setContext( $this );
2222 }
2223
2234 foreach ( $this->mFlatFields as $field ) {
2235 if ( $field->needsJSForHtml5FormValidation() ) {
2236 return true;
2237 }
2238 }
2239 return false;
2240 }
2241}
getUser()
addFields( $fields)
getContext()
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:88
Codex based HTML form.
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
setContext(IContextSource $context)
The parent class to generate form fields.
getRaw( $value)
Get the complete raw fields for the input, including help text, labels, and whatever.
getTableRow( $value)
Get the complete table row for the input, including help text, labels, and whatever.
getInline( $value)
Get the complete field as an inline element.
getDiv( $value)
Get the complete div for the input, including help text, labels, and whatever.
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:158
needsJSForHtml5FormValidation()
Whether this form, with its current fields, requires the user agent to have JavaScript enabled for th...
setSubmitCallback( $cb)
Set a callback to a function to do something with the form once it's been successfully validated.
Definition HTMLForm.php:787
setHeaderText( $msg, $section=null)
Set header text, inside the form.
Definition HTMLForm.php:967
string false $mAction
Form action URL.
Definition HTMLForm.php:259
displayForm( $submitResult)
Display the form (sending to the context's OutputPage object), with an appropriate error message or s...
string null $mAutocomplete
Form attribute autocomplete.
Definition HTMLForm.php:280
setAction( $action)
Set the value for the action attribute of the form.
string array $mTokenSalt
Salt for the edit token.
Definition HTMLForm.php:301
setFooterHtml( $html, $section=null)
Set footer HTML, inside the form.
string[] $mSubmitFlags
Definition HTMLForm.php:220
addPreHtml( $html)
Add HTML to introductory message.
Definition HTMLForm.php:842
getSubmitText()
Get the text for the submit button, either customised or a default.
setMethod( $method='post')
Set the method used to submit the form.
setValidationErrorMessage( $msg)
Set a message to display on a validation error.
Definition HTMLForm.php:802
getCancelTargetURL()
getMessage( $value)
Turns a *-message parameter (which could be a MessageSpecifier, or a message name,...
getHeaderHtml( $section=null)
Get header HTML.
Definition HTMLForm.php:940
addHeaderHtml( $html, $section=null)
Add HTML to the header, inside the form.
Definition HTMLForm.php:902
setAutocomplete( $autocomplete)
Set the value for the autocomplete attribute of the form.
static loadInputFromParameters( $fieldname, $descriptor, HTMLForm $parent=null)
Initialise a new Object for the field.
Definition HTMLForm.php:561
setSubmitName( $name)
setTitle( $t)
Set the title for form submission.
static getClassFromDescriptor( $fieldname, &$descriptor)
Get the HTMLFormField subclass for this descriptor.
Definition HTMLForm.php:530
array $availableSubclassDisplayFormats
Available formats in which to display the form.
Definition HTMLForm.php:335
string $displayFormat
Format in which to display form.
Definition HTMLForm.php:318
addPostHtml( $html)
Add HTML to the end of the display.
bool $mSubSectionBeforeFields
If true, sections that contain both fields and subsections will render their subsections before their...
Definition HTMLForm.php:311
setTableId( $id)
Set the id of the <table> or outermost <div> element.
getHTML( $submitResult)
Returns the raw HTML generated by the form.
getLegend( $key)
Get a string to go in the "<legend>" of a section fieldset.
setSubmitTextMsg( $msg)
Set the text for the submit button to a message.
wrapFieldSetSection( $legend, $section, $attributes, $isRoot)
Wraps the given $section into a user-visible fieldset.
filterDataForSubmit( $data)
Overload this if you want to apply special filtration routines to the form as a whole,...
setWrapperLegendMsg( $msg)
Prompt the whole form to be wrapped in a "<fieldset>", with this message as its "<legend>" element.
setId( $id)
setWrapperLegend( $legend)
Prompt the whole form to be wrapped in a "<fieldset>", with this text as its "<legend>" element.
formatErrors( $errors)
Format a stack of error messages into a single HTML string.
setDisplayFormat( $format)
Set format in which to display the form.
Definition HTMLForm.php:473
addButton( $data)
Add a button to the form.
addFooterHtml( $html, $section=null)
Add footer HTML, inside the form.
Definition HTMLForm.php:993
setPreHtml( $html)
Set the introductory message HTML, overwriting any existing message.
Definition HTMLForm.php:828
getPreHtml()
Get the introductory message HTML.
Definition HTMLForm.php:854
setPostHtml( $html)
Set HTML at the end of the display.
getPreText()
Get the introductory message HTML.
Definition HTMLForm.php:889
static string[] $typeMappings
A mapping of 'type' inputs onto standard HTMLFormField subclasses.
Definition HTMLForm.php:162
getHiddenFields()
Get the hidden fields that should go inside the form.
setSubmitDestructive()
Identify that the submit button in the form has a destructive action.
formatField(HTMLFormField $field, $value)
Generate the HTML for an individual field in the current display format.
suppressDefaultSubmit( $suppressSubmit=true)
Stop a default submit button being shown for this form.
setSubmitID( $t)
Set the id for the submit button.
getDisplayFormat()
Getter for displayFormat.
Definition HTMLForm.php:509
getAction()
Get the value for the action attribute of the form.
show()
The here's-one-I-made-earlier option: do the submission if posted, or display the form with or withou...
Definition HTMLForm.php:644
hasField( $fieldname)
Definition HTMLForm.php:447
$mWrapperAttributes
Definition HTMLForm.php:295
addFooterText( $msg, $section=null)
Add footer text, inside the form.
addPostText( $msg)
Add text to the end of the display.
getFooterText( $section=null)
Get footer text.
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition HTMLForm.php:953
setWrapperAttributes( $attributes)
For internal use only.
prepareForm()
Prepare form for submission.
Definition HTMLForm.php:586
array[] $mValidationErrorMessage
Definition HTMLForm.php:229
setCollapsibleOptions( $collapsedByDefault=false)
Enable collapsible mode, and set whether the form is collapsed by default.
wasSubmitted()
Test whether the form was considered to have been submitted or not, i.e.
Definition HTMLForm.php:773
getHeaderText( $section=null)
Get header text.
Definition HTMLForm.php:980
array[] $mButtons
Definition HTMLForm.php:292
tryAuthorizedSubmit()
Try submitting, with edit token check first.
Definition HTMLForm.php:605
setSubmitTooltip( $name)
displaySection( $fields, $sectionName='', $fieldsetIDPrefix='', &$hasUserVisibleFields=false)
array[] $mHiddenFields
Definition HTMLForm.php:287
setPreText( $msg)
Set the introductory message HTML, overwriting any existing message.
Definition HTMLForm.php:866
bool $mCollapsible
Whether the form can be collapsed.
Definition HTMLForm.php:266
addHiddenField( $name, $value, array $attribs=[])
Add a hidden field to the output Array values are discarded for security reasons (per WebRequest::get...
setFooterText( $msg, $section=null)
Set footer text, inside the form.
setMessagePrefix( $p)
Set the prefix for various default messages.
getField( $fieldname)
Definition HTMLForm.php:456
bool $mCollapsed
Whether the form is collapsed by default.
Definition HTMLForm.php:273
wrapForm( $html)
Wrap the form innards in an actual "<form>" element.
getFormAttributes()
Get HTML attributes for the <form> tag.
getBody()
Get the whole body of the form.
showAlways()
Same as self::show with the difference, that the form will be added to the output,...
Definition HTMLForm.php:662
getFooterHtml( $section=null)
Get footer HTML.
loadFieldData()
Load data of form fields from the request.
setHeaderHtml( $html, $section=null)
Set header HTML, inside the form.
Definition HTMLForm.php:922
setTokenSalt( $salt)
Set the salt for the edit token.
__construct( $descriptor, IContextSource $context, $messagePrefix='')
Build a new HTMLForm from an array of field attributes.
Definition HTMLForm.php:388
addPreText( $msg)
Add HTML to introductory message.
Definition HTMLForm.php:878
setFormIdentifier(string $ident, bool $single=false)
Set an internal identifier for this form.
setName( $name)
suppressReset( $suppressReset=true)
Stop a reset button being shown for this form.
setPostText( $msg)
Set text at the end of the display.
formatSection(array $fieldsHtml, $sectionName, $anyFieldHasLabel)
Put a form section together from the individual fields' HTML, merging it and wrapping.
setCancelTarget( $target)
Sets the target where the user is redirected to after clicking cancel.
array $availableDisplayFormats
Available formats in which to display the form.
Definition HTMLForm.php:324
showCancel( $show=true)
Show a cancel button (or prevent it).
Title null $mTitle
Definition HTMLForm.php:250
setSubmitText( $t)
Set the text for the submit button.
setIntro( $msg)
Set the introductory message, overwriting any existing message.
Definition HTMLForm.php:816
getButtons()
Get the submit and (potentially) reset buttons.
static factory( $displayFormat, $descriptor, IContextSource $context, $messagePrefix='')
Construct a HTMLForm object for given display type.
Definition HTMLForm.php:360
trySubmit()
Validate all the fields, and call the submission callback function if everything is kosher.
Definition HTMLForm.php:684
HTMLFormField[] $mFlatFields
Definition HTMLForm.php:215
getErrorsOrWarnings( $elements, $elementsType)
Returns a formatted list of errors or warnings from the given elements.
addHiddenFields(array $fields)
Add an array of hidden fields to the output Array values are discarded for security reasons (per WebR...
getPostHtml()
Get HTML at the end of the display.
addFields( $descriptor)
Add fields to the form.
Definition HTMLForm.php:414
MediaWiki exception.
This class is a collection of static functions that serve two purposes:
Definition Html.php:57
Some internal bits split of from Skin.php.
Definition Linker.php:65
A class containing constants representing the names of configuration variables.
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:46
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:58
Represents the target of a wiki link.
Represents a title within MediaWiki.
Definition Title.php:76
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:144
static newFromSpecifier( $value)
Transform a MessageSpecifier or a primitive value used interchangeably with specifiers (a message key...
Definition Message.php:427
Compact stacked vertical format for forms, implemented using OOUI widgets.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Compact stacked vertical format for forms.
Interface for objects which can provide a MediaWiki context on request.
Represents the target of a wiki link.
Interface for objects (potentially) representing a page that can be viewable and linked to on a wiki.