MediaWiki REL1_27
HTMLForm.php
Go to the documentation of this file.
1<?php
2
123class HTMLForm extends ContextSource {
124 // A mapping of 'type' inputs onto standard HTMLFormField subclasses
125 public static $typeMappings = [
126 'api' => 'HTMLApiField',
127 'text' => 'HTMLTextField',
128 'textwithbutton' => 'HTMLTextFieldWithButton',
129 'textarea' => 'HTMLTextAreaField',
130 'select' => 'HTMLSelectField',
131 'combobox' => 'HTMLComboboxField',
132 'radio' => 'HTMLRadioField',
133 'multiselect' => 'HTMLMultiSelectField',
134 'limitselect' => 'HTMLSelectLimitField',
135 'check' => 'HTMLCheckField',
136 'toggle' => 'HTMLCheckField',
137 'int' => 'HTMLIntField',
138 'float' => 'HTMLFloatField',
139 'info' => 'HTMLInfoField',
140 'selectorother' => 'HTMLSelectOrOtherField',
141 'selectandother' => 'HTMLSelectAndOtherField',
142 'namespaceselect' => 'HTMLSelectNamespace',
143 'namespaceselectwithbutton' => 'HTMLSelectNamespaceWithButton',
144 'tagfilter' => 'HTMLTagFilter',
145 'submit' => 'HTMLSubmitField',
146 'hidden' => 'HTMLHiddenField',
147 'edittools' => 'HTMLEditTools',
148 'checkmatrix' => 'HTMLCheckMatrix',
149 'cloner' => 'HTMLFormFieldCloner',
150 'autocompleteselect' => 'HTMLAutoCompleteSelectField',
151 // HTMLTextField will output the correct type="" attribute automagically.
152 // There are about four zillion other HTML5 input types, like range, but
153 // we don't use those at the moment, so no point in adding all of them.
154 'email' => 'HTMLTextField',
155 'password' => 'HTMLTextField',
156 'url' => 'HTMLTextField',
157 'title' => 'HTMLTitleTextField',
158 'user' => 'HTMLUserTextField',
159 ];
160
162
164
166 protected $mFlatFields;
167
168 protected $mFieldTree;
169 protected $mShowReset = false;
170 protected $mShowSubmit = true;
171 protected $mSubmitFlags = [ 'constructive', 'primary' ];
172
175
176 protected $mPre = '';
177 protected $mHeader = '';
178 protected $mFooter = '';
179 protected $mSectionHeaders = [];
180 protected $mSectionFooters = [];
181 protected $mPost = '';
182 protected $mId;
183 protected $mName;
184 protected $mTableId = '';
185
186 protected $mSubmitID;
187 protected $mSubmitName;
188 protected $mSubmitText;
190
191 protected $mTitle;
192 protected $mMethod = 'post';
193 protected $mWasSubmitted = false;
194
200 protected $mAction = false;
201
207 protected $mAutocomplete = false;
208
209 protected $mUseMultipart = false;
210 protected $mHiddenFields = [];
211 protected $mButtons = [];
212
213 protected $mWrapperLegend = false;
214
219 protected $mTokenSalt = '';
220
228 protected $mSubSectionBeforeFields = true;
229
235 protected $displayFormat = 'table';
236
242 'table',
243 'div',
244 'raw',
245 'inline',
246 ];
247
253 'vform',
254 'ooui',
255 ];
256
264 public static function factory( $displayFormat/*, $arguments...*/ ) {
265 $arguments = func_get_args();
266 array_shift( $arguments );
267
268 switch ( $displayFormat ) {
269 case 'vform':
270 $reflector = new ReflectionClass( 'VFormHTMLForm' );
271 return $reflector->newInstanceArgs( $arguments );
272 case 'ooui':
273 $reflector = new ReflectionClass( 'OOUIHTMLForm' );
274 return $reflector->newInstanceArgs( $arguments );
275 default:
276 $reflector = new ReflectionClass( 'HTMLForm' );
277 $form = $reflector->newInstanceArgs( $arguments );
278 $form->setDisplayFormat( $displayFormat );
279 return $form;
280 }
281 }
282
291 public function __construct( $descriptor, /*IContextSource*/ $context = null,
292 $messagePrefix = ''
293 ) {
294 if ( $context instanceof IContextSource ) {
295 $this->setContext( $context );
296 $this->mTitle = false; // We don't need them to set a title
297 $this->mMessagePrefix = $messagePrefix;
298 } elseif ( $context === null && $messagePrefix !== '' ) {
299 $this->mMessagePrefix = $messagePrefix;
300 } elseif ( is_string( $context ) && $messagePrefix === '' ) {
301 // B/C since 1.18
302 // it's actually $messagePrefix
303 $this->mMessagePrefix = $context;
304 }
305
306 // Evil hack for mobile :(
307 if (
308 !$this->getConfig()->get( 'HTMLFormAllowTableFormat' )
309 && $this->displayFormat === 'table'
310 ) {
311 $this->displayFormat = 'div';
312 }
313
314 // Expand out into a tree.
315 $loadedDescriptor = [];
316 $this->mFlatFields = [];
317
318 foreach ( $descriptor as $fieldname => $info ) {
319 $section = isset( $info['section'] )
320 ? $info['section']
321 : '';
322
323 if ( isset( $info['type'] ) && $info['type'] === 'file' ) {
324 $this->mUseMultipart = true;
325 }
326
327 $field = static::loadInputFromParameters( $fieldname, $info, $this );
328
329 $setSection =& $loadedDescriptor;
330 if ( $section ) {
331 $sectionParts = explode( '/', $section );
332
333 while ( count( $sectionParts ) ) {
334 $newName = array_shift( $sectionParts );
335
336 if ( !isset( $setSection[$newName] ) ) {
337 $setSection[$newName] = [];
338 }
339
340 $setSection =& $setSection[$newName];
341 }
342 }
343
344 $setSection[$fieldname] = $field;
345 $this->mFlatFields[$fieldname] = $field;
346 }
347
348 $this->mFieldTree = $loadedDescriptor;
349 }
350
361 public function setDisplayFormat( $format ) {
362 if (
363 in_array( $format, $this->availableSubclassDisplayFormats, true ) ||
364 in_array( $this->displayFormat, $this->availableSubclassDisplayFormats, true )
365 ) {
366 throw new MWException( 'Cannot change display format after creation, ' .
367 'use HTMLForm::factory() instead' );
368 }
369
370 if ( !in_array( $format, $this->availableDisplayFormats, true ) ) {
371 throw new MWException( 'Display format must be one of ' .
372 print_r( $this->availableDisplayFormats, true ) );
373 }
374
375 // Evil hack for mobile :(
376 if ( !$this->getConfig()->get( 'HTMLFormAllowTableFormat' ) && $format === 'table' ) {
377 $format = 'div';
378 }
379
380 $this->displayFormat = $format;
381
382 return $this;
383 }
384
390 public function getDisplayFormat() {
392 }
393
400 public function isVForm() {
401 wfDeprecated( __METHOD__, '1.25' );
402 return false;
403 }
404
421 public static function getClassFromDescriptor( $fieldname, &$descriptor ) {
422 if ( isset( $descriptor['class'] ) ) {
423 $class = $descriptor['class'];
424 } elseif ( isset( $descriptor['type'] ) ) {
425 $class = static::$typeMappings[$descriptor['type']];
426 $descriptor['class'] = $class;
427 } else {
428 $class = null;
429 }
430
431 if ( !$class ) {
432 throw new MWException( "Descriptor with no class for $fieldname: "
433 . print_r( $descriptor, true ) );
434 }
435
436 return $class;
437 }
438
449 public static function loadInputFromParameters( $fieldname, $descriptor,
450 HTMLForm $parent = null
451 ) {
452 $class = static::getClassFromDescriptor( $fieldname, $descriptor );
453
454 $descriptor['fieldname'] = $fieldname;
455 if ( $parent ) {
456 $descriptor['parent'] = $parent;
457 }
458
459 # @todo This will throw a fatal error whenever someone try to use
460 # 'class' to feed a CSS class instead of 'cssclass'. Would be
461 # great to avoid the fatal error and show a nice error.
462 return new $class( $descriptor );
463 }
464
474 public function prepareForm() {
475 # Check if we have the info we need
476 if ( !$this->mTitle instanceof Title && $this->mTitle !== false ) {
477 throw new MWException( 'You must call setTitle() on an HTMLForm' );
478 }
479
480 # Load data from the request.
481 $this->loadData();
482
483 return $this;
484 }
485
490 public function tryAuthorizedSubmit() {
491 $result = false;
492
493 $submit = false;
494 if ( $this->getMethod() !== 'post' ) {
495 $submit = true; // no session check needed
496 } elseif ( $this->getRequest()->wasPosted() ) {
497 $editToken = $this->getRequest()->getVal( 'wpEditToken' );
498 if ( $this->getUser()->isLoggedIn() || $editToken !== null ) {
499 // Session tokens for logged-out users have no security value.
500 // However, if the user gave one, check it in order to give a nice
501 // "session expired" error instead of "permission denied" or such.
502 $submit = $this->getUser()->matchEditToken( $editToken, $this->mTokenSalt );
503 } else {
504 $submit = true;
505 }
506 }
507
508 if ( $submit ) {
509 $this->mWasSubmitted = true;
510 $result = $this->trySubmit();
511 }
512
513 return $result;
514 }
515
522 public function show() {
523 $this->prepareForm();
524
525 $result = $this->tryAuthorizedSubmit();
526 if ( $result === true || ( $result instanceof Status && $result->isGood() ) ) {
527 return $result;
528 }
529
530 $this->displayForm( $result );
531
532 return false;
533 }
534
540 public function showAlways() {
541 $this->prepareForm();
542
543 $result = $this->tryAuthorizedSubmit();
544
545 $this->displayForm( $result );
546
547 return $result;
548 }
549
561 public function trySubmit() {
562 $valid = true;
563 $hoistedErrors = [];
564 $hoistedErrors[] = isset( $this->mValidationErrorMessage )
565 ? $this->mValidationErrorMessage
566 : [ 'htmlform-invalid-input' ];
567
568 $this->mWasSubmitted = true;
569
570 # Check for cancelled submission
571 foreach ( $this->mFlatFields as $fieldname => $field ) {
572 if ( !array_key_exists( $fieldname, $this->mFieldData ) ) {
573 continue;
574 }
575 if ( $field->cancelSubmit( $this->mFieldData[$fieldname], $this->mFieldData ) ) {
576 $this->mWasSubmitted = false;
577 return false;
578 }
579 }
580
581 # Check for validation
582 foreach ( $this->mFlatFields as $fieldname => $field ) {
583 if ( !array_key_exists( $fieldname, $this->mFieldData ) ) {
584 continue;
585 }
586 if ( $field->isHidden( $this->mFieldData ) ) {
587 continue;
588 }
589 $res = $field->validate( $this->mFieldData[$fieldname], $this->mFieldData );
590 if ( $res !== true ) {
591 $valid = false;
592 if ( $res !== false && !$field->canDisplayErrors() ) {
593 $hoistedErrors[] = [ 'rawmessage', $res ];
594 }
595 }
596 }
597
598 if ( !$valid ) {
599 if ( count( $hoistedErrors ) === 1 ) {
600 $hoistedErrors = $hoistedErrors[0];
601 }
602 return $hoistedErrors;
603 }
604
605 $callback = $this->mSubmitCallback;
606 if ( !is_callable( $callback ) ) {
607 throw new MWException( 'HTMLForm: no submit callback provided. Use ' .
608 'setSubmitCallback() to set one.' );
609 }
610
611 $data = $this->filterDataForSubmit( $this->mFieldData );
612
613 $res = call_user_func( $callback, $data, $this );
614 if ( $res === false ) {
615 $this->mWasSubmitted = false;
616 }
617
618 return $res;
619 }
620
632 public function wasSubmitted() {
634 }
635
646 public function setSubmitCallback( $cb ) {
647 $this->mSubmitCallback = $cb;
648
649 return $this;
650 }
651
660 public function setValidationErrorMessage( $msg ) {
661 $this->mValidationErrorMessage = $msg;
662
663 return $this;
664 }
665
673 public function setIntro( $msg ) {
674 $this->setPreText( $msg );
675
676 return $this;
677 }
678
687 public function setPreText( $msg ) {
688 $this->mPre = $msg;
689
690 return $this;
691 }
692
700 public function addPreText( $msg ) {
701 $this->mPre .= $msg;
702
703 return $this;
704 }
705
714 public function addHeaderText( $msg, $section = null ) {
715 if ( $section === null ) {
716 $this->mHeader .= $msg;
717 } else {
718 if ( !isset( $this->mSectionHeaders[$section] ) ) {
719 $this->mSectionHeaders[$section] = '';
720 }
721 $this->mSectionHeaders[$section] .= $msg;
722 }
723
724 return $this;
725 }
726
736 public function setHeaderText( $msg, $section = null ) {
737 if ( $section === null ) {
738 $this->mHeader = $msg;
739 } else {
740 $this->mSectionHeaders[$section] = $msg;
741 }
742
743 return $this;
744 }
745
753 public function getHeaderText( $section = null ) {
754 if ( $section === null ) {
755 return $this->mHeader;
756 } else {
757 return isset( $this->mSectionHeaders[$section] ) ? $this->mSectionHeaders[$section] : '';
758 }
759 }
760
769 public function addFooterText( $msg, $section = null ) {
770 if ( $section === null ) {
771 $this->mFooter .= $msg;
772 } else {
773 if ( !isset( $this->mSectionFooters[$section] ) ) {
774 $this->mSectionFooters[$section] = '';
775 }
776 $this->mSectionFooters[$section] .= $msg;
777 }
778
779 return $this;
780 }
781
791 public function setFooterText( $msg, $section = null ) {
792 if ( $section === null ) {
793 $this->mFooter = $msg;
794 } else {
795 $this->mSectionFooters[$section] = $msg;
796 }
797
798 return $this;
799 }
800
808 public function getFooterText( $section = null ) {
809 if ( $section === null ) {
810 return $this->mFooter;
811 } else {
812 return isset( $this->mSectionFooters[$section] ) ? $this->mSectionFooters[$section] : '';
813 }
814 }
815
823 public function addPostText( $msg ) {
824 $this->mPost .= $msg;
825
826 return $this;
827 }
828
836 public function setPostText( $msg ) {
837 $this->mPost = $msg;
838
839 return $this;
840 }
841
851 public function addHiddenField( $name, $value, array $attribs = [] ) {
852 $attribs += [ 'name' => $name ];
853 $this->mHiddenFields[] = [ $value, $attribs ];
854
855 return $this;
856 }
857
868 public function addHiddenFields( array $fields ) {
869 foreach ( $fields as $name => $value ) {
870 $this->mHiddenFields[] = [ $value, [ 'name' => $name ] ];
871 }
872
873 return $this;
874 }
875
899 public function addButton( $data ) {
900 if ( !is_array( $data ) ) {
901 $args = func_get_args();
902 if ( count( $args ) < 2 || count( $args ) > 4 ) {
903 throw new InvalidArgumentException(
904 'Incorrect number of arguments for deprecated calling style'
905 );
906 }
907 $data = [
908 'name' => $args[0],
909 'value' => $args[1],
910 'id' => isset( $args[2] ) ? $args[2] : null,
911 'attribs' => isset( $args[3] ) ? $args[3] : null,
912 ];
913 } else {
914 if ( !isset( $data['name'] ) ) {
915 throw new InvalidArgumentException( 'A name is required' );
916 }
917 if ( !isset( $data['value'] ) ) {
918 throw new InvalidArgumentException( 'A value is required' );
919 }
920 }
921 $this->mButtons[] = $data + [
922 'id' => null,
923 'attribs' => null,
924 'flags' => null,
925 ];
926
927 return $this;
928 }
929
939 public function setTokenSalt( $salt ) {
940 $this->mTokenSalt = $salt;
941
942 return $this;
943 }
944
957 public function displayForm( $submitResult ) {
958 $this->getOutput()->addHTML( $this->getHTML( $submitResult ) );
959 }
960
968 public function getHTML( $submitResult ) {
969 # For good measure (it is the default)
970 $this->getOutput()->preventClickjacking();
971 $this->getOutput()->addModules( 'mediawiki.htmlform' );
972 $this->getOutput()->addModuleStyles( 'mediawiki.htmlform.styles' );
973
974 $html = ''
975 . $this->getErrors( $submitResult )
976 . $this->getHeaderText()
977 . $this->getBody()
978 . $this->getHiddenFields()
979 . $this->getButtons()
980 . $this->getFooterText();
981
982 $html = $this->wrapForm( $html );
983
984 return '' . $this->mPre . $html . $this->mPost;
985 }
986
991 protected function getFormAttributes() {
992 # Use multipart/form-data
993 $encType = $this->mUseMultipart
994 ? 'multipart/form-data'
995 : 'application/x-www-form-urlencoded';
996 # Attributes
997 $attribs = [
998 'action' => $this->getAction(),
999 'method' => $this->getMethod(),
1000 'enctype' => $encType,
1001 ];
1002 if ( $this->mId ) {
1003 $attribs['id'] = $this->mId;
1004 }
1005 if ( $this->mAutocomplete ) {
1006 $attribs['autocomplete'] = $this->mAutocomplete;
1007 }
1008 if ( $this->mName ) {
1009 $attribs['name'] = $this->mName;
1010 }
1011 return $attribs;
1012 }
1013
1021 public function wrapForm( $html ) {
1022 # Include a <fieldset> wrapper for style, if requested.
1023 if ( $this->mWrapperLegend !== false ) {
1024 $legend = is_string( $this->mWrapperLegend ) ? $this->mWrapperLegend : false;
1025 $html = Xml::fieldset( $legend, $html );
1026 }
1027
1028 return Html::rawElement(
1029 'form',
1030 $this->getFormAttributes() + [ 'class' => 'visualClear' ],
1031 $html
1032 );
1033 }
1034
1039 public function getHiddenFields() {
1040 $html = '';
1041 if ( $this->getMethod() === 'post' ) {
1043 'wpEditToken',
1044 $this->getUser()->getEditToken( $this->mTokenSalt ),
1045 [ 'id' => 'wpEditToken' ]
1046 ) . "\n";
1047 $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
1048 }
1049
1050 $articlePath = $this->getConfig()->get( 'ArticlePath' );
1051 if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() === 'get' ) {
1052 $html .= Html::hidden( 'title', $this->getTitle()->getPrefixedText() ) . "\n";
1053 }
1054
1055 foreach ( $this->mHiddenFields as $data ) {
1056 list( $value, $attribs ) = $data;
1057 $html .= Html::hidden( $attribs['name'], $value, $attribs ) . "\n";
1058 }
1059
1060 return $html;
1061 }
1062
1067 public function getButtons() {
1068 $buttons = '';
1069 $useMediaWikiUIEverywhere = $this->getConfig()->get( 'UseMediaWikiUIEverywhere' );
1070
1071 if ( $this->mShowSubmit ) {
1072 $attribs = [];
1073
1074 if ( isset( $this->mSubmitID ) ) {
1075 $attribs['id'] = $this->mSubmitID;
1076 }
1077
1078 if ( isset( $this->mSubmitName ) ) {
1079 $attribs['name'] = $this->mSubmitName;
1080 }
1081
1082 if ( isset( $this->mSubmitTooltip ) ) {
1083 $attribs += Linker::tooltipAndAccesskeyAttribs( $this->mSubmitTooltip );
1084 }
1085
1086 $attribs['class'] = [ 'mw-htmlform-submit' ];
1087
1088 if ( $useMediaWikiUIEverywhere ) {
1089 foreach ( $this->mSubmitFlags as $flag ) {
1090 $attribs['class'][] = 'mw-ui-' . $flag;
1091 }
1092 $attribs['class'][] = 'mw-ui-button';
1093 }
1094
1095 $buttons .= Xml::submitButton( $this->getSubmitText(), $attribs ) . "\n";
1096 }
1097
1098 if ( $this->mShowReset ) {
1099 $buttons .= Html::element(
1100 'input',
1101 [
1102 'type' => 'reset',
1103 'value' => $this->msg( 'htmlform-reset' )->text(),
1104 'class' => $useMediaWikiUIEverywhere ? 'mw-ui-button' : null,
1105 ]
1106 ) . "\n";
1107 }
1108
1109 // IE<8 has bugs with <button>, so we'll need to avoid them.
1110 $isBadIE = preg_match( '/MSIE [1-7]\./i', $this->getRequest()->getHeader( 'User-Agent' ) );
1111
1112 foreach ( $this->mButtons as $button ) {
1113 $attrs = [
1114 'type' => 'submit',
1115 'name' => $button['name'],
1116 'value' => $button['value']
1117 ];
1118
1119 if ( isset( $button['label-message'] ) ) {
1120 $label = $this->getMessage( $button['label-message'] )->parse();
1121 } elseif ( isset( $button['label'] ) ) {
1122 $label = htmlspecialchars( $button['label'] );
1123 } elseif ( isset( $button['label-raw'] ) ) {
1124 $label = $button['label-raw'];
1125 } else {
1126 $label = htmlspecialchars( $button['value'] );
1127 }
1128
1129 if ( $button['attribs'] ) {
1130 $attrs += $button['attribs'];
1131 }
1132
1133 if ( isset( $button['id'] ) ) {
1134 $attrs['id'] = $button['id'];
1135 }
1136
1137 if ( $useMediaWikiUIEverywhere ) {
1138 $attrs['class'] = isset( $attrs['class'] ) ? (array)$attrs['class'] : [];
1139 $attrs['class'][] = 'mw-ui-button';
1140 }
1141
1142 if ( $isBadIE ) {
1143 $buttons .= Html::element( 'input', $attrs ) . "\n";
1144 } else {
1145 $buttons .= Html::rawElement( 'button', $attrs, $label ) . "\n";
1146 }
1147 }
1148
1149 if ( !$buttons ) {
1150 return '';
1151 }
1152
1153 return Html::rawElement( 'span',
1154 [ 'class' => 'mw-htmlform-submit-buttons' ], "\n$buttons" ) . "\n";
1155 }
1156
1161 public function getBody() {
1162 return $this->displaySection( $this->mFieldTree, $this->mTableId );
1163 }
1164
1172 public function getErrors( $errors ) {
1173 if ( $errors instanceof Status ) {
1174 if ( $errors->isOK() ) {
1175 $errorstr = '';
1176 } else {
1177 $errorstr = $this->getOutput()->parse( $errors->getWikiText() );
1178 }
1179 } elseif ( is_array( $errors ) ) {
1180 $errorstr = $this->formatErrors( $errors );
1181 } else {
1182 $errorstr = $errors;
1183 }
1184
1185 return $errorstr
1186 ? Html::rawElement( 'div', [ 'class' => 'error' ], $errorstr )
1187 : '';
1188 }
1189
1197 public function formatErrors( $errors ) {
1198 $errorstr = '';
1199
1200 foreach ( $errors as $error ) {
1201 $errorstr .= Html::rawElement(
1202 'li',
1203 [],
1204 $this->getMessage( $error )->parse()
1205 );
1206 }
1207
1208 $errorstr = Html::rawElement( 'ul', [], $errorstr );
1209
1210 return $errorstr;
1211 }
1212
1220 public function setSubmitText( $t ) {
1221 $this->mSubmitText = $t;
1222
1223 return $this;
1224 }
1225
1230 public function setSubmitDestructive() {
1231 $this->mSubmitFlags = [ 'destructive', 'primary' ];
1232 }
1233
1238 public function setSubmitProgressive() {
1239 $this->mSubmitFlags = [ 'progressive', 'primary' ];
1240 }
1241
1250 public function setSubmitTextMsg( $msg ) {
1251 if ( !$msg instanceof Message ) {
1252 $msg = $this->msg( $msg );
1253 }
1254 $this->setSubmitText( $msg->text() );
1255
1256 return $this;
1257 }
1258
1263 public function getSubmitText() {
1264 return $this->mSubmitText ?: $this->msg( 'htmlform-submit' )->text();
1265 }
1266
1272 public function setSubmitName( $name ) {
1273 $this->mSubmitName = $name;
1274
1275 return $this;
1276 }
1277
1283 public function setSubmitTooltip( $name ) {
1284 $this->mSubmitTooltip = $name;
1285
1286 return $this;
1287 }
1288
1297 public function setSubmitID( $t ) {
1298 $this->mSubmitID = $t;
1299
1300 return $this;
1301 }
1302
1313 public function suppressDefaultSubmit( $suppressSubmit = true ) {
1314 $this->mShowSubmit = !$suppressSubmit;
1315
1316 return $this;
1317 }
1318
1328 public function setTableId( $id ) {
1329 $this->mTableId = $id;
1330
1331 return $this;
1332 }
1333
1339 public function setId( $id ) {
1340 $this->mId = $id;
1341
1342 return $this;
1343 }
1344
1349 public function setName( $name ) {
1350 $this->mName = $name;
1351
1352 return $this;
1353 }
1354
1366 public function setWrapperLegend( $legend ) {
1367 $this->mWrapperLegend = $legend;
1368
1369 return $this;
1370 }
1371
1381 public function setWrapperLegendMsg( $msg ) {
1382 if ( !$msg instanceof Message ) {
1383 $msg = $this->msg( $msg );
1384 }
1385 $this->setWrapperLegend( $msg->text() );
1386
1387 return $this;
1388 }
1389
1399 public function setMessagePrefix( $p ) {
1400 $this->mMessagePrefix = $p;
1401
1402 return $this;
1403 }
1404
1412 public function setTitle( $t ) {
1413 $this->mTitle = $t;
1414
1415 return $this;
1416 }
1417
1422 public function getTitle() {
1423 return $this->mTitle === false
1424 ? $this->getContext()->getTitle()
1425 : $this->mTitle;
1426 }
1427
1435 public function setMethod( $method = 'post' ) {
1436 $this->mMethod = strtolower( $method );
1437
1438 return $this;
1439 }
1440
1444 public function getMethod() {
1445 return $this->mMethod;
1446 }
1447
1456 protected function wrapFieldSetSection( $legend, $section, $attributes ) {
1457 return Xml::fieldset( $legend, $section, $attributes ) . "\n";
1458 }
1459
1476 public function displaySection( $fields,
1477 $sectionName = '',
1478 $fieldsetIDPrefix = '',
1479 &$hasUserVisibleFields = false
1480 ) {
1481 if ( $this->mFieldData === null ) {
1482 throw new LogicException( 'HTMLForm::displaySection() called on uninitialized field data. '
1483 . 'You probably called displayForm() without calling prepareForm() first.' );
1484 }
1485
1487
1488 $html = [];
1489 $subsectionHtml = '';
1490 $hasLabel = false;
1491
1492 // Conveniently, PHP method names are case-insensitive.
1493 // For grep: this can call getDiv, getRaw, getInline, getVForm, getOOUI
1494 $getFieldHtmlMethod = $displayFormat === 'table' ? 'getTableRow' : ( 'get' . $displayFormat );
1495
1496 foreach ( $fields as $key => $value ) {
1497 if ( $value instanceof HTMLFormField ) {
1498 $v = array_key_exists( $key, $this->mFieldData )
1499 ? $this->mFieldData[$key]
1500 : $value->getDefault();
1501
1502 $retval = $value->$getFieldHtmlMethod( $v );
1503
1504 // check, if the form field should be added to
1505 // the output.
1506 if ( $value->hasVisibleOutput() ) {
1507 $html[] = $retval;
1508
1509 $labelValue = trim( $value->getLabel() );
1510 if ( $labelValue !== '&#160;' && $labelValue !== '' ) {
1511 $hasLabel = true;
1512 }
1513
1514 $hasUserVisibleFields = true;
1515 }
1516 } elseif ( is_array( $value ) ) {
1517 $subsectionHasVisibleFields = false;
1518 $section =
1519 $this->displaySection( $value,
1520 "mw-htmlform-$key",
1521 "$fieldsetIDPrefix$key-",
1522 $subsectionHasVisibleFields );
1523 $legend = null;
1524
1525 if ( $subsectionHasVisibleFields === true ) {
1526 // Display the section with various niceties.
1527 $hasUserVisibleFields = true;
1528
1529 $legend = $this->getLegend( $key );
1530
1531 $section = $this->getHeaderText( $key ) .
1532 $section .
1533 $this->getFooterText( $key );
1534
1535 $attributes = [];
1536 if ( $fieldsetIDPrefix ) {
1537 $attributes['id'] = Sanitizer::escapeId( "$fieldsetIDPrefix$key" );
1538 }
1539 $subsectionHtml .= $this->wrapFieldSetSection( $legend, $section, $attributes );
1540 } else {
1541 // Just return the inputs, nothing fancy.
1542 $subsectionHtml .= $section;
1543 }
1544 }
1545 }
1546
1547 $html = $this->formatSection( $html, $sectionName, $hasLabel );
1548
1549 if ( $subsectionHtml ) {
1550 if ( $this->mSubSectionBeforeFields ) {
1551 return $subsectionHtml . "\n" . $html;
1552 } else {
1553 return $html . "\n" . $subsectionHtml;
1554 }
1555 } else {
1556 return $html;
1557 }
1558 }
1559
1567 protected function formatSection( array $fieldsHtml, $sectionName, $anyFieldHasLabel ) {
1569 $html = implode( '', $fieldsHtml );
1570
1571 if ( $displayFormat === 'raw' ) {
1572 return $html;
1573 }
1574
1575 $classes = [];
1576
1577 if ( !$anyFieldHasLabel ) { // Avoid strange spacing when no labels exist
1578 $classes[] = 'mw-htmlform-nolabel';
1579 }
1580
1581 $attribs = [
1582 'class' => implode( ' ', $classes ),
1583 ];
1584
1585 if ( $sectionName ) {
1586 $attribs['id'] = Sanitizer::escapeId( $sectionName );
1587 }
1588
1589 if ( $displayFormat === 'table' ) {
1590 return Html::rawElement( 'table',
1591 $attribs,
1592 Html::rawElement( 'tbody', [], "\n$html\n" ) ) . "\n";
1593 } elseif ( $displayFormat === 'inline' ) {
1594 return Html::rawElement( 'span', $attribs, "\n$html\n" );
1595 } else {
1596 return Html::rawElement( 'div', $attribs, "\n$html\n" );
1597 }
1598 }
1599
1603 public function loadData() {
1604 $fieldData = [];
1605
1606 foreach ( $this->mFlatFields as $fieldname => $field ) {
1607 $request = $this->getRequest();
1608 if ( $field->skipLoadData( $request ) ) {
1609 continue;
1610 } elseif ( !empty( $field->mParams['disabled'] ) ) {
1611 $fieldData[$fieldname] = $field->getDefault();
1612 } else {
1613 $fieldData[$fieldname] = $field->loadDataFromRequest( $request );
1614 }
1615 }
1616
1617 # Filter data.
1618 foreach ( $fieldData as $name => &$value ) {
1619 $field = $this->mFlatFields[$name];
1620 $value = $field->filter( $value, $this->mFlatFields );
1621 }
1622
1623 $this->mFieldData = $fieldData;
1624 }
1625
1633 public function suppressReset( $suppressReset = true ) {
1634 $this->mShowReset = !$suppressReset;
1635
1636 return $this;
1637 }
1638
1648 public function filterDataForSubmit( $data ) {
1649 return $data;
1650 }
1651
1660 public function getLegend( $key ) {
1661 return $this->msg( "{$this->mMessagePrefix}-$key" )->text();
1662 }
1663
1674 public function setAction( $action ) {
1675 $this->mAction = $action;
1676
1677 return $this;
1678 }
1679
1687 public function getAction() {
1688 // If an action is alredy provided, return it
1689 if ( $this->mAction !== false ) {
1690 return $this->mAction;
1691 }
1692
1693 $articlePath = $this->getConfig()->get( 'ArticlePath' );
1694 // Check whether we are in GET mode and the ArticlePath contains a "?"
1695 // meaning that getLocalURL() would return something like "index.php?title=...".
1696 // As browser remove the query string before submitting GET forms,
1697 // it means that the title would be lost. In such case use wfScript() instead
1698 // and put title in an hidden field (see getHiddenFields()).
1699 if ( strpos( $articlePath, '?' ) !== false && $this->getMethod() === 'get' ) {
1700 return wfScript();
1701 }
1702
1703 return $this->getTitle()->getLocalURL();
1704 }
1705
1716 public function setAutocomplete( $autocomplete ) {
1717 $this->mAutocomplete = $autocomplete;
1718
1719 return $this;
1720 }
1721
1728 protected function getMessage( $value ) {
1729 return Message::newFromSpecifier( $value )->setContext( $this );
1730 }
1731}
wfScript( $script='index')
Get the path to a specified script file, respecting file extensions; this is a wrapper around $wgScri...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Throws a warning that $function is deprecated.
if( $line===false) $args
Definition cdb.php:64
The simplest way of implementing IContextSource is to hold a RequestContext as a member variable and ...
getUser()
Get the User object.
getRequest()
Get the WebRequest object.
getConfig()
Get the Config object.
msg()
Get a Message object with context set Parameters are the same as wfMessage()
getOutput()
Get the OutputPage object.
IContextSource $context
getContext()
Get the base IContextSource object.
setContext(IContextSource $context)
Set the IContextSource object.
The parent class to generate form fields.
Object handling generic submission, CSRF protection, layout and other logic for UI forms.
Definition HTMLForm.php:123
setSubmitCallback( $cb)
Set a callback to a function to do something with the form once it's been successfully validated.
Definition HTMLForm.php:646
setHeaderText( $msg, $section=null)
Set header text, inside the form.
Definition HTMLForm.php:736
displayForm( $submitResult)
Display the form (sending to the context's OutputPage object), with an appropriate error message or s...
Definition HTMLForm.php:957
bool string $mAction
Form action URL.
Definition HTMLForm.php:200
setAction( $action)
Set the value for the action attribute of the form.
string array $mTokenSalt
Salt for the edit token.
Definition HTMLForm.php:219
getSubmitText()
Get the text for the submit button, either customised or a default.
setMethod( $method='post')
Set the method used to submit the form.
$mValidationErrorMessage
Definition HTMLForm.php:174
setValidationErrorMessage( $msg)
Set a message to display on a validation error.
Definition HTMLForm.php:660
getMessage( $value)
Turns a *-message parameter (which could be a MessageSpecifier, or a message name,...
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:449
setSubmitName( $name)
setTitle( $t)
Set the title for form submission.
static getClassFromDescriptor( $fieldname, &$descriptor)
Get the HTMLFormField subclass for this descriptor.
Definition HTMLForm.php:421
array $availableSubclassDisplayFormats
Available formats in which to display the form.
Definition HTMLForm.php:252
string $displayFormat
Format in which to display form.
Definition HTMLForm.php:235
__construct( $descriptor, $context=null, $messagePrefix='')
Build a new HTMLForm from an array of field attributes.
Definition HTMLForm.php:291
setTableId( $id)
Set the id of the <table> or outermost <div> element.
getHTML( $submitResult)
Returns the raw HTML generated by the form.
Definition HTMLForm.php:968
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.
setSubmitProgressive()
Identify that the submit button in the form has a progressive action.
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.
$mSubSectionBeforeFields
If true, sections that contain both fields and subsections will render their subsections before their...
Definition HTMLForm.php:228
setDisplayFormat( $format)
Set format in which to display the form.
Definition HTMLForm.php:361
addButton( $data)
Add a button to the form.
Definition HTMLForm.php:899
loadData()
Construct the form fields from the Descriptor array.
getHiddenFields()
Get the hidden fields that should go inside the form.
setSubmitDestructive()
Identify that the submit button in the form has a destructive action.
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:390
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:522
addFooterText( $msg, $section=null)
Add footer text, inside the form.
Definition HTMLForm.php:769
addPostText( $msg)
Add text to the end of the display.
Definition HTMLForm.php:823
getFooterText( $section=null)
Get footer text.
Definition HTMLForm.php:808
addHeaderText( $msg, $section=null)
Add HTML to the header, inside the form.
Definition HTMLForm.php:714
prepareForm()
Prepare form for submission.
Definition HTMLForm.php:474
getTitle()
Get the title.
wasSubmitted()
Test whether the form was considered to have been submitted or not, i.e.
Definition HTMLForm.php:632
getHeaderText( $section=null)
Get header text.
Definition HTMLForm.php:753
tryAuthorizedSubmit()
Try submitting, with edit token check first.
Definition HTMLForm.php:490
setSubmitTooltip( $name)
displaySection( $fields, $sectionName='', $fieldsetIDPrefix='', &$hasUserVisibleFields=false)
setPreText( $msg)
Set the introductory message HTML, overwriting any existing message.
Definition HTMLForm.php:687
addHiddenField( $name, $value, array $attribs=[])
Add a hidden field to the output.
Definition HTMLForm.php:851
bool string $mAutocomplete
Form attribute autocomplete.
Definition HTMLForm.php:207
setFooterText( $msg, $section=null)
Set footer text, inside the form.
Definition HTMLForm.php:791
setMessagePrefix( $p)
Set the prefix for various default messages.
wrapForm( $html)
Wrap the form innards in an actual "<form>" element.
getFormAttributes()
Get HTML attributes for the <form> tag.
Definition HTMLForm.php:991
wrapFieldSetSection( $legend, $section, $attributes)
Wraps the given $section into an user-visible fieldset.
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:540
setTokenSalt( $salt)
Set the salt for the edit token.
Definition HTMLForm.php:939
addPreText( $msg)
Add HTML to introductory message.
Definition HTMLForm.php:700
getErrors( $errors)
Format and display an error message stack.
setName( $name)
suppressReset( $suppressReset=true)
Stop a reset button being shown for this form.
setPostText( $msg)
Set text at the end of the display.
Definition HTMLForm.php:836
static $typeMappings
Definition HTMLForm.php:125
formatSection(array $fieldsHtml, $sectionName, $anyFieldHasLabel)
Put a form section together from the individual fields' HTML, merging it and wrapping.
isVForm()
Test if displayFormat is 'vform'.
Definition HTMLForm.php:400
static factory( $displayFormat)
Construct a HTMLForm object for given display type.
Definition HTMLForm.php:264
array $availableDisplayFormats
Available formats in which to display the form.
Definition HTMLForm.php:241
setSubmitText( $t)
Set the text for the submit button.
setIntro( $msg)
Set the introductory message, overwriting any existing message.
Definition HTMLForm.php:673
getButtons()
Get the submit and (potentially) reset buttons.
trySubmit()
Validate all the fields, and call the submission callback function if everything is kosher.
Definition HTMLForm.php:561
HTMLFormField[] $mFlatFields
Definition HTMLForm.php:166
addHiddenFields(array $fields)
Add an array of hidden fields to the output.
Definition HTMLForm.php:868
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition Html.php:230
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition Html.php:210
static hidden( $name, $value, array $attribs=[])
Convenience function to produce an input element with type=hidden.
Definition Html.php:759
static tooltipAndAccesskeyAttribs( $name, array $msgParams=[])
Returns the attributes for the tooltip and access key.
Definition Linker.php:2337
MediaWiki exception.
The Message class provides methods which fulfil two basic services:
Definition Message.php:159
static escapeId( $id, $options=[])
Given a value, escape it so that it can be used in an id attribute and return it.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:40
isGood()
Returns whether the operation completed and didn't have any error or warnings.
Definition Status.php:132
Represents a title within MediaWiki.
Definition Title.php:34
static submitButton( $value, $attribs=[])
Convenience function to build an HTML submit button When $wgUseMediaWikiUIEverywhere is true it will ...
Definition Xml.php:460
static fieldset( $legend=false, $content=false, $attribs=[])
Shortcut for creating fieldsets.
Definition Xml.php:578
$res
Definition database.txt:21
deferred txt A few of the database updates required by various functions here can be deferred until after the result page is displayed to the user For updating the view updating the linked to tables after a etc PHP does not yet have any way to tell the server to actually return and disconnect while still running these but it might have such a feature in the future We handle these by creating a deferred update object and putting those objects on a global list
Definition deferred.txt:11
design txt This is a brief overview of the new design More thorough and up to date information is available on the documentation wiki at etc Handles the details of getting and saving to the user table of the and dealing with sessions and cookies OutputPage Encapsulates the entire HTML page that will be sent in response to any server request It is used by calling its functions to add text
Definition design.txt:18
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
the array() calling protocol came about after MediaWiki 1.4rc1.
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses after processing & $attribs
Definition hooks.txt:1819
The index of the header message $result[1]=The index of the body text message $result[2 through n]=Parameters passed to body text message. Please note the header message cannot receive/use parameters. 'ImportHandleLogItemXMLTag':When parsing a XML tag in a log item. Return false to stop further processing of the tag $reader:XMLReader object $logInfo:Array of information 'ImportHandlePageXMLTag':When parsing a XML tag in a page. Return false to stop further processing of the tag $reader:XMLReader object & $pageInfo:Array of information 'ImportHandleRevisionXMLTag':When parsing a XML tag in a page revision. Return false to stop further processing of the tag $reader:XMLReader object $pageInfo:Array of page information $revisionInfo:Array of revision information 'ImportHandleToplevelXMLTag':When parsing a top level XML tag. Return false to stop further processing of the tag $reader:XMLReader object 'ImportHandleUploadXMLTag':When parsing a XML tag in a file upload. Return false to stop further processing of the tag $reader:XMLReader object $revisionInfo:Array of information 'ImportLogInterwikiLink':Hook to change the interwiki link used in log entries and edit summaries for transwiki imports. & $fullInterwikiPrefix:Interwiki prefix, may contain colons. & $pageTitle:String that contains page title. 'ImportSources':Called when reading from the $wgImportSources configuration variable. Can be used to lazy-load the import sources list. & $importSources:The value of $wgImportSources. Modify as necessary. See the comment in DefaultSettings.php for the detail of how to structure this array. 'InfoAction':When building information to display on the action=info page. $context:IContextSource object & $pageInfo:Array of information 'InitializeArticleMaybeRedirect':MediaWiki check to see if title is a redirect. & $title:Title object for the current page & $request:WebRequest & $ignoreRedirect:boolean to skip redirect check & $target:Title/string of redirect target & $article:Article object 'InternalParseBeforeLinks':during Parser 's internalParse method before links but after nowiki/noinclude/includeonly/onlyinclude and other processings. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InternalParseBeforeSanitize':during Parser 's internalParse method just before the parser removes unwanted/dangerous HTML tags and after nowiki/noinclude/includeonly/onlyinclude and other processings. Ideal for syntax-extensions after template/parser function execution which respect nowiki and HTML-comments. & $parser:Parser object & $text:string containing partially parsed text & $stripState:Parser 's internal StripState object 'InterwikiLoadPrefix':When resolving if a given prefix is an interwiki or not. Return true without providing an interwiki to continue interwiki search. $prefix:interwiki prefix we are looking for. & $iwData:output array describing the interwiki with keys iw_url, iw_local, iw_trans and optionally iw_api and iw_wikiid. 'InvalidateEmailComplete':Called after a user 's email has been invalidated successfully. $user:user(object) whose email is being invalidated 'IRCLineURL':When constructing the URL to use in an IRC notification. Callee may modify $url and $query, URL will be constructed as $url . $query & $url:URL to index.php & $query:Query string $rc:RecentChange object that triggered url generation 'IsFileCacheable':Override the result of Article::isFileCacheable()(if true) & $article:article(object) being checked 'IsTrustedProxy':Override the result of IP::isTrustedProxy() & $ip:IP being check & $result:Change this value to override the result of IP::isTrustedProxy() 'IsUploadAllowedFromUrl':Override the result of UploadFromUrl::isAllowedUrl() $url:URL used to upload from & $allowed:Boolean indicating if uploading is allowed for given URL 'isValidEmailAddr':Override the result of Sanitizer::validateEmail(), for instance to return false if the domain name doesn 't match your organization. $addr:The e-mail address entered by the user & $result:Set this and return false to override the internal checks 'isValidPassword':Override the result of User::isValidPassword() $password:The password entered by the user & $result:Set this and return false to override the internal checks $user:User the password is being validated for 'Language::getMessagesFileName':$code:The language code or the language we 're looking for a messages file for & $file:The messages file path, you can override this to change the location. 'LanguageGetMagic':DEPRECATED! Use $magicWords in a file listed in $wgExtensionMessagesFiles instead. Use this to define synonyms of magic words depending of the language & $magicExtensions:associative array of magic words synonyms $lang:language code(string) 'LanguageGetNamespaces':Provide custom ordering for namespaces or remove namespaces. Do not use this hook to add namespaces. Use CanonicalNamespaces for that. & $namespaces:Array of namespaces indexed by their numbers 'LanguageGetSpecialPageAliases':DEPRECATED! Use $specialPageAliases in a file listed in $wgExtensionMessagesFiles instead. Use to define aliases of special pages names depending of the language & $specialPageAliases:associative array of magic words synonyms $lang:language code(string) 'LanguageGetTranslatedLanguageNames':Provide translated language names. & $names:array of language code=> language name $code:language of the preferred translations 'LanguageLinks':Manipulate a page 's language links. This is called in various places to allow extensions to define the effective language links for a page. $title:The page 's Title. & $links:Associative array mapping language codes to prefixed links of the form "language:title". & $linkFlags:Associative array mapping prefixed links to arrays of flags. Currently unused, but planned to provide support for marking individual language links in the UI, e.g. for featured articles. 'LanguageSelector':Hook to change the language selector available on a page. $out:The output page. $cssClassName:CSS class name of the language selector. 'LinkBegin':Used when generating internal and interwiki links in Linker::link(), before processing starts. Return false to skip default processing and return $ret. See documentation for Linker::link() for details on the expected meanings of parameters. $skin:the Skin object $target:the Title that the link is pointing to & $html:the contents that the< a > tag should have(raw HTML) $result
Definition hooks.txt:1799
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a local account incomplete not yet checked for validity & $retval
Definition hooks.txt:268
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition hooks.txt:2530
null means default in associative array with keys and values unescaped Should be merged with default with a value of false meaning to suppress the attribute in associative array with keys and values unescaped noclasses just before the function returns a value If you return an< a > element with HTML attributes $attribs and contents $html will be returned If you return $ret will be returned and may include noclasses & $html
Definition hooks.txt:1818
Allows to change the fields on the form that will be generated $name
Definition hooks.txt:314
usually copyright or history_copyright This message must be in HTML not wikitext if the section is included from a template $section
Definition hooks.txt:2727
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition injection.txt:37
Interface for objects which can provide a MediaWiki context on request.