MediaWiki master
LoginSignupSpecialPage.php
Go to the documentation of this file.
1<?php
10namespace MediaWiki\SpecialPage;
11
12use Exception;
13use LogicException;
38use StatusValue;
39use Wikimedia\ScopedCallback;
40
48
56 protected string $mReturnTo;
62 protected string $mReturnToQuery;
69 protected string $mReturnToAnchor;
76 protected bool $mAlwaysShowLogin;
77
79 protected $mPosted;
81 protected $mAction;
83 protected $mToken;
85 protected $mStickHTTPS;
87 protected $mFromHTTP;
89 protected $mEntryError = '';
91 protected $mEntryErrorType = 'error';
93 protected $loginHelper = null;
94
96 protected $mLoaded = false;
98 protected $mLoadedRequest = false;
102 private $reasonValidatorResult = null;
103
105 protected $securityLevel;
106
112 protected $targetUser;
113
115 protected $authForm;
116
120 abstract protected function isSignup();
121
128 abstract protected function successfulAction( $direct = false, $extraMessages = null );
129
136 abstract protected function logAuthResult( $success, UserIdentity $performer, $status = null );
137
139 protected function setRequest( array $data, $wasPosted = null ) {
140 parent::setRequest( $data, $wasPosted );
141 $this->mLoadedRequest = false;
142 }
143
148 private function getLoginHelper(): LoginHelper {
149 if ( $this->loginHelper === null ) {
150 $this->loginHelper = new LoginHelper( $this->getContext() );
151 }
152 return $this->loginHelper;
153 }
154
158 private function loadRequestParameters() {
159 if ( $this->mLoadedRequest ) {
160 return;
161 }
162 $this->mLoadedRequest = true;
163 $request = $this->getRequest();
164
165 $this->mPosted = $request->wasPosted();
166 $this->mAction = $request->getRawVal( 'action' );
167 $this->mFromHTTP = $request->getBool( 'fromhttp', false )
168 || $request->getBool( 'wpFromhttp', false );
169 $this->mStickHTTPS = $this->getConfig()->get( MainConfigNames::ForceHTTPS )
170 || ( !$this->mFromHTTP && $request->getProtocol() === 'https' )
171 || $request->getBool( 'wpForceHttps', false );
172 $this->mReturnTo = $request->getVal( 'returnto', '' );
173 $this->mReturnToQuery = $request->getVal( 'returntoquery', '' );
174 $this->mReturnToAnchor = $request->getVal( 'returntoanchor', '' );
175 $this->mAlwaysShowLogin = $request->getBool( 'alwaysShowLogin' );
176 }
177
183 protected function load( $subPage ) {
184 $this->loadRequestParameters();
185 if ( $this->mLoaded ) {
186 return;
187 }
188 $this->mLoaded = true;
189 $request = $this->getRequest();
190
191 // set securityLevel early, loadAuth might rely on it
192 $securityLevel = $this->getRequest()->getText( 'force' );
193 if (
194 $securityLevel &&
195 MediaWikiServices::getInstance()->getAuthManager()->securitySensitiveOperationStatus(
196 $securityLevel ) === AuthManager::SEC_REAUTH
197 ) {
198 $this->securityLevel = $securityLevel;
199 }
200
201 $this->loadAuth( $subPage );
202
203 $this->mToken = $request->getVal( $this->getTokenName() );
204
205 // Show an error or warning or a notice passed on from a previous page
206 $entryError = $this->msg( $request->getVal( 'error', '' ) );
207 $entryWarning = $this->msg( $request->getVal( 'warning', '' ) );
208 $entryNotice = $this->msg( $request->getVal( 'notice', '' ) );
209 // bc: provide login link as a parameter for messages where the translation
210 // was not updated
211 $loginreqlink = $this->getLinkRenderer()->makeKnownLink(
212 $this->getPageTitle(),
213 $this->msg( 'loginreqlink' )->text(),
214 [],
215 $this->getPreservedParams( [ 'reset' => true ] )
216 );
217
218 // Only show valid error or warning messages.
219 $validErrorMessages = LoginHelper::getValidErrorMessages();
220 if ( $entryError->exists()
221 && in_array( $entryError->getKey(), $validErrorMessages, true )
222 ) {
223 $this->mEntryErrorType = 'error';
224 $this->mEntryError = $entryError->rawParams( $loginreqlink )->parse();
225
226 } elseif ( $entryWarning->exists()
227 && in_array( $entryWarning->getKey(), $validErrorMessages, true )
228 ) {
229 $this->mEntryErrorType = 'warning';
230 $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->parse();
231 } elseif ( $entryNotice->exists()
232 && in_array( $entryNotice->getKey(), $validErrorMessages, true )
233 ) {
234 $this->mEntryErrorType = 'notice';
235 $this->mEntryError = $entryNotice->parse();
236 }
237
238 # 1. When switching accounts, it sucks to get automatically logged out
239 # 2. Do not return to PasswordReset after a successful password change
240 # but goto Wiki start page (Main_Page) instead ( T35997 )
241 $returnToTitle = Title::newFromText( $this->mReturnTo );
242 if ( is_object( $returnToTitle )
243 && ( $returnToTitle->isSpecial( 'Userlogout' )
244 || $returnToTitle->isSpecial( 'PasswordReset' ) )
245 ) {
246 $this->mReturnTo = '';
247 $this->mReturnToQuery = '';
248 }
249 }
250
252 protected function getPreservedParams( $options = [] ) {
253 $params = $options['params'] ?? [];
254
255 // Override returnto* with their property-based values, to account for the
256 // special-casing in load().
257 $this->loadRequestParameters();
258 $properties = [
259 'returnto' => 'mReturnTo',
260 'returntoquery' => 'mReturnToQuery',
261 'returntoanchor' => 'mReturnToAnchor',
262 ];
263 foreach ( $properties as $key => $prop ) {
264 $value = $this->$prop;
265 if ( $value !== '' ) {
266 $params[$key] = $value;
267 } else {
268 unset( $params[$key] );
269 }
270 }
271
272 if ( $this->mAlwaysShowLogin ) {
273 $params['alwaysShowLogin'] = '1';
274 }
275 if ( $this->getConfig()->get( MainConfigNames::SecureLogin ) && !$this->isSignup() ) {
276 $params['fromhttp'] = $this->mFromHTTP ? '1' : null;
277 }
278
279 $options['params'] = $params;
280 return parent::getPreservedParams( $options );
281 }
282
284 protected function beforeExecute( $subPage ) {
285 // finish initializing the class before processing the request - T135924
286 $this->loadRequestParameters();
287 return parent::beforeExecute( $subPage );
288 }
289
293 public function execute( $subPage ) {
294 if ( $this->mPosted ) {
295 $timer = MediaWikiServices::getInstance()->getStatsFactory()
296 ->getTiming( 'auth_specialpage_executeTiming_seconds' )
297 ->start();
298 $profilingScope = new ScopedCallback( function () use ( $timer ) {
299 $timer
300 ->setLabel( 'action', $this->authAction )
301 ->stop();
302 } );
303 }
304
305 $authManager = MediaWikiServices::getInstance()->getAuthManager();
306 $session = $this->getRequest()->getSession();
307
308 // Before persisting, set the login token to avoid double writes
309 $this->getToken();
310
311 // Session data is used for various things in the authentication process, so we must make
312 // sure a session cookie or some equivalent mechanism is set.
313 $session->persist();
314 // Explicitly disable cache to ensure cookie blocks may be set (T152462).
315 // (Technically redundant with sessions persisting from this page.)
316 $this->getOutput()->disableClientCache();
317
318 $this->load( $subPage );
319
320 // Do this early, so that it affects how error pages are rendered too
321 if ( $this->getLoginHelper()->isDisplayModePopup() ) {
322 // Replace the default skin with a "micro-skin" that omits most of the interface. (T362706)
323 // In the future, we might allow normal skins to serve this mode too, if they advise that
324 // they support it by setting a skin option, so that colors and fonts could stay consistent.
325 $skinFactory = MediaWikiServices::getInstance()->getSkinFactory();
326 $this->getContext()->setSkin( $skinFactory->makeSkin( 'authentication-popup' ) );
327 }
328
329 $this->setHeaders();
330 $this->checkPermissions();
331
332 // Make sure the system configuration allows log in / sign up
333 if ( !$this->isSignup() && !$authManager->canAuthenticateNow() ) {
334 if ( !$session->canSetUser() ) {
335 throw new ErrorPageError( 'cannotloginnow-title', 'cannotloginnow-text', [
336 $session->getProvider()->describe( $this->getLanguage() )
337 ] );
338 }
339 throw new ErrorPageError( 'cannotlogin-title', 'cannotlogin-text' );
340 } elseif ( $this->isSignup() && !$authManager->canCreateAccounts() ) {
341 throw new ErrorPageError( 'cannotcreateaccount-title', 'cannotcreateaccount-text' );
342 }
343
344 /*
345 * In the case where the user is already logged in, and was redirected to
346 * the login form from a page that requires login, do not show the login
347 * page. The use case scenario for this is when a user opens a large number
348 * of tabs, is redirected to the login page on all of them, and then logs
349 * in on one, expecting all the others to work properly.
350 *
351 * However, do show the form if it was visited intentionally (no 'returnto'
352 * is present). People who often switch between several accounts have grown
353 * accustomed to this behavior.
354 *
355 * For temporary users, the form is always shown, since the UI presents
356 * temporary users as not logged in and offers to discard their temporary
357 * account by logging in.
358 *
359 * Also make an exception when force=<level> is set in the URL, which means the user must
360 * reauthenticate for security reasons; for POST (although it shouldn't really happen);
361 * and allow an explicit URL parameter override.
362 */
363 if ( !$this->isSignup() && !$this->mPosted && !$this->securityLevel &&
364 ( $this->mReturnTo !== '' || $this->mReturnToQuery !== '' ) &&
365 !$this->mAlwaysShowLogin &&
366 !$this->getUser()->isTemp() && $this->getUser()->isRegistered()
367 ) {
368 $this->successfulAction();
369 return;
370 }
371
372 // If logging in and not on HTTPS, either redirect to it or offer a link.
373 if ( $this->getRequest()->getProtocol() !== 'https' ) {
374 $title = $this->getFullTitle();
375 $query = $this->getPreservedParams() + [
376 'title' => null,
377 ( $this->mEntryErrorType === 'error' ? 'error'
378 : 'warning' ) => $this->mEntryError,
379 ] + $this->getRequest()->getQueryValues();
380 $url = $title->getFullURL( $query, false, PROTO_HTTPS );
381 if ( $this->getConfig()->get( MainConfigNames::SecureLogin ) && !$this->mFromHTTP ) {
382 // Avoid infinite redirect
383 $url = wfAppendQuery( $url, 'fromhttp=1' );
384 $this->getOutput()->redirect( $url );
385 // Since we only do this redir to change proto, always vary
386 $this->getOutput()->addVaryHeader( 'X-Forwarded-Proto' );
387
388 return;
389 } else {
390 // A wiki without HTTPS login support should set $wgServer to
391 // http://somehost, in which case the secure URL generated
392 // above won't actually start with https://
393 if ( str_starts_with( $url, 'https://' ) ) {
394 $this->mSecureLoginUrl = $url;
395 }
396 }
397 }
398
399 if ( !$this->isActionAllowed( $this->authAction ) ) {
400 // FIXME how do we explain this to the user? can we handle session loss better?
401 // messages used: authpage-cannot-login, authpage-cannot-login-continue,
402 // authpage-cannot-create, authpage-cannot-create-continue
403 $this->mainLoginForm( [], 'authpage-cannot-' . $this->authAction );
404 return;
405 }
406
407 if ( $this->canBypassForm( $button_name ) ) {
408 $this->setRequest( [], true );
409 $this->getRequest()->setVal( $this->getTokenName(), $this->getToken() );
410 if ( $button_name ) {
411 $this->getRequest()->setVal( $button_name, true );
412 }
413 }
414 $performer = $this->getUser();
415 $status = $this->trySubmit();
416
417 if ( !$status || !$status->isGood() ) {
418 $this->mainLoginForm( $this->authRequests, $status ? $status->getMessage() : '', 'error' );
419 return;
420 }
421
423 $response = $status->getValue();
424
425 $returnToUrl = $this->getPageTitle( 'return' )
426 ->getFullURL( $this->getPreservedParams( [ 'withToken' => true ] ), false, PROTO_HTTPS );
427 switch ( $response->status ) {
428 case AuthenticationResponse::PASS:
429 $this->logAuthResult( true, $performer );
430 $this->proxyAccountCreation = $this->isSignup() && $this->getUser()->isNamed();
431 $this->targetUser = User::newFromName( $response->username );
432
433 if (
434 !$this->proxyAccountCreation
435 && $response->loginRequest
436 && $authManager->canAuthenticateNow()
437 ) {
438 // successful registration; log the user in instantly
439 $response2 = $authManager->beginAuthentication( [ $response->loginRequest ],
440 $returnToUrl );
441 if ( $response2->status !== AuthenticationResponse::PASS ) {
442 LoggerFactory::getInstance( 'login' )
443 ->error( 'Could not log in after account creation' );
444 $this->successfulAction( true, Status::newFatal( 'createacct-loginerror' ) );
445 break;
446 }
447 }
448
449 if ( !$this->proxyAccountCreation ) {
450 $context = RequestContext::getMain();
451 $localContext = $this->getContext();
452 if ( $context !== $localContext ) {
453 // remove AuthManagerSpecialPage context hack
454 $this->setContext( $context );
455 }
456 // Ensure that the context user is the same as the session user.
457 $this->getAuthManager()->setRequestContextUserFromSessionUser();
458 }
459
460 $this->successfulAction( true );
461 break;
462 case AuthenticationResponse::FAIL:
463 // fall through
464 case AuthenticationResponse::RESTART:
465 $this->authForm = null;
466 if ( $response->status === AuthenticationResponse::FAIL ) {
467 $action = $this->getDefaultAction( $subPage );
468 $messageType = 'error';
469 } else {
470 $action = $this->getContinueAction( $this->authAction );
471 $messageType = 'warning';
472 }
473 $this->logAuthResult( false, $performer, $response->message ? $response->message->getKey() : '-' );
474 $this->loadAuth( $subPage, $action, true );
475 $this->mainLoginForm( $this->authRequests, $response->message, $messageType );
476 break;
477 case AuthenticationResponse::REDIRECT:
478 $this->authForm = null;
479 $this->getOutput()->redirect( $response->redirectTarget );
480 break;
481 case AuthenticationResponse::UI:
482 $this->authForm = null;
483 $this->authAction = $this->isSignup() ? AuthManager::ACTION_CREATE_CONTINUE
484 : AuthManager::ACTION_LOGIN_CONTINUE;
485 $this->authRequests = $response->neededRequests;
486 $this->mainLoginForm( $response->neededRequests, $response->message, $response->messageType );
487 break;
488 default:
489 throw new LogicException( 'invalid AuthenticationResponse' );
490 }
491 }
492
494 protected function getAuthenticationRequests( $action, ?UserIdentity $user = null ) {
495 $options = [];
496 if ( $action === AuthManager::ACTION_LOGIN && $this->securityLevel !== null ) {
497 if ( $this->getUser()->isRegistered() ) {
498 $options['securityLevel'] = $this->securityLevel;
499 } else {
500 // TODO might be nice to show an error. For now just do nothing,
501 // the user will be redirected after login to the reauth form anyway.
502 }
503 }
504 return $this->getAuthManager()->getAuthenticationRequests( $action,
505 $user, $options );
506 }
507
521 private function canBypassForm( &$button_name ) {
522 $button_name = null;
523 if ( $this->isContinued() ) {
524 return false;
525 }
526 $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
527 foreach ( $fields as $fieldname => $field ) {
528 if ( !isset( $field['type'] ) ) {
529 return false;
530 }
531 if ( !empty( $field['skippable'] ) ) {
532 continue;
533 }
534 if ( $field['type'] === 'button' ) {
535 if ( $button_name !== null ) {
536 $button_name = null;
537 return false;
538 } else {
539 $button_name = $fieldname;
540 }
541 } elseif ( $field['type'] !== 'null' ) {
542 return false;
543 }
544 }
545 return true;
546 }
547
557 protected function showSuccessPage(
558 $type, $title, $msgname, $injected_html, $extraMessages
559 ) {
560 $out = $this->getOutput();
561 $out->setPageTitleMsg( $title );
562 if ( $msgname ) {
563 $out->addWikiMsg( $msgname, wfEscapeWikiText( $this->getUser()->getName() ) );
564 }
565 if ( $extraMessages ) {
566 $extraMessages = Status::wrap( $extraMessages );
567 $out->addWikiTextAsInterface(
568 $extraMessages->getWikiText( false, false, $this->getLanguage() )
569 );
570 }
571
572 $out->addHTML( $injected_html );
573
574 $helper = new LoginHelper( $this->getContext() );
575 $helper->showReturnToPage( $type, $this->mReturnTo, $this->mReturnToQuery,
576 $this->mStickHTTPS, $this->mReturnToAnchor );
577 }
578
592 protected function mainLoginForm( array $requests, $msg = '', $msgtype = 'error' ) {
593 $user = $this->getUser();
594 $out = $this->getOutput();
595
596 // FIXME how to handle empty $requests - restart, or no form, just an error message?
597 // no form would be better for no session type errors, restart is better when can* fails.
598 if ( !$requests ) {
599 $this->authAction = $this->getDefaultAction( $this->subPage );
600 $this->authForm = null;
601 $requests = $this->getAuthenticationRequests( $this->authAction, $user );
602 }
603
604 // Generic styles and scripts for both login and signup form
605 $out->addModuleStyles( [
606 'mediawiki.special.userlogin.common.styles',
607 'mediawiki.codex.messagebox.styles'
608 ] );
609 if ( $this->isSignup() ) {
610 // Additional styles and scripts for signup form
611 $out->addModules( 'mediawiki.special.createaccount' );
612 $out->addModuleStyles( [
613 'mediawiki.special.userlogin.signup.styles'
614 ] );
615 $userPolicyTitleUrl = false;
616 if ( !$this->msg( 'createacct-helpusername-url' )->inContentLanguage()->isDisabled() ) {
617 $titleFactory = MediaWikiServices::getInstance()->getTitleFactory();
618 $userPolicyTitle = $titleFactory->newFromText(
619 $this->msg( 'createacct-helpusername-url' )->inContentLanguage()->text(),
620 );
621 if ( $userPolicyTitle && ( $userPolicyTitle->exists() || $userPolicyTitle->isExternal() ) ) {
622 $userPolicyTitleUrl = $userPolicyTitle->getFullURL();
623 }
624 }
625 $out->addJsConfigVars( [
626 'wgCreateAccountUsernamePolicyUrl' => $userPolicyTitleUrl,
627 'wgCreateAccountUsernamePolicyBulletsHtml' => $this->getCreateAccountUsernamePolicyBulletsHtml()
628 ] );
629 } else {
630 // Additional styles for login form
631 $out->addModuleStyles( [
632 'mediawiki.special.userlogin.login.styles'
633 ] );
634 }
635 $out->disallowUserJs(); // just in case...
636
637 $form = $this->getAuthForm( $requests, $this->authAction );
638 $form->prepareForm();
639
640 $submitStatus = Status::newGood();
641 if ( $msg && $msgtype === 'warning' ) {
642 $submitStatus->warning( $msg );
643 } elseif ( $msg && $msgtype === 'error' ) {
644 $submitStatus->fatal( $msg );
645
646 // T409431 Pass information about the error to the frontend to
647 // be logged by Javascript instrumentation handlers.
648 $this->getOutput()->addJsConfigVars(
649 'wgErrorPageMessageKey',
650 is_string( $msg ) ? $msg : $msg->getKey()
651 );
652 }
653
654 // warning header for non-standard workflows (e.g. security reauthentication)
655 if ( $this->getUser()->isNamed() && !$this->isContinued() ) {
656 if ( !$this->isSignup() && $this->securityLevel ) {
657 $securityLevelLower = strtolower( $this->securityLevel );
658 $reauthSubaction = $this->getRequest()->getRawVal( 'reauthSubaction' );
659 if (
660 $reauthSubaction !== null &&
661 $this->msg( "userlogin-reauth-banner-$securityLevelLower-$reauthSubaction" )->exists()
662 ) {
663 $submitStatus->warning( "userlogin-reauth-banner-$securityLevelLower-$reauthSubaction" );
664 } elseif ( $this->msg( "userlogin-reauth-banner-$securityLevelLower" )->exists() ) {
665 $submitStatus->warning( "userlogin-reauth-banner-$securityLevelLower" );
666 } else {
667 $submitStatus->warning( 'userlogin-reauth-banner-generic', $this->securityLevel );
668 }
669
670 // Build cancel link
671 $cancelLinkAttribs = [ 'class' => 'mw-authentication-popup-cancel' ];
672 if ( $this->getLoginHelper()->isDisplayModePopup() ) {
673 $cancelLinkAttribs['class'] .= ' mw-authentication-popup-link';
674 $this->getOutput()->addModules( 'mediawiki.authenticationPopup.cancel' );
675 }
676 $returnTitle = Title::newFromText( $this->mReturnTo );
677 if ( $returnTitle && !$returnTitle->isSpecialPage() ) {
678 $cancelLink = $this->getLinkRenderer()->makeLink(
679 $returnTitle->createFragmentTarget( $this->mReturnToAnchor ),
680 $this->msg( 'userlogin-reauth-description-link' )->text(),
681 $cancelLinkAttribs,
682 wfCgiToArray( $this->mReturnToQuery )
683 );
684 } else {
685 $cancelLink = $this->getLinkRenderer()->makeLink(
686 Title::newMainPage(),
687 $this->msg( 'userlogin-reauth-description-link' )->text(),
688 $cancelLinkAttribs
689 );
690 }
691
692 $form->addHeaderHtml(
693 $this->msg( 'userlogin-reauth-description' )
694 ->rawParams( $cancelLink )
695 ->parseAsBlock()
696 );
697 } else {
698 // User is accessing the login or signup page while already logged in.
699 // Add a big warning and a button to leave this page (T284927),
700 // but allow using the form if they really want to.
701 $form->addPreHtml(
702 Html::warningBox( $this->msg(
703 $this->isSignup() ? 'createacct-loggedin' : 'userlogin-loggedin',
704 $this->getUser()->getName()
705 )->parse() ) .
706 '<div class="cdx-field"><div class="cdx-field__control">' .
707 Html::element( 'a',
708 [
709 'class' => 'cdx-button cdx-button--fake-button cdx-button--fake-button--enabled ' .
710 'cdx-button--action-progressive cdx-button--weight-primary mw-htmlform-submit ' .
711 ( $this->getLoginHelper()->isDisplayModePopup() ? 'mw-authentication-popup-link' : '' ),
712 'href' => ( Title::newFromText( $this->mReturnTo ) ?: Title::newMainPage() )
713 ->createFragmentTarget( $this->mReturnToAnchor )->getLinkURL( $this->mReturnToQuery ),
714 ],
715 $this->msg(
716 $this->isSignup() ? 'createacct-loggedin-continue-as' : 'userlogin-loggedin-continue-as',
717 $this->getUser()->getName()
718 )->text()
719 ) .
720 '</div></div>' .
721 Html::element( 'h2', [], $this->msg(
722 $this->isSignup() ? 'createacct-loggedin-heading' : 'userlogin-loggedin-heading'
723 )->text() ) .
724 $this->msg(
725 $this->isSignup() ? 'createacct-loggedin-prompt' : 'userlogin-loggedin-prompt'
726 )->parseAsBlock()
727 );
728 }
729 }
730
731 $formHtml = $form->getHTML( $submitStatus );
732
733 $out->addHTML( $this->getPageHtml( $formHtml ) );
734 }
735
742 protected function getPageHtml( $formHtml ) {
743 $loginPrompt = $this->isSignup() || $this->getLoginHelper()->isDisplayModePopup() || $this->isContinued()
744 ? ''
745 : Html::rawElement( 'div', [ 'id' => 'userloginprompt' ], $this->msg( 'loginprompt' )->parseAsBlock() );
746 $languageLinks = $this->getConfig()->get( MainConfigNames::LoginLanguageSelector )
747 ? $this->makeLanguageSelector() : '';
748 $signupStartMsg = $this->msg( 'signupstart' );
749 $signupStart = ( $this->isSignup() && !$signupStartMsg->isDisabled() )
750 ? Html::rawElement( 'div', [ 'id' => 'signupstart' ], $signupStartMsg->parseAsBlock() ) : '';
751 if ( $languageLinks ) {
752 $languageLinks = Html::rawElement( 'div', [ 'id' => 'languagelinks' ],
753 Html::rawElement( 'p', [], $languageLinks )
754 );
755 }
756 if ( $this->getUser()->isTemp() ) {
757 $noticeHtml = $this->getNoticeHtml();
758 } else {
759 $noticeHtml = '';
760 }
761 $formBlock = Html::rawElement( 'div', [ 'id' => 'userloginForm' ], $formHtml );
762 $formAndBenefits = $formBlock;
763 if ( $this->isSignup() && $this->showExtraInformation() && !$this->getUser()->isNamed() ) {
764 $benefitsContainerHtml = null;
765 $info = [
766 'context' => $this->getContext(),
767 'form' => $this->authForm,
768 ];
769 $options = [
770 'beforeForm' => false,
771 ];
772 $this->getHookRunner()->onSpecialCreateAccountBenefits(
773 $benefitsContainerHtml, $info, $options
774 );
775 $benefitsContainerHtml ??= '';
776 $formAndBenefits = $options['beforeForm']
777 ? ( $benefitsContainerHtml . $formBlock )
778 : ( $formBlock . $benefitsContainerHtml );
779 }
780
781 return $loginPrompt
782 . $languageLinks
783 . $signupStart
784 . $noticeHtml
785 . Html::rawElement( 'div', [ 'class' => 'mw-ui-container' ],
786 $formAndBenefits
787 );
788 }
789
796 protected function getAuthForm( array $requests, $action ) {
797 // FIXME merge this with parent
798
799 if ( $this->authForm ) {
800 return $this->authForm;
801 }
802
803 $usingHTTPS = $this->getRequest()->getProtocol() === 'https';
804
805 // get basic form description from the auth logic
806 $fieldInfo = AuthenticationRequest::mergeFieldInfo( $requests );
807 // this will call onAuthChangeFormFields()
808 $formDescriptor = $this->fieldInfoToFormDescriptor( $requests, $fieldInfo, $this->authAction );
809 $this->postProcessFormDescriptor( $formDescriptor, $requests );
810
811 $context = $this->getContext();
812 if ( $context->getRequest() !== $this->getRequest() ) {
813 // We have overridden the request, need to make sure the form uses that too.
814 $context = new DerivativeContext( $this->getContext() );
815 $context->setRequest( $this->getRequest() );
816 }
817 $form = HTMLForm::factory( 'codex', $formDescriptor, $context );
818
819 $form->addHiddenField( 'authAction', $this->authAction );
820 $form->addHiddenField( 'force', $this->securityLevel );
821 $form->addHiddenField( $this->getTokenName(), $this->getToken()->toString() );
822 $config = $this->getConfig();
823 if ( $config->get( MainConfigNames::SecureLogin ) &&
824 !$config->get( MainConfigNames::ForceHTTPS ) ) {
825 // If using HTTPS coming from HTTP, then the 'fromhttp' parameter must be preserved
826 if ( !$this->isSignup() ) {
827 $form->addHiddenField( 'wpForceHttps', (int)$this->mStickHTTPS );
828 $form->addHiddenField( 'wpFromhttp', $usingHTTPS );
829 }
830 }
831
832 $form->setAction( $this->getPageTitle()->getLocalURL( $this->getPreservedParams(
833 // We have manually set authAction above, so we don't need it in the action URL.
834 [ 'reset' => true ]
835 ) ) );
836 $form->setName( 'userlogin' . ( $this->isSignup() ? '2' : '' ) );
837 if ( $this->isSignup() ) {
838 $form->setId( 'userlogin2' );
839 }
840
841 $form->suppressDefaultSubmit();
842
843 $this->authForm = $form;
844
845 return $form;
846 }
847
849 public function onAuthChangeFormFields(
850 array $requests, array $fieldInfo, array &$formDescriptor, $action
851 ) {
852 $formDescriptor = self::mergeDefaultFormDescriptor( $fieldInfo, $formDescriptor,
853 $this->getFieldDefinitions( $fieldInfo, $requests ) );
854 }
855
862 protected function showExtraInformation() {
863 return $this->authAction !== $this->getContinueAction( $this->authAction )
864 && ( !$this->securityLevel || !$this->getUser()->isNamed() );
865 }
866
876 private function getCreateAccountUsernamePolicyBulletsHtml(): array {
877 return [
878 $this->msg( 'createacct-username-policy-popover-bullet1' )->parse(),
879 $this->msg( 'createacct-username-policy-popover-bullet2' )->parse(),
880 $this->msg( 'createacct-username-policy-popover-bullet3' )->parse(),
881 ];
882 }
883
892 protected function getFieldDefinitions( array $fieldInfo, array $requests ) {
893 $isLoggedIn = $this->getUser()->isRegistered();
894 $continuePart = $this->isContinued() ? 'continue-' : '';
895 $anotherPart = $isLoggedIn ? 'another-' : '';
896 // @phan-suppress-next-line PhanUndeclaredMethod
897 $expiration = $this->getRequest()->getSession()->getProvider()->getRememberUserDuration();
898 $expirationDays = ceil( $expiration / ( 3600 * 24 ) );
899 $secureLoginLink = '';
900 if ( $this->mSecureLoginUrl ) {
901 $secureLoginLink = Html::rawElement( 'a', [
902 'href' => $this->mSecureLoginUrl,
903 'class' => 'mw-login-flush-right mw-secure',
904 ], Html::element( 'span', [ 'class' => 'mw-secure--icon' ] ) .
905 $this->msg( 'userlogin-signwithsecure' )->parse() );
906 }
907
908 if ( $this->isSignup() ) {
909 $config = $this->getConfig();
910 $usernameHelpButton = Html::rawElement(
911 'button',
912 [
913 'id' => 'mw-username-help',
914 'type' => 'button',
915 'class' => 'cdx-button cdx-button--icon-only cdx-button--weight-quiet cdx-button--size-small',
916 'aria-label' => $this->msg( 'userlogin-yourname-desc-button-a11y-label' )->text(),
917 ],
918 Html::element( 'span', [ 'class' => 'cdx-button__icon' ] )
919 );
920 $hideIf = isset( $fieldInfo['mailpassword'] ) ? [ 'hide-if' => [ '===', 'mailpassword', '1' ] ] : [];
921 $fieldDefinitions = [
922 'username' => [
923 'label-raw' => $this->msg( 'userlogin-yourname' )->escaped(),
924 'id' => 'wpName2',
925 'placeholder-message' => $isLoggedIn ? 'createacct-another-username-ph'
926 : 'userlogin-yourname-ph',
927 'description-raw' => $this->msg( 'userlogin-yourname-desc' )->escaped() . $usernameHelpButton,
928 'cssclass' => 'mw-createacct-username',
929 ],
930 'mailpassword' => [
931 // create account without providing password, a temporary one will be mailed
932 'type' => 'check',
933 'label-message' => 'createaccountmail',
934 'name' => 'wpCreateaccountMail',
935 'id' => 'wpCreateaccountMail',
936 ],
937 'password' => [
938 'id' => 'wpPassword2',
939 'autocomplete' => 'new-password',
940 'placeholder-message' => 'createacct-yourpassword-ph',
941 'help-message' => '',
942 'end-icon-class' => 'mw-password-reveal-icon'
943 ] + $hideIf,
944 'domain' => [],
945 'retype' => [
946 'type' => 'password',
947 'label-message' => 'createacct-yourpasswordagain',
948 'id' => 'wpRetype',
949 'cssclass' => 'loginPassword',
950 'size' => 20,
951 'autocomplete' => 'new-password',
952 'validation-callback' => function ( $value, $alldata ) {
953 if ( empty( $alldata['mailpassword'] ) && !empty( $alldata['password'] ) ) {
954 if ( !$value ) {
955 return $this->msg( 'htmlform-required' );
956 } elseif ( $value !== $alldata['password'] ) {
957 return $this->msg( 'badretype' );
958 }
959 }
960 return true;
961 },
962 'placeholder-message' => 'createacct-yourpasswordagain-ph',
963 'end-icon-class' => 'mw-password-reveal-icon'
964 ] + $hideIf,
965 'email' => [
966 'type' => 'email',
967 'label-message' => 'createacct-emailrequired',
968 'id' => 'wpEmail',
969 'cssclass' => 'loginText',
970 'size' => '20',
971 'maxlength' => 255,
972 'autocomplete' => 'email',
973 // FIXME will break non-standard providers
974 'required' => $config->get( MainConfigNames::EmailConfirmToEdit ),
975 'show-optional-flag' => !$config->get( MainConfigNames::EmailConfirmToEdit ),
976 'validation-callback' => function ( $value, $alldata ) {
977 // AuthManager will check most of these, but that will make the auth
978 // session fail and this won't, so nicer to do it this way
979 if ( !$value &&
980 $this->getConfig()->get( MainConfigNames::EmailConfirmToEdit )
981 ) {
982 // no point in allowing registration without email when email is
983 // required to edit
984 return $this->msg( 'noemailtitle' );
985 } elseif ( !$value && !empty( $alldata['mailpassword'] ) ) {
986 // cannot send password via email when there is no email address
987 return $this->msg( 'noemailcreate' );
988 } elseif ( $value && !Sanitizer::validateEmail( $value ) ) {
989 return $this->msg( 'invalidemailaddress' );
990 } elseif ( is_string( $value ) && strlen( $value ) > 255 ) {
991 return $this->msg( 'changeemail-maxlength' );
992 }
993 return true;
994 },
995 // The following messages are used here:
996 // * createacct-email-ph
997 // * createacct-another-email-ph
998 'placeholder-message' => 'createacct-' . $anotherPart . 'email-ph',
999 ],
1000 'realname' => [
1001 'type' => 'text',
1002 'help-message' => $isLoggedIn ? 'createacct-another-realname-tip'
1003 : 'prefs-help-realname',
1004 'label-message' => 'createacct-realname',
1005 'cssclass' => 'loginText',
1006 'size' => 20,
1007 'placeholder-message' => 'createacct-realname',
1008 'id' => 'wpRealName',
1009 'autocomplete' => 'name',
1010 ],
1011 'reason' => [
1012 // comment for the user creation log
1013 'type' => 'text',
1014 'label-message' => 'createacct-reason',
1015 'cssclass' => 'loginText',
1016 'id' => 'wpReason',
1017 'size' => '20',
1018 'validation-callback' => function ( $value, $alldata ) {
1019 // if the user sets an email address as the user creation reason, confirm that
1020 // that was their intent
1021 if ( $value && Sanitizer::validateEmail( $value ) ) {
1022 if ( $this->reasonValidatorResult !== null ) {
1023 return $this->reasonValidatorResult;
1024 }
1025 $this->reasonValidatorResult = true;
1026 $authManager = MediaWikiServices::getInstance()->getAuthManager();
1027 if ( !$authManager->getAuthenticationSessionData( 'reason-retry', false ) ) {
1028 $authManager->setAuthenticationSessionData( 'reason-retry', true );
1029 $this->reasonValidatorResult = $this->msg( 'createacct-reason-confirm' );
1030 }
1031 return $this->reasonValidatorResult;
1032 }
1033 return true;
1034 },
1035 'placeholder-message' => 'createacct-reason-ph',
1036 ],
1037 'createaccount' => [
1038 // submit button
1039 'type' => 'submit',
1040 // The following messages are used here:
1041 // * createacct-submit
1042 // * createacct-another-submit
1043 // * createacct-continue-submit
1044 // * createacct-another-continue-submit
1045 'default' => $this->msg( 'createacct-' . $anotherPart . $continuePart .
1046 'submit' )->text(),
1047 'name' => 'wpCreateaccount',
1048 'id' => 'wpCreateaccount',
1049 'size' => 'large',
1050 'weight' => 100,
1051 ],
1052 ];
1053
1054 if ( $this->loginHelper->isDisplayModePopup() ) {
1055 $fieldDefinitions['redirectnotice'] = [
1056 'type' => 'info',
1057 'default' => $this->msg( 'createacct-popup-redirect-notice' )->text(),
1058 'cssclass' => 'mw-createacct-redirect-notice',
1059 'weight' => -1,
1060 ];
1061 }
1062 } else {
1063 // When the user's password is too weak, they might be asked to provide a stronger one
1064 // as a followup step. That is a form with only two fields, 'password' and 'retype',
1065 // and they should behave more like account creation.
1066 $passwordRequest = AuthenticationRequest::getRequestByClass( $this->authRequests,
1067 PasswordAuthenticationRequest::class );
1068 $changePassword = $passwordRequest && $passwordRequest->action == AuthManager::ACTION_CHANGE;
1069 $fieldDefinitions = [
1070 'username' => (
1071 [
1072 'label-raw' => $this->msg( 'userlogin-yourname' )->escaped() . $secureLoginLink,
1073 'id' => 'wpName1',
1074 'placeholder-message' => 'userlogin-yourname-ph',
1075 ] + ( $changePassword ? [
1076 // There is no username field on the AuthManager level when changing
1077 // passwords. Fake one because password
1078 'baseField' => 'password',
1079 'nodata' => true,
1080 'readonly' => true,
1081 'cssclass' => 'mw-htmlform-hidden-field',
1082 ] : [] )
1083 ),
1084 'password' => (
1085 $changePassword ? [
1086 'autocomplete' => 'new-password',
1087 'placeholder-message' => 'createacct-yourpassword-ph',
1088 'help-message' => '',
1089 ] : [
1090 'id' => 'wpPassword1',
1091 'autocomplete' => 'current-password',
1092 'placeholder-message' => 'userlogin-yourpassword-ph',
1093 ]
1094 ),
1095 'retype' => [
1096 'type' => 'password',
1097 'autocomplete' => 'new-password',
1098 'placeholder-message' => 'createacct-yourpasswordagain-ph',
1099 ],
1100 'domain' => [],
1101 'rememberMe' => [
1102 // option for saving the user token to a cookie
1103 'type' => 'check',
1104 'cssclass' => 'mw-userlogin-rememberme',
1105 'name' => 'wpRemember',
1106 'label-message' => $this->msg( 'userlogin-remembermypassword' )
1107 ->numParams( $expirationDays ),
1108 'id' => 'wpRemember',
1109 ],
1110 'loginattempt' => [
1111 // submit button
1112 'type' => 'submit',
1113 'default' => $this->msg( $this->securityLevel ?
1114 'pt-login-reauth-button' :
1115 // The following messages are used here:
1116 // * pt-login-button
1117 // * pt-login-continue-button
1118 'pt-login-' . $continuePart . 'button'
1119 )->text(),
1120 'id' => 'wpLoginAttempt',
1121 'size' => 'large',
1122 'weight' => 100,
1123 ],
1124 'linkcontainer' => [
1125 // help link
1126 'type' => 'info',
1127 'cssclass' => 'mw-form-related-link-container mw-userlogin-help',
1128 // 'id' => 'mw-userlogin-help', // FIXME HTMLInfoField ignores this
1129 'raw' => true,
1130 'default' => Html::element( 'a', [
1131 'href' => Skin::makeInternalOrExternalUrl( $this->msg( 'helplogin-url' )
1132 ->inContentLanguage()
1133 ->text() ),
1134 ], $this->msg( 'userlogin-helplink2' )->text() ),
1135 'weight' => 200,
1136 ],
1137 // button for ResetPasswordSecondaryAuthenticationProvider
1138 'skipReset' => [
1139 'weight' => 110,
1140 'flags' => [],
1141 ],
1142 ];
1143 }
1144
1145 // T369641: We want to ensure that this transformation to the username and/or
1146 // password fields are applied only when we have matching requests within the
1147 // authentication manager.
1148 $isUsernameOrPasswordRequest =
1149 AuthenticationRequest::getRequestByClass( $requests, UsernameAuthenticationRequest::class ) ||
1150 AuthenticationRequest::getRequestByClass( $requests, PasswordAuthenticationRequest::class );
1151
1152 if ( $isUsernameOrPasswordRequest ) {
1153 $fieldDefinitions['username'] += [
1154 'type' => 'text',
1155 'name' => 'wpName',
1156 'cssclass' => 'loginText mw-userlogin-username',
1157 'size' => 20,
1158 'autocomplete' => 'username',
1159 // 'required' => true,
1160 ];
1161 $fieldDefinitions['password'] += [
1162 'type' => 'password',
1163 // 'label-message' => 'userlogin-yourpassword', // would override the changepassword label
1164 'name' => 'wpPassword',
1165 'cssclass' => 'loginPassword mw-userlogin-password',
1166 'size' => 20,
1167 // 'required' => true,
1168 ];
1169 }
1170
1171 if ( $this->getUser()->isNamed() && $this->securityLevel ) {
1172 // Keep the 'username' field key in the descriptor so the form processor
1173 // still binds POST['wpName'] -> $data['username'] for the AuthenticationRequest,
1174 // but render it as a hidden input. Add a separate info field for the visual.
1175 $fieldDefinitions['username']['type'] = 'hidden';
1176 $fieldDefinitions['username']['default'] = $this->getUser()->getName();
1177 unset( $fieldDefinitions['username']['placeholder-message'] );
1178 unset( $fieldDefinitions['username']['label-raw'] );
1179
1180 $fieldDefinitions['usernameDisplay'] = [
1181 'type' => 'info',
1182 'default' => $this->msg( 'userlogin-yourname-reauth', $this->getUser()->getName() )->parse(),
1183 'raw' => true,
1184 'weight' => -10,
1185 ];
1186 }
1187
1188 if ( $this->mEntryError ) {
1189 $defaultHtml = '';
1190 if ( $this->mEntryErrorType === 'error' ) {
1191 $defaultHtml = Html::errorBox( $this->mEntryError );
1192 } elseif ( $this->mEntryErrorType === 'warning' ) {
1193 $defaultHtml = Html::warningBox( $this->mEntryError );
1194 } elseif ( $this->mEntryErrorType === 'notice' ) {
1195 $defaultHtml = Html::noticeBox( $this->mEntryError );
1196 }
1197 $fieldDefinitions['entryError'] = [
1198 'type' => 'info',
1199 'default' => $defaultHtml,
1200 'raw' => true,
1201 'rawrow' => true,
1202 'weight' => -100,
1203 ];
1204 }
1205 if ( !$this->showExtraInformation() ) {
1206 unset( $fieldDefinitions['linkcontainer'], $fieldDefinitions['signupend'] );
1207 }
1208 if ( $this->isSignup() && $this->showExtraInformation() ) {
1209 // blank signup footer for site customization
1210 // uses signupend-https for HTTPS requests if it's not blank, signupend otherwise
1211 $signupendMsg = $this->msg( 'signupend' );
1212 $signupendHttpsMsg = $this->msg( 'signupend-https' );
1213 if ( !$signupendMsg->isDisabled() ) {
1214 $usingHTTPS = $this->getRequest()->getProtocol() === 'https';
1215 $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
1216 ? $signupendHttpsMsg->parse() : $signupendMsg->parse();
1217 $fieldDefinitions['signupend'] = [
1218 'type' => 'info',
1219 'raw' => true,
1220 'default' => Html::rawElement( 'div', [ 'id' => 'signupend' ], $signupendText ),
1221 'weight' => 225,
1222 ];
1223 }
1224 }
1225 if ( !$this->isSignup() && $this->showExtraInformation() ) {
1226 $passwordReset = MediaWikiServices::getInstance()->getPasswordReset();
1227 if ( $passwordReset->isEnabled()->isGood() ) {
1228 $fieldDefinitions['passwordReset'] = [
1229 'type' => 'info',
1230 'raw' => true,
1231 'cssclass' => 'mw-form-related-link-container',
1232 'default' => $this->getLinkRenderer()->makeLink(
1233 SpecialPage::getTitleFor( 'PasswordReset' ),
1234 $this->msg( 'userlogin-resetpassword-link' )->text(),
1235 [ 'class' => 'mw-authentication-popup-link' ],
1236 $this->getPreservedParams()
1237 ),
1238 'weight' => 230,
1239 ];
1240 }
1241
1242 // Don't show a "create account" link if the user can't.
1243 if ( $this->showCreateAccountLink() ) {
1244 // link to the other action
1245 $linkTitle = SpecialPage::getTitleFor( $this->isSignup() ? 'Userlogin' : 'CreateAccount' );
1246 $linkq = wfArrayToCgi( $this->getPreservedParams( [ 'reset' => true ] ) );
1247 $isLoggedIn = $this->getUser()->isRegistered()
1248 && !$this->getUser()->isTemp();
1249 $popupMode = $this->getLoginHelper()->isDisplayModePopup();
1250
1251 $fieldDefinitions['createOrLogin'] = [
1252 'type' => 'info',
1253 'raw' => true,
1254 'linkQuery' => $linkq,
1255 'default' => function ( $params ) use ( $isLoggedIn, $linkTitle ) {
1256 $buttonClasses = 'cdx-button cdx-button--action-progressive '
1257 . 'cdx-button--fake-button cdx-button--fake-button--enabled';
1258
1259 return Html::rawElement( 'div',
1260 // The following element IDs are used here:
1261 // mw-createaccount, mw-createaccount-cta
1262 [ 'id' => 'mw-createaccount' . ( !$isLoggedIn ? '-cta' : '' ),
1263 'class' => ( $isLoggedIn ? 'mw-form-related-link-container' : '' ) ],
1264 ( $isLoggedIn ? '' : $this->msg( 'userlogin-noaccount' )->escaped() )
1265 . Html::element( 'a',
1266 [
1267 // The following element IDs are used here:
1268 // mw-createaccount-join, mw-createaccount-join-loggedin
1269 'id' => 'mw-createaccount-join' . ( $isLoggedIn ? '-loggedin' : '' ),
1270 'href' => $linkTitle->getLocalURL( $params['linkQuery'] ),
1271 'class' => [ 'mw-authentication-popup-link', $buttonClasses => !$isLoggedIn ],
1272 'target' => '_self',
1273 'tabindex' => 100,
1274 ],
1275 $this->msg(
1276 $isLoggedIn ? 'userlogin-createanother' : 'userlogin-joinproject'
1277 )->text()
1278 )
1279 );
1280 },
1281 'weight' => $popupMode ? -1 : 235,
1282 ];
1283 }
1284 }
1285
1286 return $fieldDefinitions;
1287 }
1288
1294 private function showCreateAccountLink() {
1295 return $this->isSignup() ||
1296 $this->getContext()->getAuthority()->isAllowed( 'createaccount' );
1297 }
1298
1302 protected function getTokenName() {
1303 return $this->isSignup() ? 'wpCreateaccountToken' : 'wpLoginToken';
1304 }
1305
1312 protected function makeLanguageSelector() {
1313 $msg = $this->msg( 'loginlanguagelinks' )->inContentLanguage();
1314 if ( $msg->isBlank() ) {
1315 return '';
1316 }
1317 $langs = explode( "\n", $msg->text() );
1318 $links = [];
1319 foreach ( $langs as $lang ) {
1320 $lang = trim( $lang, '* ' );
1321 $parts = explode( '|', $lang );
1322 if ( count( $parts ) >= 2 ) {
1323 $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
1324 }
1325 }
1326
1327 return count( $links ) > 0 ? $this->msg( 'loginlanguagelabel' )->rawParams(
1328 $this->getLanguage()->pipeList( $links ) )->escaped() : '';
1329 }
1330
1339 protected function makeLanguageSelectorLink( $text, $lang ) {
1340 $services = MediaWikiServices::getInstance();
1341
1342 if ( $this->getLanguage()->getCode() == $lang
1343 || !$services->getLanguageNameUtils()->isValidCode( $lang )
1344 ) {
1345 // no link for currently used language
1346 // or invalid language code
1347 return htmlspecialchars( $text );
1348 }
1349
1350 $query = $this->getPreservedParams();
1351 $query['uselang'] = $lang;
1352
1353 $attr = [];
1354 $targetLanguage = $services->getLanguageFactory()->getLanguage( $lang );
1355 $attr['lang'] = $attr['hreflang'] = $targetLanguage->getHtmlCode();
1356 $attr['class'] = 'mw-authentication-popup-link';
1357 $attr['title'] = false;
1358
1359 return $this->getLinkRenderer()->makeKnownLink(
1360 $this->getPageTitle(),
1361 $text,
1362 $attr,
1363 $query
1364 );
1365 }
1366
1368 protected function getGroupName() {
1369 return 'login';
1370 }
1371
1376 protected function postProcessFormDescriptor( &$formDescriptor, $requests ) {
1377 // Pre-fill username (if not creating an account, T46775).
1378 if (
1379 isset( $formDescriptor['username'] ) &&
1380 !isset( $formDescriptor['username']['default'] ) &&
1381 !$this->isSignup()
1382 ) {
1383 $user = $this->getUser();
1384 if ( $user->isRegistered() && !$user->isTemp() ) {
1385 $formDescriptor['username']['default'] = $user->getName();
1386 } else {
1387 $formDescriptor['username']['default'] =
1388 $this->getRequest()->getSession()->suggestLoginUsername();
1389 }
1390 }
1391
1392 // don't show a submit button if there is nothing to submit (i.e. the only form content
1393 // is other submit buttons, for redirect flows)
1394 if ( !$this->needsSubmitButton( $requests ) ) {
1395 unset( $formDescriptor['createaccount'], $formDescriptor['loginattempt'] );
1396 }
1397
1398 if ( $this->getUser()->isNamed() && !$this->isContinued() && !$this->securityLevel ) {
1399 // Remove 'primary' flag from the default form submission button if the user is already logged in
1400 if ( isset( $formDescriptor['createaccount'] ) ) {
1401 $formDescriptor['createaccount']['flags'] = [ 'progressive' ];
1402 }
1403 if ( isset( $formDescriptor['loginattempt'] ) ) {
1404 $formDescriptor['loginattempt']['flags'] = [ 'progressive' ];
1405 }
1406 }
1407
1408 if ( !$this->isSignup() ) {
1409 // FIXME HACK don't focus on non-empty field
1410 // maybe there should be an autofocus-if similar to hide-if?
1411 if (
1412 isset( $formDescriptor['username'] )
1413 && empty( $formDescriptor['username']['default'] )
1414 && !$this->getRequest()->getCheck( 'wpName' )
1415 ) {
1416 $formDescriptor['username']['autofocus'] = true;
1417 } elseif ( isset( $formDescriptor['password'] ) ) {
1418 $formDescriptor['password']['autofocus'] = true;
1419 }
1420 }
1421
1422 $this->addTabIndex( $formDescriptor );
1423 }
1424
1430 protected function getNoticeHtml() {
1431 $noticeContent = $this->msg( 'createacct-temp-warning', $this->getUser()->getName() )->parse();
1432 return Html::noticeBox(
1433 $noticeContent,
1434 'mw-createaccount-temp-warning',
1435 '',
1436 'mw-userLogin-icon--user-temporary'
1437 );
1438 }
1439
1440}
1441
1442// @codeCoverageIgnoreStart
1444class_alias( LoginSignupSpecialPage::class, 'LoginSignupSpecialPage' );
1445// @codeCoverageIgnoreEnd
const PROTO_HTTPS
Definition Defines.php:218
wfEscapeWikiText( $input)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
wfCgiToArray( $query)
This is the logical opposite of wfArrayToCgi(): it accepts a query string as its argument and returns...
if(!defined('MW_SETUP_CALLBACK'))
Definition WebStart.php:71
AuthManager is the authentication system in MediaWiki and serves entry point for authentication.
This is a value object for authentication requests.
This is a value object to hold authentication response data.
This is a value object for authentication requests with a username and password.
AuthenticationRequest to ensure something with a username is present.
An IContextSource implementation which will inherit context from another source but allow individual ...
Group all the pieces relevant to the context of a request into one instance.
An error page which can definitely be safely rendered using the OutputPage.
Abort the web request with a custom HTML string that will represent the entire response.
Show an error when a user tries to do something they do not have the necessary permissions for.
Show an error when the wiki is locked/read-only and the user tries to do something that requires writ...
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition HTMLForm.php:214
This class is a collection of static functions that serve two purposes:
Definition Html.php:44
Create PSR-3 logger objects.
A class containing constants representing the names of configuration variables.
const LoginLanguageSelector
Name constant for the LoginLanguageSelector setting, for use with Config::get()
const ForceHTTPS
Name constant for the ForceHTTPS setting, for use with Config::get()
const SecureLogin
Name constant for the SecureLogin setting, for use with Config::get()
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:144
HTML sanitizer for MediaWiki.
Definition Sanitizer.php:34
The base class for all skins.
Definition Skin.php:54
A special page subclass for authentication-related special pages.
Holds shared logic for login and account creation pages.
setRequest(array $data, $wasPosted=null)
Override the POST data, GET data from the real request is preserved.Used to preserve POST data over a...
makeLanguageSelectorLink( $text, $lang)
Create a language selector link for a particular language Links back to this page preserving type and...
string string $mReturnToAnchor
The fragment part of the URL to return to after authentication finishes.
beforeExecute( $subPage)
Gets called before execute.Return false to prevent calling execute() (since 1.27+)....
showSuccessPage( $type, $title, $msgname, $injected_html, $extraMessages)
Show the success page.
getAuthForm(array $requests, $action)
Generates a form from the given request.
bool $mAlwaysShowLogin
Value of the 'alwaysShowLogin' URL parameter.
mainLoginForm(array $requests, $msg='', $msgtype='error')
getPreservedParams( $options=[])
Returns URL query parameters which should be preserved between authentication requests....
logAuthResult( $success, UserIdentity $performer, $status=null)
Logs to the authmanager-stats channel.
bool $proxyAccountCreation
True if the user if creating an account for someone else.
showExtraInformation()
Show extra information such as password recovery information, link from login to signup,...
string string $mReturnToQuery
The query string part of the URL to return to after authentication finishes.
onAuthChangeFormFields(array $requests, array $fieldInfo, array &$formDescriptor, $action)
Change the form descriptor that determines how a field will look in the authentication form....
makeLanguageSelector()
Produce a bar of links which allow the user to select another language during login/registration but ...
getAuthenticationRequests( $action, ?UserIdentity $user=null)
Get the list of AuthenticationRequests from the AuthManager.In this class this is just a wrapper arou...
successfulAction( $direct=false, $extraMessages=null)
string string $mReturnTo
The title of the page to return to after authentication finishes, or the empty string when there is n...
getNoticeHtml()
Generates the HTML for a notice box to be displayed to a temporary user.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getFieldDefinitions(array $fieldInfo, array $requests)
Create a HTMLForm descriptor for the core login fields.
getPageHtml( $formHtml)
Add page elements which are outside the form.
User $targetUser
FIXME another flag for passing data.
getContext()
Gets the context this SpecialPage is executed in.
Helper functions for the login form that need to be shared with other special pages (such as CentralA...
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:44
Represents a title within MediaWiki.
Definition Title.php:69
User class for the MediaWiki software.
Definition User.php:129
Generic operation result class Has warning/error list, boolean status and arbitrary value.
return[ 'config-schema-inverse'=>['default'=>['ConfigRegistry'=>['main'=> 'MediaWiki\\Config\\GlobalVarConfig::newInstance',], 'Sitename'=> 'MediaWiki', 'Server'=> false, 'CanonicalServer'=> false, 'ServerName'=> false, 'AssumeProxiesUseDefaultProtocolPorts'=> true, 'HttpsPort'=> 443, 'ForceHTTPS'=> false, 'ScriptPath'=> '/wiki', 'UsePathInfo'=> null, 'Script'=> false, 'LoadScript'=> false, 'RestPath'=> false, 'StylePath'=> false, 'LocalStylePath'=> false, 'ExtensionAssetsPath'=> false, 'ExtensionDirectory'=> null, 'StyleDirectory'=> null, 'ArticlePath'=> false, 'UploadPath'=> false, 'ImgAuthPath'=> false, 'ThumbPath'=> false, 'UploadDirectory'=> false, 'FileCacheDirectory'=> false, 'Logo'=> false, 'Logos'=> false, 'Favicon'=> '/favicon.ico', 'AppleTouchIcon'=> false, 'ReferrerPolicy'=> false, 'TmpDirectory'=> false, 'UploadBaseUrl'=> '', 'UploadStashScalerBaseUrl'=> false, 'ActionPaths'=>[], 'MainPageIsDomainRoot'=> false, 'EnableUploads'=> false, 'UploadStashMaxAge'=> 21600, 'EnableAsyncUploads'=> false, 'EnableAsyncUploadsByURL'=> false, 'EnableChunkedUploads'=> false, 'UploadMaintenance'=> false, 'IllegalFileChars'=> ':\\/\\\\', 'DeletedDirectory'=> false, 'ImgAuthDetails'=> false, 'ImgAuthUrlPathMap'=>[], 'LocalFileRepo'=>['class'=> 'MediaWiki\\FileRepo\\LocalRepo', 'name'=> 'local', 'directory'=> null, 'scriptDirUrl'=> null, 'favicon'=> null, 'url'=> null, 'hashLevels'=> null, 'thumbScriptUrl'=> null, 'transformVia404'=> null, 'deletedDir'=> null, 'deletedHashLevels'=> null, 'updateCompatibleMetadata'=> null, 'reserializeMetadata'=> null,], 'ForeignFileRepos'=>[], 'UseInstantCommons'=> false, 'UseSharedUploads'=> false, 'SharedUploadDirectory'=> null, 'SharedUploadPath'=> null, 'HashedSharedUploadDirectory'=> true, 'RepositoryBaseUrl'=> 'https:'FetchCommonsDescriptions'=> false, 'SharedUploadDBname'=> false, 'SharedUploadDBprefix'=> '', 'CacheSharedUploads'=> true, 'ForeignUploadTargets'=>['local',], 'UploadDialog'=>['fields'=>['description'=> true, 'date'=> false, 'categories'=> false,], 'licensemessages'=>['local'=> 'generic-local', 'foreign'=> 'generic-foreign',], 'comment'=>['local'=> '', 'foreign'=> '',], 'format'=>['filepage'=> ' $DESCRIPTION', 'description'=> ' $TEXT', 'ownwork'=> '', 'license'=> '', 'uncategorized'=> '',],], 'FileBackends'=>[], 'LockManagers'=>[], 'DefaultLockManager'=> null, 'ShowEXIF'=> null, 'UpdateCompatibleMetadata'=> false, 'AllowCopyUploads'=> false, 'CopyUploadsDomains'=>[], 'CopyUploadsFromSpecialUpload'=> false, 'CopyUploadProxy'=> false, 'CopyUploadTimeout'=> false, 'CopyUploadAllowOnWikiDomainConfig'=> false, 'MaxUploadSize'=> 104857600, 'MinUploadChunkSize'=> 1024, 'UploadNavigationUrl'=> false, 'UploadMissingFileUrl'=> false, 'ThumbnailScriptPath'=> false, 'SharedThumbnailScriptPath'=> false, 'HashedUploadDirectory'=> true, 'CSPUploadEntryPoint'=> true, 'FileExtensions'=>['png', 'gif', 'jpg', 'jpeg', 'webp',], 'ProhibitedFileExtensions'=>['html', 'htm', 'js', 'jsb', 'mhtml', 'mht', 'xhtml', 'xht', 'php', 'phtml', 'php3', 'php4', 'php5', 'phps', 'phar', 'shtml', 'jhtml', 'pl', 'py', 'cgi', 'exe', 'scr', 'dll', 'msi', 'vbs', 'bat', 'com', 'pif', 'cmd', 'vxd', 'cpl', 'xml',], 'MimeTypeExclusions'=>['text/html', 'application/javascript', 'text/javascript', 'text/x-javascript', 'application/x-shellscript', 'application/x-php', 'text/x-php', 'text/x-python', 'text/x-perl', 'text/x-bash', 'text/x-sh', 'text/x-csh', 'text/scriptlet', 'application/x-msdownload', 'application/x-msmetafile', 'application/java', 'application/xml', 'text/xml',], 'CheckFileExtensions'=> true, 'StrictFileExtensions'=> true, 'DisableUploadScriptChecks'=> false, 'UploadSizeWarning'=> false, 'TrustedMediaFormats'=>['BITMAP', 'AUDIO', 'VIDEO', 'image/svg+xml', 'application/pdf',], 'MediaHandlers'=>[], 'NativeImageLazyLoading'=> true, 'ParserTestMediaHandlers'=>['image/jpeg'=> 'MockBitmapHandler', 'image/png'=> 'MockBitmapHandler', 'image/gif'=> 'MockBitmapHandler', 'image/tiff'=> 'MockBitmapHandler', 'image/webp'=> 'MockBitmapHandler', 'image/x-ms-bmp'=> 'MockBitmapHandler', 'image/x-bmp'=> 'MockBitmapHandler', 'image/x-xcf'=> 'MockBitmapHandler', 'image/svg+xml'=> 'MockSvgHandler', 'image/vnd.djvu'=> 'MockDjVuHandler',], 'UseImageResize'=> true, 'UseImageMagick'=> false, 'ImageMagickConvertCommand'=> '/usr/bin/convert', 'MaxInterlacingAreas'=>[], 'SharpenParameter'=> '0x0.4', 'SharpenReductionThreshold'=> 0.85, 'ImageMagickTempDir'=> false, 'CustomConvertCommand'=> false, 'JpegTran'=> '/usr/bin/jpegtran', 'JpegPixelFormat'=> 'yuv420', 'JpegQuality'=> 80, 'Exiv2Command'=> '/usr/bin/exiv2', 'Exiftool'=> '/usr/bin/exiftool', 'SVGConverters'=>['ImageMagick'=> ' $path/convert -background "#ffffff00" -thumbnail $widthx$height\\! $input PNG:$output', 'inkscape'=> ' $path/inkscape -w $width -o $output $input', 'batik'=> 'java -Djava.awt.headless=true -jar $path/batik-rasterizer.jar -w $width -d $output $input', 'rsvg'=> ' $path/rsvg-convert -w $width -h $height -l $lang -o $output $input', 'ImagickExt'=>['SvgHandler::rasterizeImagickExt',],], 'SVGConverter'=> 'ImageMagick', 'SVGConverterPath'=> '', 'SVGMaxSize'=> 5120, 'SVGMetadataCutoff'=> 5242880, 'SVGNativeRendering'=> true, 'SVGNativeRenderingSizeLimit'=> 51200, 'MediaInTargetLanguage'=> true, 'MaxImageArea'=> 12500000, 'MaxAnimatedGifArea'=> 12500000, 'MaxAnimatedWebPArea'=> 12500000, 'WebPThumbnailType'=>['webp', 'image/webp',], 'TiffThumbnailType'=>[], 'ThumbnailEpoch'=> '20030516000000', 'AttemptFailureEpoch'=> 1, 'IgnoreImageErrors'=> false, 'GenerateThumbnailOnParse'=> true, 'ShowArchiveThumbnails'=> true, 'EnableAutoRotation'=> null, 'Antivirus'=> null, 'AntivirusSetup'=>['clamav'=>['command'=> 'clamscan --no-summary ', 'codemap'=>[0=> 0, 1=> 1, 52=> -1, ' *'=> false,], 'messagepattern'=> '/.*?:(.*)/sim',],], 'AntivirusRequired'=> true, 'VerifyMimeType'=> true, 'MimeTypeFile'=> 'internal', 'MimeInfoFile'=> 'internal', 'MimeDetectorCommand'=> null, 'TrivialMimeDetection'=> false, 'XMLMimeTypes'=>['http:'svg'=> 'image/svg+xml', 'http:'http:'html'=> 'text/html',], 'ImageLimits'=>[[320, 240,], [640, 480,], [800, 600,], [1024, 768,], [1280, 1024,], [2560, 2048,],], 'ThumbLimits'=>[120, 150, 180, 200, 220, 250, 300, 400,], 'ThumbnailNamespaces'=>[6,], 'ThumbnailSteps'=> null, 'ThumbnailBuckets'=> null, 'ThumbnailMinimumBucketDistance'=> 50, 'UploadThumbnailRenderMap'=>[], 'UploadThumbnailRenderMethod'=> 'jobqueue', 'UploadThumbnailRenderHttpCustomHost'=> false, 'UploadThumbnailRenderHttpCustomDomain'=> false, 'UseTinyRGBForJPGThumbnails'=> false, 'GalleryOptions'=>[], 'ThumbUpright'=> 0.75, 'DirectoryMode'=> 511, 'ResponsiveImages'=> true, 'ImagePreconnect'=> false, 'TrackMediaRequestProvenance'=> false, 'DjvuUseBoxedCommand'=> false, 'DjvuDump'=> null, 'DjvuRenderer'=> null, 'DjvuTxt'=> null, 'DjvuPostProcessor'=> 'pnmtojpeg', 'DjvuOutputExtension'=> 'jpg', 'EmergencyContact'=> false, 'RestTermsOfServiceUrl'=> null, 'PasswordSender'=> false, 'NoReplyAddress'=> false, 'EnableEmail'=> true, 'EnableUserEmail'=> true, 'UserEmailUseReplyTo'=> true, 'PasswordReminderResendTime'=> 24, 'NewPasswordExpiry'=> 604800, 'UserEmailConfirmationTokenExpiry'=> 604800, 'PasswordExpirationDays'=> false, 'PasswordExpireGrace'=> 604800, 'SMTP'=> false, 'AdditionalMailParams'=> null, 'AllowHTMLEmail'=> false, 'EnotifFromEditor'=> false, 'EmailAuthentication'=> true, 'EmailConfirmationBanner'=> false, 'EnotifWatchlist'=> false, 'EnotifUserTalk'=> false, 'EnotifRevealEditorAddress'=> false, 'EnotifMinorEdits'=> true, 'EnotifUseRealName'=> false, 'UsersNotifiedOnAllChanges'=>[], 'DBname'=> 'my_wiki', 'DBmwschema'=> null, 'DBprefix'=> '', 'DBserver'=> 'localhost', 'DBport'=> 5432, 'DBuser'=> 'wikiuser', 'DBpassword'=> '', 'DBtype'=> 'mysql', 'DBssl'=> false, 'DBcompress'=> false, 'DBStrictWarnings'=> false, 'DBadminuser'=> null, 'DBadminpassword'=> null, 'SearchType'=> null, 'SearchTypeAlternatives'=> null, 'DBTableOptions'=> 'ENGINE=InnoDB, DEFAULT CHARSET=binary', 'SQLMode'=> '', 'SQLiteDataDir'=> '', 'SharedDB'=> null, 'SharedPrefix'=> false, 'SharedTables'=>['user', 'user_properties', 'user_autocreate_serial',], 'SharedSchema'=> false, 'DBservers'=> false, 'LBFactoryConf'=>['class'=> 'Wikimedia\\Rdbms\\LBFactorySimple',], 'DataCenterUpdateStickTTL'=> 10, 'DBerrorLog'=> false, 'DBerrorLogTZ'=> false, 'LocalDatabases'=>[], 'DatabaseReplicaLagWarning'=> 10, 'DatabaseReplicaLagCritical'=> 30, 'MaxExecutionTimeForExpensiveQueries'=> 0, 'VirtualDomainsMapping'=>[], 'RemoteVirtualDomainsMapping'=>[], 'FileSchemaMigrationStage'=> 3, 'ExternalLinksDomainGaps'=>[], 'ContentHandlers'=>['wikitext'=>['class'=> 'MediaWiki\\Content\\WikitextContentHandler', 'services'=>['TitleFactory', 'ParserFactory', 'GlobalIdGenerator', 'LanguageNameUtils', 'LinkRenderer', 'MagicWordFactory', 'ParsoidParserFactory',],], 'javascript'=>['class'=> 'MediaWiki\\Content\\JavaScriptContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup', 'CodeHighlighter',],], 'json'=>['class'=> 'MediaWiki\\Content\\JsonContentHandler', 'services'=>['ParsoidParserFactory', 'TitleFactory',],], 'css'=>['class'=> 'MediaWiki\\Content\\CssContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'UserOptionsLookup', 'CodeHighlighter',],], 'vue'=>['class'=> 'MediaWiki\\Content\\VueContentHandler', 'services'=>['MainConfig', 'ParserFactory', 'CodeHighlighter',],], 'text'=> 'MediaWiki\\Content\\TextContentHandler', 'unknown'=> 'MediaWiki\\Content\\FallbackContentHandler',], 'NamespaceContentModels'=>[], 'TextModelsToParse'=>['wikitext', 'javascript', 'css',], 'CompressRevisions'=> false, 'ExternalStores'=>[], 'ExternalServers'=>[], 'DefaultExternalStore'=> false, 'RevisionCacheExpiry'=> 604800, 'PageLanguageUseDB'=> false, 'DiffEngine'=> null, 'ExternalDiffEngine'=> false, 'Wikidiff2Options'=>[], 'RequestTimeLimit'=> null, 'TransactionalTimeLimit'=> 120, 'CriticalSectionTimeLimit'=> 180.0, 'MiserMode'=> false, 'DisableQueryPages'=> false, 'QueryCacheLimit'=> 1000, 'WantedPagesThreshold'=> 1, 'AllowSlowParserFunctions'=> false, 'AllowSchemaUpdates'=> true, 'MaxArticleSize'=> 2048, 'MemoryLimit'=> '50M', 'PoolCounterConf'=> null, 'PoolCountClientConf'=>['servers'=>['127.0.0.1',], 'timeout'=> 0.1,], 'MaxUserDBWriteDuration'=> false, 'MaxJobDBWriteDuration'=> false, 'LinkHolderBatchSize'=> 1000, 'MaximumMovedPages'=> 100, 'ForceDeferredUpdatesPreSend'=> false, 'MultiShardSiteStats'=> false, 'CacheDirectory'=> false, 'MainCacheType'=> 0, 'MessageCacheType'=> -1, 'ParserCacheType'=> -1, 'SessionCacheType'=> -1, 'AnonSessionCacheType'=> false, 'LanguageConverterCacheType'=> -1, 'ObjectCaches'=>[0=>['class'=> 'Wikimedia\\ObjectCache\\EmptyBagOStuff', 'reportDupes'=> false,], 1=>['class'=> 'MediaWiki\\ObjectCache\\SqlBagOStuff', 'loggroup'=> 'SQLBagOStuff',], 'memcached-php'=>['class'=> 'Wikimedia\\ObjectCache\\MemcachedPhpBagOStuff', 'loggroup'=> 'memcached',], 'memcached-pecl'=>['class'=> 'Wikimedia\\ObjectCache\\MemcachedPeclBagOStuff', 'loggroup'=> 'memcached',], 'hash'=>['class'=> 'Wikimedia\\ObjectCache\\HashBagOStuff', 'reportDupes'=> false,], 'apc'=>['class'=> 'Wikimedia\\ObjectCache\\APCUBagOStuff', 'reportDupes'=> false,], 'apcu'=>['class'=> 'Wikimedia\\ObjectCache\\APCUBagOStuff', 'reportDupes'=> false,],], 'WANObjectCache'=>[], 'MicroStashType'=> -1, 'MainStash'=> 1, 'ParsoidCacheConfig'=>['StashType'=> null, 'StashDuration'=> 86400, 'WarmParsoidParserCache'=> false,], 'ParsoidSelectiveUpdateSampleRate'=> 0, 'SplitParsoidParserCache'=> true, 'ParserCacheFilterConfig'=>['pcache'=>['default'=>['minCpuTime'=> 0,],], 'postproc-pcache'=>['default'=>['minCpuTime'=> 9223372036854775807,],], 'parsoid-pcache'=>['default'=>['minCpuTime'=> 0,],], 'postproc-parsoid-pcache'=>['default'=>['minCpuTime'=> 0,],],], 'ChronologyProtectorSecret'=> '', 'ParserCacheExpireTime'=> 86400, 'ParserCacheAsyncExpireTime'=> 60, 'ParserCacheAsyncRefreshJobs'=> true, 'OldRevisionParserCacheExpireTime'=> 3600, 'ObjectCacheSessionExpiry'=> 3600, 'SuspiciousIpExpiry'=> false, 'SessionPbkdf2Iterations'=> 10001, 'UseSessionCookieJwt'=> false, 'JwtSessionCookieIssuer'=> null, 'MemCachedServers'=>['127.0.0.1:11211',], 'MemCachedPersistent'=> false, 'MemCachedTimeout'=> 500000, 'UseLocalMessageCache'=> false, 'AdaptiveMessageCache'=> false, 'LocalisationCacheConf'=>['class'=> 'MediaWiki\\Language\\LocalisationCache', 'store'=> 'detect', 'storeClass'=> false, 'storeDirectory'=> false, 'storeServer'=>[], 'forceRecache'=> false, 'manualRecache'=> false,], 'CachePages'=> true, 'CacheEpoch'=> '20030516000000', 'GitInfoCacheDirectory'=> false, 'UseFileCache'=> false, 'FileCacheDepth'=> 2, 'RenderHashAppend'=> '', 'EnableSidebarCache'=> false, 'SidebarCacheExpiry'=> 86400, 'UseGzip'=> false, 'InvalidateCacheOnLocalSettingsChange'=> true, 'ExtensionInfoMTime'=> false, 'EnableRemoteBagOStuffTests'=> false, 'UseCdn'=> false, 'VaryOnXFP'=> false, 'InternalServer'=> false, 'CdnMaxAge'=> 18000, 'CdnMaxageLagged'=> 30, 'CdnMaxageStale'=> 10, 'CdnReboundPurgeDelay'=> 0, 'CdnMaxageSubstitute'=> 60, 'ForcedRawSMaxage'=> 300, 'CdnServers'=>[], 'CdnServersNoPurge'=>[], 'HTCPRouting'=>[], 'HTCPMulticastTTL'=> 1, 'UsePrivateIPs'=> false, 'CdnMatchParameterOrder'=> true, 'LanguageCode'=> 'en', 'GrammarForms'=>[], 'InterwikiMagic'=> true, 'HideInterlanguageLinks'=> false, 'ExtraInterlanguageLinkPrefixes'=>[], 'InterlanguageLinkCodeMap'=>[], 'ExtraLanguageNames'=>[], 'ExtraLanguageCodes'=>['bh'=> 'bho', 'no'=> 'nb', 'simple'=> 'en',], 'DummyLanguageCodes'=>[], 'AllUnicodeFixes'=> false, 'LegacyEncoding'=> false, 'AmericanDates'=> false, 'TranslateNumerals'=> true, 'UseDatabaseMessages'=> true, 'MaxMsgCacheEntrySize'=> 10000, 'DisableLangConversion'=> false, 'DisableTitleConversion'=> false, 'DefaultLanguageVariant'=> false, 'UsePigLatinVariant'=> false, 'DisabledVariants'=>[], 'VariantArticlePath'=> false, 'UseXssLanguage'=> false, 'LoginLanguageSelector'=> false, 'ForceUIMsgAsContentMsg'=>[], 'RawHtmlMessages'=>[], 'Localtimezone'=> null, 'LocalTZoffset'=> null, 'OverrideUcfirstCharacters'=>[], 'MimeType'=> 'text/html', 'Html5Version'=> null, 'EditSubmitButtonLabelPublish'=> false, 'XhtmlNamespaces'=>[], 'SiteNotice'=> '', 'BrowserFormatDetection'=> 'telephone=no', 'SkinMetaTags'=>[], 'DefaultSkin'=> 'vector-2022', 'FallbackSkin'=> 'fallback', 'SkipSkins'=>[], 'DisableOutputCompression'=> false, 'FragmentMode'=>['html5', 'legacy',], 'ExternalInterwikiFragmentMode'=> 'legacy', 'FooterIcons'=>['copyright'=>['copyright'=>[],], 'poweredby'=>['mediawiki'=>['src'=> null, 'url'=> 'https:'alt'=> 'Powered by MediaWiki', 'lang'=> 'en',],],], 'EnableSectionShare'=> false, 'UseCombinedLoginLink'=> false, 'Edititis'=> false, 'Send404Code'=> true, 'ShowRollbackEditCount'=> 10, 'EnableCanonicalServerLink'=> false, 'InterwikiLogoOverride'=>[], 'ResourceModules'=>[], 'ResourceModuleSkinStyles'=>[], 'ResourceLoaderSources'=>[], 'ResourceBasePath'=> null, 'ResourceLoaderMaxage'=>[], 'ResourceLoaderDebug'=> false, 'ResourceLoaderMaxQueryLength'=> false, 'ResourceLoaderValidateJS'=> true, 'ResourceLoaderEnableJSProfiler'=> false, 'ResourceLoaderStorageEnabled'=> true, 'ResourceLoaderStorageVersion'=> 1, 'ResourceLoaderEnableSourceMapLinks'=> true, 'AllowSiteCSSOnRestrictedPages'=> false, 'VueDevelopmentMode'=> false, 'CodexDevelopmentDir'=> null, 'MetaNamespace'=> false, 'MetaNamespaceTalk'=> false, 'CanonicalNamespaceNames'=>[-2=> 'Media', -1=> 'Special', 0=> '', 1=> 'Talk', 2=> 'User', 3=> 'User_talk', 4=> 'Project', 5=> 'Project_talk', 6=> 'File', 7=> 'File_talk', 8=> 'MediaWiki', 9=> 'MediaWiki_talk', 10=> 'Template', 11=> 'Template_talk', 12=> 'Help', 13=> 'Help_talk', 14=> 'Category', 15=> 'Category_talk',], 'ExtraNamespaces'=>[], 'ExtraGenderNamespaces'=>[], 'NamespaceAliases'=>[], 'LegalTitleChars'=> ' %!"$&\'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+', 'CapitalLinks' => true, 'CapitalLinkOverrides' => [ ], 'NamespacesWithSubpages' => [ 1 => true, 2 => true, 3 => true, 4 => true, 5 => true, 7 => true, 8 => true, 9 => true, 10 => true, 11 => true, 12 => true, 13 => true, 15 => true, ], 'NamespacesWithoutAutoSummaries' => [ ], 'ContentNamespaces' => [ 0, ], 'ShortPagesNamespaceExclusions' => [ ], 'ExtraSignatureNamespaces' => [ ], 'InvalidRedirectTargets' => [ 'Filepath', 'Mypage', 'Mytalk', 'Redirect', 'Mylog', ], 'DisableHardRedirects' => false, 'FixDoubleRedirects' => false, 'LocalInterwikis' => [ ], 'InterwikiExpiry' => 10800, 'InterwikiCache' => false, 'InterwikiScopes' => 3, 'InterwikiFallbackSite' => 'wiki', 'RedirectSources' => false, 'SiteTypes' => [ 'mediawiki' => 'MediaWiki\\Site\\MediaWikiSite', ], 'MaxTocLevel' => 999, 'MaxPPNodeCount' => 1000000, 'MaxTemplateDepth' => 100, 'MaxPPExpandDepth' => 100, 'UrlProtocols' => [ 'bitcoin:', 'ftp: 'ftps: 'geo:', 'git: 'gopher: 'http: 'https: 'irc: 'ircs: 'magnet:', 'mailto:', 'matrix:', 'mms: 'news:', 'nntp: 'redis: 'sftp: 'sip:', 'sips:', 'sms:', 'ssh: 'svn: 'tel:', 'telnet: 'urn:', 'wikipedia: 'worldwind: 'xmpp:', ' ], 'CleanSignatures' => true, 'AllowExternalImages' => false, 'AllowExternalImagesFrom' => '', 'EnableImageWhitelist' => false, 'TidyConfig' => [ ], 'ParsoidSettings' => [ 'useSelser' => true, ], 'ParsoidExperimentalParserFunctionOutput' => false, 'RawHtml' => false, 'ExternalLinkTarget' => false, 'NoFollowLinks' => true, 'NoFollowNsExceptions' => [ ], 'NoFollowDomainExceptions' => [ 'mediawiki.org', ], 'RegisterInternalExternals' => false, 'ExternalLinksIgnoreDomains' => [ ], 'AllowDisplayTitle' => true, 'RestrictDisplayTitle' => true, 'ExpensiveParserFunctionLimit' => 100, 'PreprocessorCacheThreshold' => 1000, 'EnableScaryTranscluding' => false, 'TranscludeCacheExpiry' => 3600, 'EnableMagicLinks' => [ 'ISBN' => false, 'PMID' => false, 'RFC' => false, ], 'ParserEnableUserLanguage' => false, 'ArticleCountMethod' => 'link', 'ActiveUserDays' => 30, 'LearnerEdits' => 10, 'LearnerMemberSince' => 4, 'ExperiencedUserEdits' => 500, 'ExperiencedUserMemberSince' => 30, 'ManualRevertSearchRadius' => 15, 'RevertedTagMaxDepth' => 15, 'CentralIdLookupProviders' => [ 'local' => [ 'class' => 'MediaWiki\\User\\CentralId\\LocalIdLookup', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', 'HideUserUtils', ], ], ], 'CentralIdLookupProvider' => 'local', 'UserRegistrationProviders' => [ 'local' => [ 'class' => 'MediaWiki\\User\\Registration\\LocalUserRegistrationProvider', 'services' => [ 'ConnectionProvider', ], ], ], 'PasswordPolicy' => [ 'policies' => [ 'bureaucrat' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'sysop' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'interface-admin' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'bot' => [ 'MinimalPasswordLength' => 10, 'MinimumPasswordLengthToLogin' => 1, ], 'default' => [ 'MinimalPasswordLength' => [ 'value' => 8, 'suggestChangeOnLogin' => true, ], 'PasswordCannotBeSubstringInUsername' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], 'PasswordCannotMatchDefaults' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], 'MaximalPasswordLength' => [ 'value' => 4096, 'suggestChangeOnLogin' => true, ], 'PasswordNotInCommonList' => [ 'value' => true, 'suggestChangeOnLogin' => true, ], ], ], 'checks' => [ 'MinimalPasswordLength' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMinimalPasswordLength', ], 'MinimumPasswordLengthToLogin' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMinimumPasswordLengthToLogin', ], 'PasswordCannotBeSubstringInUsername' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordCannotBeSubstringInUsername', ], 'PasswordCannotMatchDefaults' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordCannotMatchDefaults', ], 'MaximalPasswordLength' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkMaximalPasswordLength', ], 'PasswordNotInCommonList' => [ 'MediaWiki\\Password\\PasswordPolicyChecks', 'checkPasswordNotInCommonList', ], ], ], 'AuthManagerConfig' => null, 'AuthManagerAutoConfig' => [ 'preauth' => [ 'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\ThrottlePreAuthenticationProvider', 'sort' => 0, ], 'MediaWiki\\Auth\\PreviouslyRenamedAccountPreAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\PreviouslyRenamedAccountPreAuthenticationProvider', 'services' => [ 'ConnectionProvider', 'UserFactory', ], 'sort' => 0, ], ], 'primaryauth' => [ 'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\TemporaryPasswordPrimaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', 'UserOptionsLookup', ], 'args' => [ [ 'authoritative' => false, ], ], 'sort' => 0, ], 'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\LocalPasswordPrimaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', ], 'args' => [ [ 'authoritative' => true, ], ], 'sort' => 100, ], ], 'secondaryauth' => [ 'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\CheckBlocksSecondaryAuthenticationProvider', 'sort' => 0, ], 'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\ResetPasswordSecondaryAuthenticationProvider', 'sort' => 100, ], 'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider' => [ 'class' => 'MediaWiki\\Auth\\EmailNotificationSecondaryAuthenticationProvider', 'services' => [ 'DBLoadBalancerFactory', ], 'sort' => 200, ], ], ], 'RememberMe' => 'choose', 'ReauthenticateTime' => [ 'default' => 3600, ], 'ChangeCredentialsBlacklist' => [ 'MediaWiki\\Auth\\TemporaryPasswordAuthenticationRequest', ], 'RemoveCredentialsBlacklist' => [ 'MediaWiki\\Auth\\PasswordAuthenticationRequest', ], 'InvalidPasswordReset' => true, 'PasswordDefault' => 'pbkdf2', 'PasswordConfig' => [ 'A' => [ 'class' => 'MediaWiki\\Password\\MWOldPassword', ], 'B' => [ 'class' => 'MediaWiki\\Password\\MWSaltedPassword', ], 'pbkdf2-legacyA' => [ 'class' => 'MediaWiki\\Password\\LayeredParameterizedPassword', 'types' => [ 'A', 'pbkdf2', ], ], 'pbkdf2-legacyB' => [ 'class' => 'MediaWiki\\Password\\LayeredParameterizedPassword', 'types' => [ 'B', 'pbkdf2', ], ], 'bcrypt' => [ 'class' => 'MediaWiki\\Password\\BcryptPassword', 'cost' => 9, ], 'pbkdf2' => [ 'class' => 'MediaWiki\\Password\\Pbkdf2PasswordUsingOpenSSL', 'algo' => 'sha512', 'cost' => '30000', 'length' => '64', ], 'argon2' => [ 'class' => 'MediaWiki\\Password\\Argon2Password', 'algo' => 'auto', ], ], 'PasswordResetRoutes' => [ 'username' => true, 'email' => true, ], 'MaxSigChars' => 255, 'SignatureValidation' => 'warning', 'SignatureAllowedLintErrors' => [ 'obsolete-tag', ], 'MaxNameChars' => 255, 'ReservedUsernames' => [ 'MediaWiki default', 'Conversion script', 'Maintenance script', 'Template namespace initialisation script', 'ScriptImporter', 'Delete page script', 'Move page script', 'Command line script', 'Unknown user', 'msg:double-redirect-fixer', 'msg:usermessage-editor', 'msg:proxyblocker', 'msg:sorbs', 'msg:spambot_username', 'msg:autochange-username', ], 'DefaultUserOptions' => [ 'ccmeonemails' => 0, 'date' => 'default', 'diffonly' => 0, 'diff-type' => 'table', 'disablemail' => 0, 'editfont' => 'monospace', 'editondblclick' => 0, 'editrecovery' => 0, 'editsectiononrightclick' => 0, 'email-allow-new-users' => 1, 'enotifminoredits' => 0, 'enotifrevealaddr' => 0, 'enotifusertalkpages' => 1, 'enotifwatchlistpages' => 1, 'extendwatchlist' => 1, 'fancysig' => 0, 'forceeditsummary' => 0, 'forcesafemode' => 0, 'gender' => 'unknown', 'hidecategorization' => 1, 'hideminor' => 0, 'hidepatrolled' => 0, 'imagesize' => 2, 'minordefault' => 0, 'newpageshidepatrolled' => 0, 'nickname' => '', 'norollbackdiff' => 0, 'prefershttps' => 1, 'previewonfirst' => 0, 'previewontop' => 1, 'pst-cssjs' => 1, 'rcdays' => 7, 'rcenhancedfilters-disable' => 0, 'rclimit' => 50, 'requireemail' => 0, 'search-match-redirect' => true, 'search-special-page' => 'Search', 'search-thumbnail-extra-namespaces' => true, 'searchlimit' => 20, 'showhiddencats' => 0, 'shownumberswatching' => 1, 'showrollbackconfirmation' => 0, 'skin' => false, 'skin-responsive' => 1, 'thumbsize' => 5, 'underline' => 2, 'useeditwarning' => 1, 'uselivepreview' => 0, 'usenewrc' => 1, 'watchcreations' => 1, 'watchcreations-expiry' => 'infinite', 'watchdefault' => 1, 'watchdefault-expiry' => 'infinite', 'watchdeletion' => 0, 'watchlistdays' => 7, 'watchlisthideanons' => 0, 'watchlisthidebots' => 0, 'watchlisthidecategorization' => 1, 'watchlisthideliu' => 0, 'watchlisthideminor' => 0, 'watchlisthideown' => 0, 'watchlisthidepatrolled' => 0, 'watchlistreloadautomatically' => 0, 'watchlistunwatchlinks' => 0, 'watchmoves' => 0, 'watchrollback' => 0, 'watchuploads' => 1, 'watchrollback-expiry' => 'infinite', 'watchstar-expiry' => 'infinite', 'wlenhancedfilters-disable' => 0, 'wllimit' => 250, ], 'ConditionalUserOptions' => [ ], 'HiddenPrefs' => [ ], 'UserJsPrefLimit' => 100, 'InvalidUsernameCharacters' => '@:>=', 'UserrightsInterwikiDelimiter' => '@', 'SecureLogin' => false, 'AuthenticationTokenVersion' => null, 'SessionProviders' => [ 'MediaWiki\\Session\\CookieSessionProvider' => [ 'class' => 'MediaWiki\\Session\\CookieSessionProvider', 'args' => [ [ 'priority' => 30, ], ], 'services' => [ 'JwtCodec', 'UrlUtils', ], ], 'MediaWiki\\Session\\BotPasswordSessionProvider' => [ 'class' => 'MediaWiki\\Session\\BotPasswordSessionProvider', 'args' => [ [ 'priority' => 75, ], ], 'services' => [ 'GrantsInfo', ], ], ], 'AutoCreateTempUser' => [ 'known' => false, 'enabled' => false, 'actions' => [ 'edit', ], 'genPattern' => '~$1', 'matchPattern' => null, 'reservedPattern' => '~$1', 'serialProvider' => [ 'type' => 'local', 'useYear' => true, ], 'serialMapping' => [ 'type' => 'readable-numeric', ], 'expireAfterDays' => 90, 'notifyBeforeExpirationDays' => 10, ], 'AutoblockExemptions' => [ ], 'AutoblockExpiry' => 86400, 'BlockAllowsUTEdit' => true, 'BlockCIDRLimit' => [ 'IPv4' => 16, 'IPv6' => 19, ], 'BlockDisablesLogin' => false, 'EnableMultiBlocks' => false, 'WhitelistRead' => false, 'WhitelistReadRegexp' => false, 'EmailConfirmToEdit' => false, 'HideIdentifiableRedirects' => true, 'GroupPermissions' => [ '*' => [ 'createaccount' => true, 'autocreateaccount' => true, 'read' => true, 'edit' => true, 'createpage' => true, 'createtalk' => true, 'viewmyprivateinfo' => true, 'editmyprivateinfo' => true, 'editmyoptions' => true, ], 'user' => [ 'move' => true, 'move-subpages' => true, 'move-rootuserpages' => true, 'move-categorypages' => true, 'movefile' => true, 'read' => true, 'edit' => true, 'createpage' => true, 'createtalk' => true, 'upload' => true, 'reupload' => true, 'reupload-shared' => true, 'minoredit' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, 'editmyuserjsredirect' => true, 'sendemail' => true, 'applychangetags' => true, 'changetags' => true, 'viewmywatchlist' => true, 'editmywatchlist' => true, 'createwithcontentmodel' => true, 'logout' => true, ], 'autoconfirmed' => [ 'autoconfirmed' => true, 'editsemiprotected' => true, ], 'bot' => [ 'bot' => true, 'autoconfirmed' => true, 'editsemiprotected' => true, 'nominornewtalk' => true, 'autopatrol' => true, 'suppressredirect' => true, 'apihighlimits' => true, ], 'sysop' => [ 'block' => true, 'createaccount' => true, 'createpreviouslyrenamedaccount' => true, 'delete' => true, 'bigdelete' => true, 'deletedhistory' => true, 'deletedtext' => true, 'undelete' => true, 'editcontentmodel' => true, 'editinterface' => true, 'editsitejson' => true, 'edituserjson' => true, 'import' => true, 'importupload' => true, 'move' => true, 'move-subpages' => true, 'move-rootuserpages' => true, 'move-categorypages' => true, 'patrol' => true, 'autopatrol' => true, 'protect' => true, 'editprotected' => true, 'rollback' => true, 'upload' => true, 'reupload' => true, 'reupload-shared' => true, 'unwatchedpages' => true, 'autoconfirmed' => true, 'editsemiprotected' => true, 'ipblock-exempt' => true, 'blockemail' => true, 'markbotedits' => true, 'apihighlimits' => true, 'browsearchive' => true, 'noratelimit' => true, 'movefile' => true, 'unblockself' => true, 'suppressredirect' => true, 'mergehistory' => true, 'managechangetags' => true, 'deletechangetags' => true, ], 'interface-admin' => [ 'editinterface' => true, 'editsitecss' => true, 'editsitejson' => true, 'editsitejs' => true, 'editusercss' => true, 'edituserjson' => true, 'edituserjs' => true, ], 'bureaucrat' => [ 'userrights' => true, 'noratelimit' => true, 'renameuser' => true, ], 'suppress' => [ 'hideuser' => true, 'suppressrevision' => true, 'viewsuppressed' => true, 'suppressionlog' => true, 'deleterevision' => true, 'deletelogentry' => true, ], ], 'PrivilegedGroups' => [ 'bureaucrat', 'interface-admin', 'suppress', 'sysop', ], 'RevokePermissions' => [ ], 'GroupInheritsPermissions' => [ ], 'ImplicitGroups' => [ '*', 'user', 'autoconfirmed', ], 'GroupsAddToSelf' => [ ], 'GroupsRemoveFromSelf' => [ ], 'RestrictedGroups' => [ ], 'UserRequirementsPrivateConditions' => [ ], 'RestrictionTypes' => [ 'create', 'edit', 'move', 'upload', ], 'RestrictionLevels' => [ '', 'autoconfirmed', 'sysop', ], 'CascadingRestrictionLevels' => [ 'sysop', ], 'SemiprotectedRestrictionLevels' => [ 'autoconfirmed', ], 'NamespaceProtection' => [ ], 'RestrictUserPageEditing' => false, 'NonincludableNamespaces' => [ ], 'AutoConfirmAge' => 0, 'AutoConfirmCount' => 0, 'Autopromote' => [ 'autoconfirmed' => [ '&', [ 1, null, ], [ 2, null, ], ], ], 'AutopromoteOnce' => [ 'onEdit' => [ ], ], 'AutopromoteOnceLogInRC' => true, 'AutopromoteOnceRCExcludedGroups' => [ ], 'AddGroups' => [ ], 'RemoveGroups' => [ ], 'AvailableRights' => [ ], 'ImplicitRights' => [ ], 'DeleteRevisionsLimit' => 0, 'DeleteRevisionsBatchSize' => 1000, 'HideUserContribLimit' => 1000, 'AccountCreationThrottle' => [ [ 'count' => 0, 'seconds' => 86400, ], ], 'TempAccountCreationThrottle' => [ [ 'count' => 1, 'seconds' => 600, ], [ 'count' => 6, 'seconds' => 86400, ], ], 'TempAccountNameAcquisitionThrottle' => [ [ 'count' => 60, 'seconds' => 86400, ], ], 'SpamRegex' => [ ], 'SummarySpamRegex' => [ ], 'EnableDnsBlacklist' => false, 'DnsBlacklistUrls' => [ ], 'ProxyList' => [ ], 'ProxyWhitelist' => [ ], 'SoftBlockRanges' => [ ], 'ApplyIpBlocksToXff' => false, 'RateLimits' => [ 'edit' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], 'user' => [ 90, 60, ], ], 'move' => [ 'newbie' => [ 2, 120, ], 'user' => [ 8, 60, ], ], 'upload' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], ], 'rollback' => [ 'user' => [ 10, 60, ], 'newbie' => [ 5, 120, ], ], 'mailpassword' => [ 'ip' => [ 5, 3600, ], ], 'sendemail' => [ 'ip' => [ 5, 86400, ], 'newbie' => [ 5, 86400, ], 'user' => [ 20, 86400, ], ], 'changeemail' => [ 'ip-all' => [ 10, 3600, ], 'user' => [ 4, 86400, ], ], 'confirmemail' => [ 'ip-all' => [ 10, 3600, ], 'user' => [ 4, 86400, ], ], 'purge' => [ 'ip' => [ 30, 60, ], 'user' => [ 30, 60, ], ], 'linkpurge' => [ 'ip' => [ 30, 60, ], 'user' => [ 30, 60, ], ], 'renderfile' => [ 'ip' => [ 700, 30, ], 'user' => [ 700, 30, ], ], 'renderfile-nonstandard' => [ 'ip' => [ 70, 30, ], 'user' => [ 70, 30, ], ], 'stashedit' => [ 'ip' => [ 30, 60, ], 'newbie' => [ 30, 60, ], ], 'stashbasehtml' => [ 'ip' => [ 5, 60, ], 'newbie' => [ 5, 60, ], ], 'changetags' => [ 'ip' => [ 8, 60, ], 'newbie' => [ 8, 60, ], ], 'editcontentmodel' => [ 'newbie' => [ 2, 120, ], 'user' => [ 8, 60, ], ], ], 'RateLimitsExcludedIPs' => [ ], 'PutIPinRC' => true, 'QueryPageDefaultLimit' => 50, 'ExternalQuerySources' => [ ], 'PasswordAttemptThrottle' => [ [ 'count' => 5, 'seconds' => 300, ], [ 'count' => 150, 'seconds' => 172800, ], ], 'GrantPermissions' => [ 'basic' => [ 'autocreateaccount' => true, 'autoconfirmed' => true, 'autopatrol' => true, 'editsemiprotected' => true, 'ipblock-exempt' => true, 'nominornewtalk' => true, 'patrolmarks' => true, 'read' => true, 'unwatchedpages' => true, ], 'highvolume' => [ 'bot' => true, 'apihighlimits' => true, 'noratelimit' => true, 'markbotedits' => true, ], 'import' => [ 'import' => true, 'importupload' => true, ], 'editpage' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'pagelang' => true, ], 'editprotected' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editprotected' => true, ], 'editmycssjs' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editmyusercss' => true, 'editmyuserjson' => true, 'editmyuserjs' => true, ], 'editmyoptions' => [ 'editmyoptions' => true, 'editmyuserjson' => true, ], 'editinterface' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, ], 'editsiteconfig' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editinterface' => true, 'edituserjson' => true, 'editsitejson' => true, 'editusercss' => true, 'edituserjs' => true, 'editsitecss' => true, 'editsitejs' => true, ], 'createeditmovepage' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'createpage' => true, 'createtalk' => true, 'delete-redirect' => true, 'move' => true, 'move-rootuserpages' => true, 'move-subpages' => true, 'move-categorypages' => true, 'suppressredirect' => true, ], 'uploadfile' => [ 'upload' => true, 'reupload-own' => true, ], 'uploadeditmovefile' => [ 'upload' => true, 'reupload-own' => true, 'reupload' => true, 'reupload-shared' => true, 'upload_by_url' => true, 'movefile' => true, 'suppressredirect' => true, ], 'patrol' => [ 'patrol' => true, ], 'rollback' => [ 'rollback' => true, ], 'blockusers' => [ 'block' => true, 'blockemail' => true, ], 'viewdeleted' => [ 'browsearchive' => true, 'deletedhistory' => true, 'deletedtext' => true, ], 'viewrestrictedlogs' => [ 'suppressionlog' => true, ], 'delete' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'browsearchive' => true, 'deletedhistory' => true, 'deletedtext' => true, 'delete' => true, 'bigdelete' => true, 'deletelogentry' => true, 'deleterevision' => true, 'undelete' => true, ], 'oversight' => [ 'suppressrevision' => true, 'viewsuppressed' => true, ], 'protect' => [ 'edit' => true, 'minoredit' => true, 'applychangetags' => true, 'changetags' => true, 'editcontentmodel' => true, 'createwithcontentmodel' => true, 'editprotected' => true, 'protect' => true, ], 'viewmywatchlist' => [ 'viewmywatchlist' => true, ], 'editmywatchlist' => [ 'editmywatchlist' => true, ], 'sendemail' => [ 'sendemail' => true, ], 'createaccount' => [ 'createaccount' => true, ], 'privateinfo' => [ 'viewmyprivateinfo' => true, ], 'mergehistory' => [ 'mergehistory' => true, ], 'managesessions' => [ 'logout' => true, ], ], 'GrantPermissionGroups' => [ 'basic' => 'hidden', 'editpage' => 'page-interaction', 'createeditmovepage' => 'page-interaction', 'editprotected' => 'page-interaction', 'patrol' => 'page-interaction', 'uploadfile' => 'file-interaction', 'uploadeditmovefile' => 'file-interaction', 'sendemail' => 'email', 'viewmywatchlist' => 'watchlist-interaction', 'editmywatchlist' => 'watchlist-interaction', 'editmycssjs' => 'customization', 'editmyoptions' => 'customization', 'editinterface' => 'administration', 'editsiteconfig' => 'administration', 'rollback' => 'administration', 'blockusers' => 'administration', 'delete' => 'administration', 'viewdeleted' => 'administration', 'viewrestrictedlogs' => 'administration', 'protect' => 'administration', 'oversight' => 'administration', 'createaccount' => 'administration', 'mergehistory' => 'administration', 'import' => 'administration', 'highvolume' => 'high-volume', 'privateinfo' => 'private-information', 'managesessions' => 'private-information', ], 'GrantRiskGroups' => [ 'basic' => 'low', 'editpage' => 'low', 'createeditmovepage' => 'low', 'editprotected' => 'vandalism', 'patrol' => 'low', 'uploadfile' => 'low', 'uploadeditmovefile' => 'low', 'sendemail' => 'security', 'viewmywatchlist' => 'low', 'editmywatchlist' => 'low', 'editmycssjs' => 'security', 'editmyoptions' => 'security', 'editinterface' => 'vandalism', 'editsiteconfig' => 'security', 'rollback' => 'low', 'blockusers' => 'vandalism', 'delete' => 'vandalism', 'viewdeleted' => 'vandalism', 'viewrestrictedlogs' => 'security', 'protect' => 'vandalism', 'oversight' => 'security', 'createaccount' => 'low', 'mergehistory' => 'vandalism', 'import' => 'security', 'highvolume' => 'low', 'privateinfo' => 'low', 'managesessions' => 'low', ], 'EnableBotPasswords' => true, 'BotPasswordsCluster' => false, 'BotPasswordsDatabase' => false, 'BotPasswordsLimit' => 100, 'SecretKey' => false, 'JwtPrivateKey' => false, 'JwtPublicKey' => false, 'AllowUserJs' => false, 'ReauthenticateForActions' => [ 'edituserjs' => 'edituserjscss', 'editusercss' => 'edituserjscss', 'editsitejs' => 'editsitejscss', 'editsitecss' => 'editsitejscss', ], 'AllowUserCss' => false, 'AllowUserCssPrefs' => true, 'UseSiteJs' => true, 'UseSiteCss' => true, 'BreakFrames' => false, 'EditPageFrameOptions' => 'DENY', 'ApiFrameOptions' => 'DENY', 'CSPHeader' => false, 'CSPReportOnlyHeader' => false, 'CSPUseReportURIDirective' => false, 'CSPFalsePositiveUrls' => [ 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'https: 'chrome-extension' => true, ], 'AllowCrossOrigin' => false, 'RestAllowCrossOriginCookieAuth' => false, 'SessionSecret' => false, 'CookieExpiration' => 2592000, 'ExtendedLoginCookieExpiration' => 15552000, 'SessionCookieJwtExpiration' => 14400, 'CookieDomain' => '', 'CookiePath' => '/', 'CookieSecure' => 'detect', 'CookiePrefix' => false, 'CookieHttpOnly' => true, 'CookieSameSite' => null, 'CacheVaryCookies' => [ ], 'SessionName' => false, 'CookieSetOnAutoblock' => true, 'CookieSetOnIpBlock' => true, 'DebugLogFile' => '', 'DebugLogPrefix' => '', 'DebugRedirects' => false, 'DebugRawPage' => false, 'DebugComments' => false, 'DebugDumpSql' => false, 'TrxProfilerLimits' => [ 'GET' => [ 'masterConns' => 0, 'writes' => 0, 'readQueryTime' => 5, 'readQueryRows' => 10000, ], 'POST' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 100000, 'maxAffected' => 1000, ], 'POST-nonwrite' => [ 'writes' => 0, 'readQueryTime' => 5, 'readQueryRows' => 10000, ], 'PostSend-GET' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 10000, 'maxAffected' => 1000, 'masterConns' => 0, 'writes' => 0, ], 'PostSend-POST' => [ 'readQueryTime' => 5, 'writeQueryTime' => 1, 'readQueryRows' => 100000, 'maxAffected' => 1000, ], 'JobRunner' => [ 'readQueryTime' => 30, 'writeQueryTime' => 5, 'readQueryRows' => 100000, 'maxAffected' => 500, ], 'Maintenance' => [ 'writeQueryTime' => 5, 'maxAffected' => 1000, ], ], 'DebugLogGroups' => [ ], 'MWLoggerDefaultSpi' => [ 'class' => 'MediaWiki\\Logger\\LegacySpi', ], 'ShowDebug' => false, 'SpecialVersionShowHooks' => false, 'ShowExceptionDetails' => false, 'LogExceptionBacktrace' => true, 'PropagateErrors' => true, 'ShowHostnames' => false, 'OverrideHostname' => false, 'DevelopmentWarnings' => false, 'DeprecationReleaseLimit' => false, 'Profiler' => [ ], 'StatsdServer' => false, 'StatsdMetricPrefix' => 'MediaWiki', 'StatsTarget' => null, 'StatsFormat' => null, 'StatsPrefix' => 'mediawiki', 'OpenTelemetryConfig' => null, 'PageInfoTransclusionLimit' => 50, 'EnableJavaScriptTest' => false, 'DebugToolbar' => false, 'ApiClientErrorSampleRate' => 1.0, 'DisableTextSearch' => false, 'AdvancedSearchHighlighting' => false, 'SearchHighlightBoundaries' => '[\\p{Z}\\p{P}\\p{C}]', 'OpenSearchTemplates' => [ 'application/x-suggestions+json' => false, 'application/x-suggestions+xml' => false, ], 'OpenSearchDefaultLimit' => 10, 'OpenSearchDescriptionLength' => 100, 'SearchSuggestCacheExpiry' => 1200, 'DisableSearchUpdate' => false, 'NamespacesToBeSearchedDefault' => [ true, ], 'DisableInternalSearch' => false, 'SearchForwardUrl' => null, 'SitemapNamespaces' => false, 'SitemapNamespacesPriorities' => false, 'SitemapApiConfig' => [ ], 'SpecialSearchFormOptions' => [ ], 'SearchMatchRedirectPreference' => false, 'SearchRunSuggestedQuery' => true, 'Diff3' => '/usr/bin/diff3', 'Diff' => '/usr/bin/diff', 'PreviewOnOpenNamespaces' => [ 14 => true, ], 'UniversalEditButton' => true, 'UseAutomaticEditSummaries' => true, 'CommandLineDarkBg' => false, 'ReadOnly' => null, 'ReadOnlyWatchedItemStore' => false, 'ReadOnlyFile' => false, 'UpgradeKey' => false, 'GitBin' => '/usr/bin/git', 'GitRepositoryViewers' => [ 'https: 'ssh: 'https: 'git@github\\.com:(.*?)(\\.git)?' => 'https: ], 'InstallerInitialPages' => [ [ 'titlemsg' => 'mainpage', 'text' => '{{subst:int:mainpagetext}}{{subst:int:mainpagedocfooter}}', ], ], 'RCMaxAge' => 7776000, 'WatchersMaxAge' => 15552000, 'UnwatchedPageSecret' => 1, 'RCFilterByAge' => false, 'RCLinkLimits' => [ 50, 100, 250, 500, ], 'RCLinkDays' => [ 1, 3, 7, 14, 30, ], 'RCFeeds' => [ ], 'RCWatchCategoryMembership' => false, 'UseRCPatrol' => true, 'StructuredChangeFiltersLiveUpdatePollingRate' => 3, 'UseNPPatrol' => true, 'UseFilePatrol' => true, 'Feed' => true, 'FeedLimit' => 50, 'FeedCacheTimeout' => 60, 'FeedDiffCutoff' => 32768, 'OverrideSiteFeed' => [ ], 'FeedClasses' => [ 'rss' => 'MediaWiki\\Feed\\RSSFeed', 'atom' => 'MediaWiki\\Feed\\AtomFeed', ], 'AdvertisedFeedTypes' => [ 'atom', ], 'RCShowWatchingUsers' => false, 'RCShowChangedSize' => true, 'RCChangedSizeThreshold' => 500, 'ShowUpdatedMarker' => true, 'DisableAnonTalk' => false, 'UseTagFilter' => true, 'SoftwareTags' => [ 'mw-contentmodelchange' => true, 'mw-new-redirect' => true, 'mw-removed-redirect' => true, 'mw-changed-redirect-target' => true, 'mw-blank' => true, 'mw-replace' => true, 'mw-recreated' => true, 'mw-rollback' => true, 'mw-undo' => true, 'mw-manual-revert' => true, 'mw-reverted' => true, 'mw-server-side-upload' => true, 'mw-ipblock-appeal' => true, 'mw-edited-other-users-js' => true, 'mw-edited-other-users-css' => true, ], 'RestrictedTagViewRights' => [ ], 'UnwatchedPageThreshold' => false, 'RecentChangesFlags' => [ 'newpage' => [ 'letter' => 'newpageletter', 'title' => 'recentchanges-label-newpage', 'legend' => 'recentchanges-legend-newpage', 'grouping' => 'any', ], 'minor' => [ 'letter' => 'minoreditletter', 'title' => 'recentchanges-label-minor', 'legend' => 'recentchanges-legend-minor', 'class' => 'minoredit', 'grouping' => 'all', ], 'bot' => [ 'letter' => 'boteditletter', 'title' => 'recentchanges-label-bot', 'legend' => 'recentchanges-legend-bot', 'class' => 'botedit', 'grouping' => 'all', ], 'unpatrolled' => [ 'letter' => 'unpatrolledletter', 'title' => 'recentchanges-label-unpatrolled', 'legend' => 'recentchanges-legend-unpatrolled', 'grouping' => 'any', ], ], 'WatchlistExpiry' => false, 'EnableWatchstarPopover' => false, 'EnableWatchlistLabels' => false, 'WatchlistLabelsMaxPerUser' => 100, 'WatchlistPurgeRate' => 0.1, 'WatchlistExpiryMaxDuration' => '1 year', 'EnableChangesListQueryPartitioning' => false, 'RightsPage' => null, 'RightsUrl' => null, 'RightsText' => null, 'RightsIcon' => null, 'UseCopyrightUpload' => false, 'MaxCredits' => 0, 'ShowCreditsIfMax' => true, 'ImportSources' => [ ], 'ImportTargetNamespace' => null, 'ExportAllowHistory' => true, 'ExportMaxHistory' => 0, 'ExportAllowListContributors' => false, 'ExportMaxLinkDepth' => 0, 'ExportFromNamespaces' => false, 'ExportAllowAll' => false, 'ExportPagelistLimit' => 5000, 'XmlDumpSchemaVersion' => '0.11', 'WikiFarmSettingsDirectory' => null, 'WikiFarmSettingsExtension' => 'yaml', 'ExtensionFunctions' => [ ], 'ExtensionMessagesFiles' => [ ], 'MessagesDirs' => [ ], 'TranslationAliasesDirs' => [ ], 'ExtensionEntryPointListFiles' => [ ], 'EnableParserLimitReporting' => true, 'ValidSkinNames' => [ ], 'SpecialPages' => [ ], 'ExtensionCredits' => [ ], 'Hooks' => [ ], 'ServiceWiringFiles' => [ ], 'JobClasses' => [ 'deletePage' => 'MediaWiki\\Page\\DeletePageJob', 'refreshLinks' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'deleteLinks' => 'MediaWiki\\Page\\DeleteLinksJob', 'htmlCacheUpdate' => 'MediaWiki\\JobQueue\\Jobs\\HTMLCacheUpdateJob', 'sendMail' => [ 'class' => 'MediaWiki\\Mail\\EmaillingJob', 'services' => [ 'Emailer', ], ], 'enotifNotify' => [ 'class' => 'MediaWiki\\RecentChanges\\RecentChangeNotifyJob', 'services' => [ 'RecentChangeLookup', ], ], 'fixDoubleRedirect' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\DoubleRedirectJob', 'services' => [ 'RevisionLookup', 'MagicWordFactory', 'WikiPageFactory', ], 'needsPage' => true, ], 'AssembleUploadChunks' => 'MediaWiki\\JobQueue\\Jobs\\AssembleUploadChunksJob', 'PublishStashedFile' => 'MediaWiki\\JobQueue\\Jobs\\PublishStashedFileJob', 'ThumbnailRender' => 'MediaWiki\\JobQueue\\Jobs\\ThumbnailRenderJob', 'UploadFromUrl' => 'MediaWiki\\JobQueue\\Jobs\\UploadFromUrlJob', 'recentChangesUpdate' => 'MediaWiki\\RecentChanges\\RecentChangesUpdateJob', 'refreshLinksPrioritized' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'refreshLinksDynamic' => 'MediaWiki\\JobQueue\\Jobs\\RefreshLinksJob', 'activityUpdateJob' => 'MediaWiki\\Watchlist\\ActivityUpdateJob', 'categoryMembershipChange' => [ 'class' => 'MediaWiki\\RecentChanges\\CategoryMembershipChangeJob', 'services' => [ 'RecentChangeFactory', ], ], 'CategoryCountUpdateJob' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\CategoryCountUpdateJob', 'services' => [ 'ConnectionProvider', 'NamespaceInfo', ], ], 'clearUserWatchlist' => 'MediaWiki\\Watchlist\\ClearUserWatchlistJob', 'watchlistExpiry' => 'MediaWiki\\Watchlist\\WatchlistExpiryJob', 'cdnPurge' => 'MediaWiki\\JobQueue\\Jobs\\CdnPurgeJob', 'userGroupExpiry' => 'MediaWiki\\User\\UserGroupExpiryJob', 'clearWatchlistNotifications' => 'MediaWiki\\Watchlist\\ClearWatchlistNotificationsJob', 'userOptionsUpdate' => 'MediaWiki\\User\\Options\\UserOptionsUpdateJob', 'revertedTagUpdate' => 'MediaWiki\\JobQueue\\Jobs\\RevertedTagUpdateJob', 'null' => 'MediaWiki\\JobQueue\\Jobs\\NullJob', 'userEditCountInit' => 'MediaWiki\\User\\UserEditCountInitJob', 'parsoidCachePrewarm' => [ 'class' => 'MediaWiki\\JobQueue\\Jobs\\ParsoidCachePrewarmJob', 'services' => [ 'ParserOutputAccess', 'PageStore', 'RevisionLookup', 'ParsoidSiteConfig', ], 'needsPage' => false, ], 'renameUserTable' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserTableJob', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', ], ], 'renameUserDerived' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserDerivedJob', 'services' => [ 'RenameUserFactory', 'UserFactory', ], ], 'renameUser' => [ 'class' => 'MediaWiki\\RenameUser\\Job\\RenameUserTableJob', 'services' => [ 'MainConfig', 'DBLoadBalancerFactory', ], ], ], 'JobTypesExcludedFromDefaultQueue' => [ 'AssembleUploadChunks', 'PublishStashedFile', 'UploadFromUrl', ], 'JobBackoffThrottling' => [ ], 'JobTypeConf' => [ 'default' => [ 'class' => 'MediaWiki\\JobQueue\\JobQueueDB', 'order' => 'random', 'claimTTL' => 3600, ], ], 'JobQueueIncludeInMaxLagFactor' => false, 'SpecialPageCacheUpdates' => [ 'Statistics' => [ 'MediaWiki\\Deferred\\SiteStatsUpdate', 'cacheUpdate', ], ], 'PagePropLinkInvalidations' => [ 'hiddencat' => 'categorylinks', ], 'CategoryMagicGallery' => true, 'CategoryPagingLimit' => 200, 'CategoryCollation' => 'uppercase', 'TempCategoryCollations' => [ ], 'SortedCategories' => false, 'TrackingCategories' => [ ], 'LogTypes' => [ '', 'block', 'protect', 'rights', 'delete', 'upload', 'move', 'import', 'interwiki', 'patrol', 'merge', 'suppress', 'tag', 'managetags', 'contentmodel', 'renameuser', ], 'LogRestrictions' => [ 'suppress' => 'suppressionlog', ], 'FilterLogTypes' => [ 'patrol' => true, 'tag' => true, 'newusers' => false, ], 'LogNames' => [ '' => 'all-logs-page', 'block' => 'blocklogpage', 'protect' => 'protectlogpage', 'rights' => 'rightslog', 'delete' => 'dellogpage', 'upload' => 'uploadlogpage', 'move' => 'movelogpage', 'import' => 'importlogpage', 'patrol' => 'patrol-log-page', 'merge' => 'mergelog', 'suppress' => 'suppressionlog', ], 'LogHeaders' => [ '' => 'alllogstext', 'block' => 'blocklogtext', 'delete' => 'dellogpagetext', 'import' => 'importlogpagetext', 'merge' => 'mergelogpagetext', 'move' => 'movelogpagetext', 'patrol' => 'patrol-log-header', 'protect' => 'protectlogtext', 'rights' => 'rightslogtext', 'suppress' => 'suppressionlogtext', 'upload' => 'uploadlogpagetext', ], 'LogActions' => [ ], 'LogActionsHandlers' => [ 'block/block' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'block/reblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'block/unblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'contentmodel/change' => 'MediaWiki\\Logging\\ContentModelLogFormatter', 'contentmodel/new' => 'MediaWiki\\Logging\\ContentModelLogFormatter', 'delete/delete' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/delete_redir' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/delete_redir2' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/event' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/restore' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'delete/revision' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'import/interwiki' => 'MediaWiki\\Logging\\ImportLogFormatter', 'import/upload' => 'MediaWiki\\Logging\\ImportLogFormatter', 'interwiki/iw_add' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'interwiki/iw_delete' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'interwiki/iw_edit' => 'MediaWiki\\Logging\\InterwikiLogFormatter', 'managetags/activate' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/create' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/deactivate' => 'MediaWiki\\Logging\\LogFormatter', 'managetags/delete' => 'MediaWiki\\Logging\\LogFormatter', 'merge/merge' => [ 'class' => 'MediaWiki\\Logging\\MergeLogFormatter', 'services' => [ 'TitleParser', ], ], 'merge/merge-into' => [ 'class' => 'MediaWiki\\Logging\\MergeLogFormatter', 'services' => [ 'TitleParser', ], ], 'move/move' => [ 'class' => 'MediaWiki\\Logging\\MoveLogFormatter', 'services' => [ 'TitleParser', ], ], 'move/move_redir' => [ 'class' => 'MediaWiki\\Logging\\MoveLogFormatter', 'services' => [ 'TitleParser', ], ], 'patrol/patrol' => 'MediaWiki\\Logging\\PatrolLogFormatter', 'patrol/autopatrol' => 'MediaWiki\\Logging\\PatrolLogFormatter', 'protect/modify' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/move_prot' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/protect' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'protect/unprotect' => [ 'class' => 'MediaWiki\\Logging\\ProtectLogFormatter', 'services' => [ 'TitleParser', ], ], 'renameuser/renameuser' => [ 'class' => 'MediaWiki\\Logging\\RenameuserLogFormatter', 'services' => [ 'TitleParser', ], ], 'rights/autopromote' => 'MediaWiki\\Logging\\RightsLogFormatter', 'rights/rights' => 'MediaWiki\\Logging\\RightsLogFormatter', 'suppress/block' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'suppress/delete' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'suppress/event' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'suppress/reblock' => [ 'class' => 'MediaWiki\\Logging\\BlockLogFormatter', 'services' => [ 'TitleParser', 'NamespaceInfo', ], ], 'suppress/revision' => 'MediaWiki\\Logging\\DeleteLogFormatter', 'tag/update' => 'MediaWiki\\Logging\\TagLogFormatter', 'upload/overwrite' => 'MediaWiki\\Logging\\UploadLogFormatter', 'upload/revert' => 'MediaWiki\\Logging\\UploadLogFormatter', 'upload/upload' => 'MediaWiki\\Logging\\UploadLogFormatter', ], 'ActionFilteredLogs' => [ 'block' => [ 'block' => [ 'block', ], 'reblock' => [ 'reblock', ], 'unblock' => [ 'unblock', ], ], 'contentmodel' => [ 'change' => [ 'change', ], 'new' => [ 'new', ], ], 'delete' => [ 'delete' => [ 'delete', ], 'delete_redir' => [ 'delete_redir', 'delete_redir2', ], 'restore' => [ 'restore', ], 'event' => [ 'event', ], 'revision' => [ 'revision', ], ], 'import' => [ 'interwiki' => [ 'interwiki', ], 'upload' => [ 'upload', ], ], 'managetags' => [ 'create' => [ 'create', ], 'delete' => [ 'delete', ], 'activate' => [ 'activate', ], 'deactivate' => [ 'deactivate', ], ], 'move' => [ 'move' => [ 'move', ], 'move_redir' => [ 'move_redir', ], ], 'newusers' => [ 'create' => [ 'create', 'newusers', ], 'create2' => [ 'create2', ], 'autocreate' => [ 'autocreate', ], 'byemail' => [ 'byemail', ], ], 'protect' => [ 'protect' => [ 'protect', ], 'modify' => [ 'modify', ], 'unprotect' => [ 'unprotect', ], 'move_prot' => [ 'move_prot', ], ], 'rights' => [ 'rights' => [ 'rights', ], 'autopromote' => [ 'autopromote', ], ], 'suppress' => [ 'event' => [ 'event', ], 'revision' => [ 'revision', ], 'delete' => [ 'delete', ], 'block' => [ 'block', ], 'reblock' => [ 'reblock', ], ], 'upload' => [ 'upload' => [ 'upload', ], 'overwrite' => [ 'overwrite', ], 'revert' => [ 'revert', ], ], ], 'NewUserLog' => true, 'PageCreationLog' => true, 'AllowSpecialInclusion' => true, 'DisableQueryPageUpdate' => false, 'CountCategorizedImagesAsUsed' => false, 'MaxRedirectLinksRetrieved' => 500, 'RangeContributionsCIDRLimit' => [ 'IPv4' => 16, 'IPv6' => 32, ], 'Actions' => [ ], 'DefaultRobotPolicy' => 'index,follow', 'NamespaceRobotPolicies' => [ ], 'ArticleRobotPolicies' => [ ], 'ExemptFromUserRobotsControl' => null, 'DebugAPI' => false, 'APIModules' => [ ], 'APIFormatModules' => [ ], 'APIMetaModules' => [ ], 'APIPropModules' => [ ], 'APIListModules' => [ ], 'APIMaxDBRows' => 5000, 'APIMaxResultSize' => 8388608, 'APIMaxUncachedDiffs' => 1, 'APIMaxLagThreshold' => 7, 'APICacheHelpTimeout' => 3600, 'APIUselessQueryPages' => [ 'MIMEsearch', 'LinkSearch', ], 'AjaxLicensePreview' => true, 'CrossSiteAJAXdomains' => [ ], 'CrossSiteAJAXdomainExceptions' => [ ], 'AllowedCorsHeaders' => [ 'Accept', 'Accept-Language', 'Content-Language', 'Content-Type', 'Accept-Encoding', 'DNT', 'Origin', 'User-Agent', 'Api-User-Agent', 'Promise-Non-Write-API-Action', 'Access-Control-Max-Age', 'Authorization', ], 'RestAPIAdditionalRouteFiles' => [ ], 'RestLocalModuleTestBaseUrl' => null, 'RestModuleOverrides' => [ ], 'RestExternalModules' => [ ], 'MaxShellMemory' => 307200, 'MaxShellFileSize' => 102400, 'MaxShellTime' => 180, 'MaxShellWallClockTime' => 180, 'ShellCgroup' => false, 'PhpCli' => '/usr/bin/php', 'ShellRestrictionMethod' => 'autodetect', 'ShellboxUrls' => [ 'default' => null, ], 'ShellboxSecretKey' => null, 'ShellboxShell' => '/bin/sh', 'HTTPTimeout' => 25, 'HTTPConnectTimeout' => 5.0, 'HTTPMaxTimeout' => 0, 'HTTPMaxConnectTimeout' => 0, 'HTTPImportTimeout' => 25, 'AsyncHTTPTimeout' => 25, 'HTTPProxy' => '', 'LocalVirtualHosts' => [ ], 'LocalHTTPProxy' => false, 'AllowExternalReqID' => false, 'GenerateReqIDFormat' => 'rand24', 'JobRunRate' => 1, 'RunJobsAsync' => false, 'UpdateRowsPerJob' => 300, 'UpdateRowsPerQuery' => 100, 'RedirectOnLogin' => null, 'VirtualRestConfig' => [ 'paths' => [ ], 'modules' => [ ], 'global' => [ 'timeout' => 360, 'forwardCookies' => false, 'HTTPProxy' => null, ], ], 'EventRelayerConfig' => [ 'default' => [ 'class' => 'Wikimedia\\EventRelayer\\EventRelayerNull', ], ], 'Pingback' => false, 'OriginTrials' => [ ], 'ReportToExpiry' => 86400, 'ReportToEndpoints' => [ ], 'FeaturePolicyReportOnly' => [ ], 'SkinsPreferred' => [ 'vector-2022', 'vector', ], 'SpecialContributeSkinsEnabled' => [ ], 'SpecialContributeNewPageTarget' => null, 'EnableEditRecovery' => false, 'EditRecoveryExpiry' => 2592000, 'UseCodexSpecialBlock' => false, 'ShowLogoutConfirmation' => false, 'EnableProtectionIndicators' => true, 'OutputPipelineStages' => [ ], 'FeatureShutdown' => [ ], 'CloneArticleParserOutput' => true, 'UseLeximorph' => false, 'UsePostprocCacheLegacy' => false, 'UsePostprocCacheParsoid' => true, 'ParserOptionsLogUnsafeSampleRate' => 0, 'ReturnExperimentalPFragmentTypes' => [ ], 'UseParsoidLinksUpdate' => null, 'UseParsoidMessages' => null, ], 'type' => [ 'ConfigRegistry' => 'object', 'AssumeProxiesUseDefaultProtocolPorts' => 'boolean', 'ForceHTTPS' => 'boolean', 'ExtensionDirectory' => [ 'string', 'null', ], 'StyleDirectory' => [ 'string', 'null', ], 'UploadDirectory' => [ 'string', 'boolean', 'null', ], 'Logos' => [ 'object', 'boolean', ], 'ReferrerPolicy' => [ 'array', 'string', 'boolean', ], 'ActionPaths' => 'object', 'MainPageIsDomainRoot' => 'boolean', 'ImgAuthUrlPathMap' => 'object', 'LocalFileRepo' => 'object', 'ForeignFileRepos' => 'array', 'UseSharedUploads' => 'boolean', 'SharedUploadDirectory' => [ 'string', 'null', ], 'SharedUploadPath' => [ 'string', 'null', ], 'HashedSharedUploadDirectory' => 'boolean', 'FetchCommonsDescriptions' => 'boolean', 'SharedUploadDBname' => [ 'boolean', 'string', ], 'SharedUploadDBprefix' => 'string', 'CacheSharedUploads' => 'boolean', 'ForeignUploadTargets' => 'array', 'UploadDialog' => 'object', 'FileBackends' => 'object', 'LockManagers' => 'array', 'DefaultLockManager' => [ 'string', 'null', ], 'CopyUploadsDomains' => 'array', 'CopyUploadTimeout' => [ 'boolean', 'integer', ], 'SharedThumbnailScriptPath' => [ 'string', 'boolean', ], 'HashedUploadDirectory' => 'boolean', 'CSPUploadEntryPoint' => 'boolean', 'FileExtensions' => 'array', 'ProhibitedFileExtensions' => 'array', 'MimeTypeExclusions' => 'array', 'TrustedMediaFormats' => 'array', 'MediaHandlers' => 'object', 'NativeImageLazyLoading' => 'boolean', 'ParserTestMediaHandlers' => 'object', 'MaxInterlacingAreas' => 'object', 'SVGConverters' => 'object', 'SVGNativeRendering' => [ 'string', 'boolean', ], 'MaxImageArea' => [ 'string', 'integer', 'boolean', ], 'WebPThumbnailType' => 'array', 'TiffThumbnailType' => 'array', 'GenerateThumbnailOnParse' => 'boolean', 'EnableAutoRotation' => [ 'boolean', 'null', ], 'Antivirus' => [ 'string', 'null', ], 'AntivirusSetup' => 'object', 'MimeDetectorCommand' => [ 'string', 'null', ], 'XMLMimeTypes' => 'object', 'ImageLimits' => 'array', 'ThumbLimits' => 'array', 'ThumbnailNamespaces' => 'array', 'ThumbnailSteps' => [ 'array', 'null', ], 'ThumbnailBuckets' => [ 'array', 'null', ], 'UploadThumbnailRenderMap' => 'object', 'GalleryOptions' => 'object', 'DjvuDump' => [ 'string', 'null', ], 'DjvuRenderer' => [ 'string', 'null', ], 'DjvuTxt' => [ 'string', 'null', ], 'DjvuPostProcessor' => [ 'string', 'null', ], 'RestTermsOfServiceUrl' => [ 'string', 'null', ], 'SMTP' => [ 'boolean', 'object', ], 'EnotifFromEditor' => 'boolean', 'EmailConfirmationBanner' => 'boolean', 'EnotifRevealEditorAddress' => 'boolean', 'UsersNotifiedOnAllChanges' => 'object', 'DBmwschema' => [ 'string', 'null', ], 'SharedTables' => 'array', 'DBservers' => [ 'boolean', 'array', ], 'LBFactoryConf' => 'object', 'LocalDatabases' => 'array', 'VirtualDomainsMapping' => 'object', 'RemoteVirtualDomainsMapping' => 'object', 'FileSchemaMigrationStage' => 'integer', 'ExternalLinksDomainGaps' => 'object', 'ContentHandlers' => 'object', 'NamespaceContentModels' => 'object', 'TextModelsToParse' => 'array', 'ExternalStores' => 'array', 'ExternalServers' => 'object', 'DefaultExternalStore' => [ 'array', 'boolean', ], 'RevisionCacheExpiry' => 'integer', 'PageLanguageUseDB' => 'boolean', 'DiffEngine' => [ 'string', 'null', ], 'ExternalDiffEngine' => [ 'string', 'boolean', ], 'Wikidiff2Options' => 'object', 'RequestTimeLimit' => [ 'integer', 'null', ], 'CriticalSectionTimeLimit' => 'number', 'PoolCounterConf' => [ 'object', 'null', ], 'PoolCountClientConf' => 'object', 'MaxUserDBWriteDuration' => [ 'integer', 'boolean', ], 'MaxJobDBWriteDuration' => [ 'integer', 'boolean', ], 'MultiShardSiteStats' => 'boolean', 'ObjectCaches' => 'object', 'WANObjectCache' => 'object', 'MicroStashType' => [ 'string', 'integer', ], 'ParsoidCacheConfig' => 'object', 'ParsoidSelectiveUpdateSampleRate' => 'integer', 'SplitParsoidParserCache' => 'boolean', 'ParserCacheFilterConfig' => 'object', 'ChronologyProtectorSecret' => 'string', 'SuspiciousIpExpiry' => [ 'integer', 'boolean', ], 'MemCachedServers' => 'array', 'LocalisationCacheConf' => 'object', 'ExtensionInfoMTime' => [ 'integer', 'boolean', ], 'CdnServers' => 'object', 'CdnServersNoPurge' => 'object', 'HTCPRouting' => 'object', 'GrammarForms' => 'object', 'ExtraInterlanguageLinkPrefixes' => 'array', 'InterlanguageLinkCodeMap' => 'object', 'ExtraLanguageNames' => 'object', 'ExtraLanguageCodes' => 'object', 'DummyLanguageCodes' => 'object', 'DisabledVariants' => 'object', 'ForceUIMsgAsContentMsg' => 'object', 'RawHtmlMessages' => 'array', 'OverrideUcfirstCharacters' => 'object', 'XhtmlNamespaces' => 'object', 'BrowserFormatDetection' => 'string', 'SkinMetaTags' => 'object', 'SkipSkins' => 'object', 'FragmentMode' => 'array', 'FooterIcons' => 'object', 'InterwikiLogoOverride' => 'array', 'ResourceModules' => 'object', 'ResourceModuleSkinStyles' => 'object', 'ResourceLoaderSources' => 'object', 'ResourceLoaderMaxage' => 'object', 'ResourceLoaderMaxQueryLength' => [ 'integer', 'boolean', ], 'CanonicalNamespaceNames' => 'object', 'ExtraNamespaces' => 'object', 'ExtraGenderNamespaces' => 'object', 'NamespaceAliases' => 'object', 'CapitalLinkOverrides' => 'object', 'NamespacesWithSubpages' => 'object', 'NamespacesWithoutAutoSummaries' => 'array', 'ContentNamespaces' => 'array', 'ShortPagesNamespaceExclusions' => 'array', 'ExtraSignatureNamespaces' => 'array', 'InvalidRedirectTargets' => 'array', 'LocalInterwikis' => 'array', 'InterwikiCache' => [ 'boolean', 'object', ], 'SiteTypes' => 'object', 'UrlProtocols' => 'array', 'TidyConfig' => 'object', 'ParsoidSettings' => 'object', 'ParsoidExperimentalParserFunctionOutput' => 'boolean', 'NoFollowNsExceptions' => 'array', 'NoFollowDomainExceptions' => 'array', 'ExternalLinksIgnoreDomains' => 'array', 'EnableMagicLinks' => 'object', 'ManualRevertSearchRadius' => 'integer', 'RevertedTagMaxDepth' => 'integer', 'CentralIdLookupProviders' => 'object', 'CentralIdLookupProvider' => 'string', 'UserRegistrationProviders' => 'object', 'PasswordPolicy' => 'object', 'AuthManagerConfig' => [ 'object', 'null', ], 'AuthManagerAutoConfig' => 'object', 'RememberMe' => 'string', 'ReauthenticateTime' => 'object', 'ChangeCredentialsBlacklist' => 'array', 'RemoveCredentialsBlacklist' => 'array', 'PasswordConfig' => 'object', 'PasswordResetRoutes' => 'object', 'SignatureAllowedLintErrors' => 'array', 'ReservedUsernames' => 'array', 'DefaultUserOptions' => 'object', 'ConditionalUserOptions' => 'object', 'HiddenPrefs' => 'array', 'UserJsPrefLimit' => 'integer', 'AuthenticationTokenVersion' => [ 'string', 'null', ], 'SessionProviders' => 'object', 'AutoCreateTempUser' => 'object', 'AutoblockExemptions' => 'array', 'BlockCIDRLimit' => 'object', 'EnableMultiBlocks' => 'boolean', 'GroupPermissions' => 'object', 'PrivilegedGroups' => 'array', 'RevokePermissions' => 'object', 'GroupInheritsPermissions' => 'object', 'ImplicitGroups' => 'array', 'GroupsAddToSelf' => 'object', 'GroupsRemoveFromSelf' => 'object', 'RestrictedGroups' => 'object', 'UserRequirementsPrivateConditions' => 'array', 'RestrictionTypes' => 'array', 'RestrictionLevels' => 'array', 'CascadingRestrictionLevels' => 'array', 'SemiprotectedRestrictionLevels' => 'array', 'NamespaceProtection' => 'object', 'RestrictUserPageEditing' => 'boolean', 'NonincludableNamespaces' => 'object', 'Autopromote' => 'object', 'AutopromoteOnce' => 'object', 'AutopromoteOnceRCExcludedGroups' => 'array', 'AddGroups' => 'object', 'RemoveGroups' => 'object', 'AvailableRights' => 'array', 'ImplicitRights' => 'array', 'AccountCreationThrottle' => [ 'integer', 'array', ], 'TempAccountCreationThrottle' => 'array', 'TempAccountNameAcquisitionThrottle' => 'array', 'SpamRegex' => 'array', 'SummarySpamRegex' => 'array', 'DnsBlacklistUrls' => 'array', 'ProxyList' => [ 'string', 'array', ], 'ProxyWhitelist' => 'array', 'SoftBlockRanges' => 'array', 'RateLimits' => 'object', 'RateLimitsExcludedIPs' => 'array', 'ExternalQuerySources' => 'object', 'PasswordAttemptThrottle' => 'array', 'GrantPermissions' => 'object', 'GrantPermissionGroups' => 'object', 'GrantRiskGroups' => 'object', 'EnableBotPasswords' => 'boolean', 'BotPasswordsCluster' => [ 'string', 'boolean', ], 'BotPasswordsDatabase' => [ 'string', 'boolean', ], 'BotPasswordsLimit' => 'integer', 'ReauthenticateForActions' => 'object', 'CSPHeader' => [ 'boolean', 'object', ], 'CSPReportOnlyHeader' => [ 'boolean', 'object', ], 'CSPUseReportURIDirective' => [ 'boolean', 'object', ], 'CSPFalsePositiveUrls' => 'object', 'AllowCrossOrigin' => 'boolean', 'RestAllowCrossOriginCookieAuth' => 'boolean', 'CookieSameSite' => [ 'string', 'null', ], 'CacheVaryCookies' => 'array', 'TrxProfilerLimits' => 'object', 'DebugLogGroups' => 'object', 'MWLoggerDefaultSpi' => 'object', 'Profiler' => 'object', 'StatsTarget' => [ 'string', 'null', ], 'StatsFormat' => [ 'string', 'null', ], 'StatsPrefix' => 'string', 'OpenTelemetryConfig' => [ 'object', 'null', ], 'OpenSearchTemplates' => 'object', 'NamespacesToBeSearchedDefault' => 'object', 'SitemapNamespaces' => [ 'boolean', 'array', ], 'SitemapNamespacesPriorities' => [ 'boolean', 'object', ], 'SitemapApiConfig' => 'object', 'SpecialSearchFormOptions' => 'object', 'SearchMatchRedirectPreference' => 'boolean', 'SearchRunSuggestedQuery' => 'boolean', 'PreviewOnOpenNamespaces' => 'object', 'ReadOnlyWatchedItemStore' => 'boolean', 'GitRepositoryViewers' => 'object', 'InstallerInitialPages' => 'array', 'RCLinkLimits' => 'array', 'RCLinkDays' => 'array', 'RCFeeds' => 'object', 'OverrideSiteFeed' => 'object', 'FeedClasses' => 'object', 'AdvertisedFeedTypes' => 'array', 'SoftwareTags' => 'object', 'RestrictedTagViewRights' => 'object', 'RecentChangesFlags' => 'object', 'WatchlistExpiry' => 'boolean', 'EnableWatchstarPopover' => 'boolean', 'EnableWatchlistLabels' => 'boolean', 'WatchlistLabelsMaxPerUser' => 'integer', 'WatchlistPurgeRate' => 'number', 'WatchlistExpiryMaxDuration' => [ 'string', 'null', ], 'EnableChangesListQueryPartitioning' => 'boolean', 'ImportSources' => 'object', 'ExtensionFunctions' => 'array', 'ExtensionMessagesFiles' => 'object', 'MessagesDirs' => 'object', 'TranslationAliasesDirs' => 'object', 'ExtensionEntryPointListFiles' => 'object', 'ValidSkinNames' => 'object', 'SpecialPages' => 'object', 'ExtensionCredits' => 'object', 'Hooks' => 'object', 'ServiceWiringFiles' => 'array', 'JobClasses' => 'object', 'JobTypesExcludedFromDefaultQueue' => 'array', 'JobBackoffThrottling' => 'object', 'JobTypeConf' => 'object', 'SpecialPageCacheUpdates' => 'object', 'PagePropLinkInvalidations' => 'object', 'TempCategoryCollations' => 'array', 'SortedCategories' => 'boolean', 'TrackingCategories' => 'array', 'LogTypes' => 'array', 'LogRestrictions' => 'object', 'FilterLogTypes' => 'object', 'LogNames' => 'object', 'LogHeaders' => 'object', 'LogActions' => 'object', 'LogActionsHandlers' => 'object', 'ActionFilteredLogs' => 'object', 'RangeContributionsCIDRLimit' => 'object', 'Actions' => 'object', 'NamespaceRobotPolicies' => 'object', 'ArticleRobotPolicies' => 'object', 'ExemptFromUserRobotsControl' => [ 'array', 'null', ], 'APIModules' => 'object', 'APIFormatModules' => 'object', 'APIMetaModules' => 'object', 'APIPropModules' => 'object', 'APIListModules' => 'object', 'APIUselessQueryPages' => 'array', 'CrossSiteAJAXdomains' => 'object', 'CrossSiteAJAXdomainExceptions' => 'object', 'AllowedCorsHeaders' => 'array', 'RestAPIAdditionalRouteFiles' => 'array', 'RestLocalModuleTestBaseUrl' => [ 'string', 'null', ], 'RestModuleOverrides' => 'object', 'RestExternalModules' => 'object', 'ShellRestrictionMethod' => [ 'string', 'boolean', ], 'ShellboxUrls' => 'object', 'ShellboxSecretKey' => [ 'string', 'null', ], 'ShellboxShell' => [ 'string', 'null', ], 'HTTPTimeout' => 'number', 'HTTPConnectTimeout' => 'number', 'HTTPMaxTimeout' => 'number', 'HTTPMaxConnectTimeout' => 'number', 'LocalVirtualHosts' => 'object', 'LocalHTTPProxy' => [ 'string', 'boolean', ], 'GenerateReqIDFormat' => 'string', 'VirtualRestConfig' => 'object', 'EventRelayerConfig' => 'object', 'Pingback' => 'boolean', 'OriginTrials' => 'array', 'ReportToExpiry' => 'integer', 'ReportToEndpoints' => 'array', 'FeaturePolicyReportOnly' => 'array', 'SkinsPreferred' => 'array', 'SpecialContributeSkinsEnabled' => 'array', 'SpecialContributeNewPageTarget' => [ 'string', 'null', ], 'EnableEditRecovery' => 'boolean', 'EditRecoveryExpiry' => 'integer', 'UseCodexSpecialBlock' => 'boolean', 'ShowLogoutConfirmation' => 'boolean', 'EnableProtectionIndicators' => 'boolean', 'OutputPipelineStages' => 'object', 'FeatureShutdown' => 'array', 'CloneArticleParserOutput' => 'boolean', 'UseLeximorph' => 'boolean', 'UsePostprocCacheLegacy' => 'boolean', 'UsePostprocCacheParsoid' => 'boolean', 'ParserOptionsLogUnsafeSampleRate' => 'integer', 'ReturnExperimentalPFragmentTypes' => 'array', 'UseParsoidLinksUpdate' => [ 'boolean', 'null', ], 'UseParsoidMessages' => [ 'boolean', 'null', ], ], 'mergeStrategy' => [ 'WebPThumbnailType' => 'replace', 'TiffThumbnailType' => 'replace', 'LBFactoryConf' => 'replace', 'InterwikiCache' => 'replace', 'PasswordPolicy' => 'array_replace_recursive', 'AuthManagerAutoConfig' => 'array_plus_2d', 'GroupPermissions' => 'array_plus_2d', 'RevokePermissions' => 'array_plus_2d', 'AddGroups' => 'array_merge_recursive', 'RemoveGroups' => 'array_merge_recursive', 'RateLimits' => 'array_plus_2d', 'GrantPermissions' => 'array_plus_2d', 'MWLoggerDefaultSpi' => 'replace', 'Profiler' => 'replace', 'Hooks' => 'array_merge_recursive', 'RestModuleOverrides' => 'array_replace_recursive', 'RestExternalModules' => 'array_replace_recursive', 'VirtualRestConfig' => 'array_plus_2d', ], 'dynamicDefault' => [ 'UsePathInfo' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultUsePathInfo', ], ], 'Script' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultScript', ], ], 'LoadScript' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLoadScript', ], ], 'RestPath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultRestPath', ], ], 'StylePath' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultStylePath', ], ], 'LocalStylePath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocalStylePath', ], ], 'ExtensionAssetsPath' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultExtensionAssetsPath', ], ], 'ArticlePath' => [ 'use' => [ 'Script', 'UsePathInfo', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultArticlePath', ], ], 'UploadPath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultUploadPath', ], ], 'FileCacheDirectory' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultFileCacheDirectory', ], ], 'Logo' => [ 'use' => [ 'ResourceBasePath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLogo', ], ], 'DeletedDirectory' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultDeletedDirectory', ], ], 'ShowEXIF' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultShowEXIF', ], ], 'SharedPrefix' => [ 'use' => [ 'DBprefix', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultSharedPrefix', ], ], 'SharedSchema' => [ 'use' => [ 'DBmwschema', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultSharedSchema', ], ], 'DBerrorLogTZ' => [ 'use' => [ 'Localtimezone', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultDBerrorLogTZ', ], ], 'Localtimezone' => [ 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocaltimezone', ], ], 'LocalTZoffset' => [ 'use' => [ 'Localtimezone', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultLocalTZoffset', ], ], 'ResourceBasePath' => [ 'use' => [ 'ScriptPath', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultResourceBasePath', ], ], 'MetaNamespace' => [ 'use' => [ 'Sitename', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultMetaNamespace', ], ], 'CookieSecure' => [ 'use' => [ 'ForceHTTPS', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultCookieSecure', ], ], 'CookiePrefix' => [ 'use' => [ 'SharedDB', 'SharedPrefix', 'SharedTables', 'DBname', 'DBprefix', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultCookiePrefix', ], ], 'ReadOnlyFile' => [ 'use' => [ 'UploadDirectory', ], 'callback' => [ 'MediaWiki\\MainConfigSchema', 'getDefaultReadOnlyFile', ], ], ], ], 'config-schema' => [ 'UploadStashScalerBaseUrl' => [ 'deprecated' => 'since 1.36 Use thumbProxyUrl in $wgLocalFileRepo', ], 'IllegalFileChars' => [ 'deprecated' => 'since 1.41; no longer customizable', ], 'ThumbnailNamespaces' => [ 'items' => [ 'type' => 'integer', ], ], 'LocalDatabases' => [ 'items' => [ 'type' => 'string', ], ], 'ParserCacheFilterConfig' => [ 'additionalProperties' => [ 'type' => 'object', 'description' => 'A map of namespace IDs to filter definitions.', 'additionalProperties' => [ 'type' => 'object', 'description' => 'A map of filter names to values.', 'properties' => [ 'minCpuTime' => [ 'type' => 'number', ], ], ], ], ], 'RawHtmlMessages' => [ 'items' => [ 'type' => 'string', ], ], 'InterwikiLogoOverride' => [ 'items' => [ 'type' => 'string', ], ], 'LegalTitleChars' => [ 'deprecated' => 'since 1.41; use Extension:TitleBlacklist to customize', ], 'ReauthenticateTime' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'ChangeCredentialsBlacklist' => [ 'items' => [ 'type' => 'string', ], ], 'RemoveCredentialsBlacklist' => [ 'items' => [ 'type' => 'string', ], ], 'GroupPermissions' => [ 'additionalProperties' => [ 'type' => 'object', 'additionalProperties' => [ 'type' => 'boolean', ], ], ], 'GroupInheritsPermissions' => [ 'additionalProperties' => [ 'type' => 'string', ], ], 'AvailableRights' => [ 'items' => [ 'type' => 'string', ], ], 'ImplicitRights' => [ 'items' => [ 'type' => 'string', ], ], 'SoftBlockRanges' => [ 'items' => [ 'type' => 'string', ], ], 'ExternalQuerySources' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'enabled' => [ 'type' => 'boolean', 'default' => false, ], 'url' => [ 'type' => 'string', 'format' => 'uri', ], 'timeout' => [ 'type' => 'integer', 'default' => 10, ], ], 'required' => [ 'enabled', 'url', ], 'additionalProperties' => false, ], ], 'GrantPermissions' => [ 'additionalProperties' => [ 'type' => 'object', 'additionalProperties' => [ 'type' => 'boolean', ], ], ], 'GrantPermissionGroups' => [ 'additionalProperties' => [ 'type' => 'string', ], ], 'SitemapNamespacesPriorities' => [ 'deprecated' => 'since 1.45 and ignored', ], 'SitemapApiConfig' => [ 'additionalProperties' => [ 'enabled' => [ 'type' => 'bool', ], 'sitemapsPerIndex' => [ 'type' => 'int', ], 'pagesPerSitemap' => [ 'type' => 'int', ], 'expiry' => [ 'type' => 'int', ], 'skipRedirects' => [ 'type' => 'bool', ], ], ], 'SoftwareTags' => [ 'additionalProperties' => [ 'type' => 'boolean', ], ], 'UseCopyrightUpload' => [ 'deprecated' => 'since 1.47 This feature is being removed.', ], 'JobBackoffThrottling' => [ 'additionalProperties' => [ 'type' => 'number', ], ], 'JobTypeConf' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'class' => [ 'type' => 'string', ], 'order' => [ 'type' => 'string', ], 'claimTTL' => [ 'type' => 'integer', ], ], ], ], 'TrackingCategories' => [ 'deprecated' => 'since 1.25 Extensions should now register tracking categories using the new extension registration system.', ], 'RangeContributionsCIDRLimit' => [ 'additionalProperties' => [ 'type' => 'integer', ], ], 'RestModuleOverrides' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'availability' => [ 'type' => 'string', ], ], 'required' => [ 'availability', ], ], ], 'RestExternalModules' => [ 'additionalProperties' => [ 'type' => 'object', 'properties' => [ 'info' => [ 'type' => 'object', 'properties' => [ 'version' => [ 'type' => 'string', ], 'title' => [ 'type' => 'string', ], 'x-i18n-title' => [ 'type' => 'string', ], 'description' => [ 'type' => 'string', ], 'x-i18n-description' => [ 'type' => 'string', ], ], 'required' => [ 'version', ], ], 'base' => [ 'type' => 'string', 'format' => 'uri', ], 'spec' => [ 'type' => 'string', 'format' => 'uri', ], ], 'required' => [ 'info', 'base', 'spec', ], ], ], 'ShellboxUrls' => [ 'additionalProperties' => [ 'type' => [ 'string', 'boolean', 'null', ], ], ], ], 'obsolete-config' => [ 'MangleFlashPolicy' => 'Since 1.39; no longer has any effect.', 'EnableOpenSearchSuggest' => 'Since 1.35, no longer used', 'AutoloadAttemptLowercase' => 'Since 1.40; no longer has any effect.', ],]
Interface for objects representing user identity.
element(SerializerNode $parent, SerializerNode $node, $contents)