53use Wikimedia\ScopedCallback;
97 private $reasonValidatorResult =
null;
129 protected function setRequest( array $data, $wasPosted =
null ) {
130 parent::setRequest( $data, $wasPosted );
131 $this->mLoadedRequest =
false;
137 private function loadRequestParameters() {
138 if ( $this->mLoadedRequest ) {
141 $this->mLoadedRequest =
true;
144 $this->mPosted = $request->wasPosted();
145 $this->mAction = $request->getRawVal(
'action' );
146 $this->mFromHTTP = $request->getBool(
'fromhttp',
false )
147 || $request->getBool(
'wpFromhttp',
false );
149 || ( !$this->mFromHTTP && $request->getProtocol() ===
'https' )
150 || $request->getBool(
'wpForceHttps',
false );
151 $this->mReturnTo = $request->getVal(
'returnto',
'' );
152 $this->mReturnToQuery = $request->getVal(
'returntoquery',
'' );
153 $this->mReturnToAnchor = $request->getVal(
'returntoanchor',
'' );
154 if ( $request->getVal(
'display' ) ===
'popup' ) {
155 $this->mDisplay =
'popup';
165 $this->loadRequestParameters();
166 if ( $this->mLoaded ) {
169 $this->mLoaded =
true;
172 $securityLevel = $this->
getRequest()->getText(
'force' );
183 $this->mToken = $request->getVal( $this->
getTokenName() );
186 $entryError = $this->
msg( $request->getVal(
'error',
'' ) );
187 $entryWarning = $this->
msg( $request->getVal(
'warning',
'' ) );
192 $this->
msg(
'loginreqlink' )->text(),
198 if ( $entryError->exists()
201 $this->mEntryErrorType =
'error';
202 $this->mEntryError = $entryError->rawParams( $loginreqlink )->parse();
204 } elseif ( $entryWarning->exists()
207 $this->mEntryErrorType =
'warning';
208 $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->parse();
211 # 1. When switching accounts, it sucks to get automatically logged out
212 # 2. Do not return to PasswordReset after a successful password change
213 # but goto Wiki start page (Main_Page) instead ( T35997 )
214 $returnToTitle = Title::newFromText( $this->mReturnTo );
215 if ( is_object( $returnToTitle )
216 && ( $returnToTitle->isSpecial(
'Userlogout' )
217 || $returnToTitle->isSpecial(
'PasswordReset' ) )
219 $this->mReturnTo =
'';
220 $this->mReturnToQuery =
'';
226 $params = parent::getPreservedParams( $options );
230 $this->loadRequestParameters();
232 'returnto' =>
'mReturnTo',
233 'returntoquery' =>
'mReturnToQuery',
234 'returntoanchor' =>
'mReturnToAnchor',
236 foreach ( $properties as $key => $prop ) {
237 $value = $this->$prop;
238 if ( $value !==
'' ) {
246 $params[
'fromhttp'] = $this->mFromHTTP ?
'1' :
null;
248 if ( $this->mDisplay !==
'page' ) {
252 return array_filter(
$params, fn ( $val ) => $val !==
null );
257 $this->loadRequestParameters();
258 return parent::beforeExecute(
$subPage );
266 if ( $this->mPosted ) {
267 $time = microtime(
true );
268 $profilingScope =
new ScopedCallback(
function () use ( $time ) {
269 $time = microtime(
true ) - $time;
271 $stats->getTiming(
'auth_specialpage_executeTiming_seconds' )
272 ->setLabel(
'action', $this->authAction )
273 ->copyToStatsdAt(
"timing.login.ui.{$this->authAction}" )
274 ->observe( $time * 1000 );
279 $session = SessionManager::getGlobalSession();
286 $this->
getOutput()->disableClientCache();
291 if ( $this->mDisplay ===
'popup' ) {
296 $this->
getContext()->setSkin( $skinFactory->makeSkin(
'authentication-popup' ) );
303 if ( !$this->
isSignup() && !$authManager->canAuthenticateNow() ) {
304 if ( !$session->canSetUser() ) {
305 throw new ErrorPageError(
'cannotloginnow-title',
'cannotloginnow-text', [
306 $session->getProvider()->describe( $this->getLanguage() )
309 throw new ErrorPageError(
'cannotlogin-title',
'cannotlogin-text' );
310 } elseif ( $this->
isSignup() && !$authManager->canCreateAccounts() ) {
311 throw new ErrorPageError(
'cannotcreateaccount-title',
'cannotcreateaccount-text' );
332 if ( !$this->
isSignup() && !$this->mPosted && !$this->securityLevel &&
333 ( $this->mReturnTo !==
'' || $this->mReturnToQuery !==
'' ) &&
341 if ( $this->
getRequest()->getProtocol() !==
'https' ) {
345 ( $this->mEntryErrorType ===
'error' ?
'error'
346 :
'warning' ) => $this->mEntryError,
354 $this->
getOutput()->addVaryHeader(
'X-Forwarded-Proto' );
361 if ( str_starts_with(
$url,
'https://' ) ) {
362 $this->mSecureLoginUrl =
$url;
371 $this->
mainLoginForm( [],
'authpage-cannot-' . $this->authAction );
375 if ( $this->canBypassForm( $button_name ) ) {
378 if ( $button_name ) {
379 $this->
getRequest()->setVal( $button_name,
true );
385 if ( !$status || !$status->isGood() ) {
386 $this->
mainLoginForm( $this->authRequests, $status ? $status->getMessage() :
'',
'error' );
391 $response = $status->getValue();
395 switch ( $response->status ) {
396 case AuthenticationResponse::PASS:
398 $this->proxyAccountCreation = $this->
isSignup() && $this->
getUser()->isNamed();
399 $this->targetUser = User::newFromName( $response->username );
402 !$this->proxyAccountCreation
403 && $response->loginRequest
404 && $authManager->canAuthenticateNow()
407 $response2 = $authManager->beginAuthentication( [ $response->loginRequest ],
409 if ( $response2->status !== AuthenticationResponse::PASS ) {
410 LoggerFactory::getInstance(
'login' )
411 ->error(
'Could not log in after account creation' );
412 $this->
successfulAction(
true, Status::newFatal(
'createacct-loginerror' ) );
417 if ( !$this->proxyAccountCreation ) {
418 $context = RequestContext::getMain();
420 if ( $context !== $localContext ) {
430 case AuthenticationResponse::FAIL:
432 case AuthenticationResponse::RESTART:
433 unset( $this->authForm );
434 if ( $response->status === AuthenticationResponse::FAIL ) {
436 $messageType =
'error';
439 $messageType =
'warning';
441 $this->
logAuthResult(
false, $response->message ? $response->message->getKey() :
'-' );
443 $this->
mainLoginForm( $this->authRequests, $response->message, $messageType );
445 case AuthenticationResponse::REDIRECT:
446 unset( $this->authForm );
447 $this->
getOutput()->redirect( $response->redirectTarget );
449 case AuthenticationResponse::UI:
450 unset( $this->authForm );
451 $this->authAction = $this->
isSignup() ? AuthManager::ACTION_CREATE_CONTINUE
452 : AuthManager::ACTION_LOGIN_CONTINUE;
453 $this->authRequests = $response->neededRequests;
454 $this->
mainLoginForm( $response->neededRequests, $response->message, $response->messageType );
457 throw new LogicException(
'invalid AuthenticationResponse' );
474 private function canBypassForm( &$button_name ) {
479 $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
480 foreach ( $fields as $fieldname => $field ) {
481 if ( !isset( $field[
'type'] ) ) {
484 if ( !empty( $field[
'skippable'] ) ) {
487 if ( $field[
'type'] ===
'button' ) {
488 if ( $button_name !==
null ) {
492 $button_name = $fieldname;
494 } elseif ( $field[
'type'] !==
'null' ) {
511 $type, $title, $msgname, $injected_html, $extraMessages
514 if ( is_string( $title ) ) {
515 wfDeprecated( __METHOD__ .
' with string title',
'1.41' );
516 $title = (
new RawMessage(
'$1' ) )->rawParams( $title );
518 $out->setPageTitleMsg( $title );
522 if ( $extraMessages ) {
523 $extraMessages = Status::wrap( $extraMessages );
524 $out->addWikiTextAsInterface(
525 $extraMessages->getWikiText(
false,
false, $this->getLanguage() )
529 $out->addHTML( $injected_html );
532 $helper->showReturnToPage( $type, $this->mReturnTo, $this->mReturnToQuery,
533 $this->mStickHTTPS, $this->mReturnToAnchor );
549 protected function mainLoginForm( array $requests, $msg =
'', $msgtype =
'error' ) {
557 $this->authForm =
null;
559 ->getAuthenticationRequests( $this->authAction, $user );
563 $out->addModuleStyles( [
564 'mediawiki.special.userlogin.common.styles'
568 $out->addModules(
'mediawiki.special.createaccount' );
569 $out->addModuleStyles( [
570 'mediawiki.special.userlogin.signup.styles'
574 $out->addModuleStyles( [
575 'mediawiki.special.userlogin.login.styles'
578 $out->disallowUserJs();
580 $form = $this->
getAuthForm( $requests, $this->authAction );
581 $form->prepareForm();
583 $submitStatus = Status::newGood();
584 if ( $msg && $msgtype ===
'warning' ) {
585 $submitStatus->warning( $msg );
586 } elseif ( $msg && $msgtype ===
'error' ) {
587 $submitStatus->fatal( $msg );
593 $this->
getUser()->isRegistered() &&
595 $this->authAction !== AuthManager::ACTION_LOGIN_CONTINUE
597 $reauthMessage = $this->securityLevel ?
'userlogin-reauth' :
'userlogin-loggedin';
598 $submitStatus->warning( $reauthMessage, $this->
getUser()->
getName() );
601 $formHtml = $form->getHTML( $submitStatus );
613 $loginPrompt = $this->
isSignup() ?
'' : Html::rawElement(
'div',
614 [
'id' =>
'userloginprompt' ], $this->
msg(
'loginprompt' )->parseAsBlock() );
617 $signupStartMsg = $this->
msg(
'signupstart' );
618 $signupStart = ( $this->
isSignup() && !$signupStartMsg->isDisabled() )
619 ? Html::rawElement(
'div', [
'id' =>
'signupstart' ], $signupStartMsg->parseAsBlock() ) :
'';
620 if ( $languageLinks ) {
621 $languageLinks = Html::rawElement(
'div', [
'id' =>
'languagelinks' ],
622 Html::rawElement(
'p', [], $languageLinks )
625 if ( $this->
getUser()->isTemp() ) {
630 $formBlock = Html::rawElement(
'div', [
'id' =>
'userloginForm' ], $formHtml );
631 $formAndBenefits = $formBlock;
633 $benefitsContainerHtml =
null;
639 'beforeForm' =>
false,
642 $benefitsContainerHtml, $info, $options
644 if ( $benefitsContainerHtml ===
null ) {
647 $formAndBenefits = $options[
'beforeForm']
648 ? ( $benefitsContainerHtml . $formBlock )
649 : ( $formBlock . $benefitsContainerHtml );
656 . Html::rawElement(
'div', [
'class' =>
'mw-ui-container' ],
669 $benefitsContainer =
'';
670 $this->
getOutput()->addModuleStyles( [
'oojs-ui.styles.icons-user' ] );
672 if ( !$this->
getUser()->isTemp() ) {
679 for ( $benefitIdx = 1; $benefitIdx <= $benefitCount; $benefitIdx++ ) {
680 $headUnescaped = $this->
msg(
"createacct-benefit-head$benefitIdx" )->text();
681 $iconClass = $this->
msg(
"createacct-benefit-icon$benefitIdx" )->text();
682 $benefitList .= Html::rawElement(
'div', [
'class' =>
"mw-number-text $iconClass" ],
683 Html::rawElement(
'span', [],
684 $this->
msg(
"createacct-benefit-head$benefitIdx" )->escaped()
686 . Html::rawElement(
'p', [],
687 $this->
msg(
"createacct-benefit-body$benefitIdx" )->params( $headUnescaped )->escaped()
691 $benefitsContainer = Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-container' ],
692 Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-heading' ],
693 $this->
msg(
'createacct-benefit-heading' )->escaped()
695 . Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-list' ], $benefitList )
701 'oojs-ui.styles.icons-moderation',
702 'oojs-ui.styles.icons-interactions',
707 'icon' =>
'oo-ui-icon-unStar',
708 'description' => $this->
msg(
"benefit-1-description" )->escaped()
711 'icon' =>
'oo-ui-icon-userContributions',
712 'description' => $this->
msg(
"benefit-2-description" )->escaped()
715 'icon' =>
'oo-ui-icon-settings',
716 'description' => $this->
msg(
"benefit-3-description" )->escaped()
719 foreach ( $benefits as $benefit ) {
720 $benefitContent = Html::rawElement(
'div', [
'class' =>
'mw-benefit-item' ],
721 Html::rawElement(
'span', [
'class' => $benefit[
'icon' ] ] )
722 . Html::rawElement(
'p', [], $benefit[
'description'] )
725 $benefitList .= Html::rawElement(
726 'div', [
'class' =>
'mw-benefit-item-wrapper' ], $benefitContent );
729 $benefitsListWrapper = Html::rawElement(
730 'div', [
'class' =>
'mw-benefit-list-wrapper' ], $benefitList );
732 $headingSubheadingWrapper = Html::rawElement(
'div', [
'class' =>
'mw-heading-subheading-wrapper' ],
733 Html::rawElement(
'h2', [], $this->
msg(
'createacct-benefit-heading-temp-user' )->escaped() )
734 . Html::rawElement(
'p', [
'class' =>
'mw-benefit-subheading' ], $this->
msg(
735 'createacct-benefit-subheading-temp-user' )->escaped() )
738 $benefitsContainer = Html::rawElement(
739 'div', [
'class' =>
'mw-createacct-benefits-container' ],
740 $headingSubheadingWrapper
741 . $benefitsListWrapper
745 return $benefitsContainer;
757 if ( isset( $this->authForm ) ) {
758 return $this->authForm;
761 $usingHTTPS = $this->
getRequest()->getProtocol() ===
'https';
764 $fieldInfo = AuthenticationRequest::mergeFieldInfo( $requests );
766 $formDescriptor = $this->fieldInfoToFormDescriptor( $requests, $fieldInfo, $this->authAction );
767 $this->postProcessFormDescriptor( $formDescriptor, $requests );
770 if ( $context->getRequest() !== $this->getRequest() ) {
775 $form = HTMLForm::factory(
'codex', $formDescriptor, $context );
777 $form->addHiddenField(
'authAction', $this->authAction );
778 $form->addHiddenField(
'force', $this->securityLevel );
779 $form->addHiddenField( $this->getTokenName(), $this->getToken()->toString() );
780 $config = $this->getConfig();
784 if ( !$this->isSignup() ) {
785 $form->addHiddenField(
'wpForceHttps', (
int)$this->mStickHTTPS );
786 $form->addHiddenField(
'wpFromhttp', $usingHTTPS );
790 $form->setAction( $this->getPageTitle()->getLocalURL( $this->getPreservedParams(
794 $form->setName(
'userlogin' . ( $this->isSignup() ?
'2' :
'' ) );
795 if ( $this->isSignup() ) {
796 $form->setId(
'userlogin2' );
799 $form->suppressDefaultSubmit();
801 $this->authForm = $form;
808 array $requests, array $fieldInfo, array &$formDescriptor, $action
810 $formDescriptor = self::mergeDefaultFormDescriptor( $fieldInfo, $formDescriptor,
811 $this->getFieldDefinitions( $fieldInfo ) );
821 return $this->authAction !== $this->getContinueAction( $this->authAction )
822 && !$this->securityLevel;
831 $isLoggedIn = $this->
getUser()->isRegistered();
832 $continuePart = $this->isContinued() ?
'continue-' :
'';
833 $anotherPart = $isLoggedIn ?
'another-' :
'';
835 $expiration = $this->
getRequest()->getSession()->getProvider()->getRememberUserDuration();
836 $expirationDays = ceil( $expiration / ( 3600 * 24 ) );
837 $secureLoginLink =
'';
838 if ( $this->mSecureLoginUrl ) {
840 'href' => $this->mSecureLoginUrl,
841 'class' =>
'mw-login-flush-right mw-secure',
842 ], $this->msg(
'userlogin-signwithsecure' )->text() );
844 $usernameHelpLink =
'';
845 if ( !$this->msg(
'createacct-helpusername' )->isDisabled() ) {
846 $usernameHelpLink = Html::rawElement(
'span', [
847 'class' =>
'mw-login-flush-right',
848 ], $this->msg(
'createacct-helpusername' )->parse() );
851 if ( $this->isSignup() ) {
852 $config = $this->getConfig();
853 $hideIf = isset( $fieldInfo[
'mailpassword'] ) ? [
'hide-if' => [
'===',
'mailpassword',
'1' ] ] : [];
854 $fieldDefinitions = [
856 'label-raw' => $this->msg(
'userlogin-yourname' )->escaped() . $usernameHelpLink,
858 'placeholder-message' => $isLoggedIn ?
'createacct-another-username-ph'
859 :
'userlogin-yourname-ph',
864 'label-message' =>
'createaccountmail',
865 'name' =>
'wpCreateaccountMail',
866 'id' =>
'wpCreateaccountMail',
869 'id' =>
'wpPassword2',
870 'autocomplete' =>
'new-password',
871 'placeholder-message' =>
'createacct-yourpassword-ph',
872 'help-message' =>
'createacct-useuniquepass',
876 'type' =>
'password',
877 'label-message' =>
'createacct-yourpasswordagain',
879 'cssclass' =>
'loginPassword',
881 'autocomplete' =>
'new-password',
882 'validation-callback' =>
function ( $value, $alldata ) {
883 if ( empty( $alldata[
'mailpassword'] ) && !empty( $alldata[
'password'] ) ) {
885 return $this->msg(
'htmlform-required' );
886 } elseif ( $value !== $alldata[
'password'] ) {
887 return $this->msg(
'badretype' );
892 'placeholder-message' =>
'createacct-yourpasswordagain-ph',
897 ?
'createacct-emailrequired' :
'createacct-emailoptional',
899 'cssclass' =>
'loginText',
902 'autocomplete' =>
'email',
905 'validation-callback' =>
function ( $value, $alldata ) {
913 return $this->msg(
'noemailtitle' );
914 } elseif ( !$value && !empty( $alldata[
'mailpassword'] ) ) {
916 return $this->msg(
'noemailcreate' );
917 } elseif ( $value && !Sanitizer::validateEmail( $value ) ) {
918 return $this->msg(
'invalidemailaddress' );
919 } elseif ( is_string( $value ) && strlen( $value ) > 255 ) {
920 return $this->msg(
'changeemail-maxlength' );
927 'placeholder-message' =>
'createacct-' . $anotherPart .
'email-ph',
931 'help-message' => $isLoggedIn ?
'createacct-another-realname-tip'
932 :
'prefs-help-realname',
933 'label-message' =>
'createacct-realname',
934 'cssclass' =>
'loginText',
936 'placeholder-message' =>
'createacct-realname',
937 'id' =>
'wpRealName',
938 'autocomplete' =>
'name',
943 'label-message' =>
'createacct-reason',
944 'cssclass' =>
'loginText',
947 'validation-callback' =>
function ( $value, $alldata ) {
950 if ( $value && Sanitizer::validateEmail( $value ) ) {
951 if ( $this->reasonValidatorResult !==
null ) {
952 return $this->reasonValidatorResult;
954 $this->reasonValidatorResult =
true;
956 if ( !$authManager->getAuthenticationSessionData(
'reason-retry',
false ) ) {
957 $authManager->setAuthenticationSessionData(
'reason-retry',
true );
958 $this->reasonValidatorResult = $this->msg(
'createacct-reason-confirm' );
960 return $this->reasonValidatorResult;
964 'placeholder-message' =>
'createacct-reason-ph',
974 'default' => $this->msg(
'createacct-' . $anotherPart . $continuePart .
976 'name' =>
'wpCreateaccount',
977 'id' =>
'wpCreateaccount',
981 if ( !$this->msg(
'createacct-username-help' )->isDisabled() ) {
982 $fieldDefinitions[
'username'][
'help-message'] =
'createacct-username-help';
988 $passwordRequest = AuthenticationRequest::getRequestByClass( $this->authRequests,
989 PasswordAuthenticationRequest::class );
990 $changePassword = $passwordRequest && $passwordRequest->action == AuthManager::ACTION_CHANGE;
991 $fieldDefinitions = [
994 'label-raw' => $this->msg(
'userlogin-yourname' )->escaped() . $secureLoginLink,
996 'placeholder-message' =>
'userlogin-yourname-ph',
997 ] + ( $changePassword ? [
1000 'baseField' =>
'password',
1003 'cssclass' =>
'mw-htmlform-hidden-field',
1008 'autocomplete' =>
'new-password',
1009 'placeholder-message' =>
'createacct-yourpassword-ph',
1010 'help-message' =>
'createacct-useuniquepass',
1012 'id' =>
'wpPassword1',
1013 'autocomplete' =>
'current-password',
1014 'placeholder-message' =>
'userlogin-yourpassword-ph',
1018 'type' =>
'password',
1019 'autocomplete' =>
'new-password',
1020 'placeholder-message' =>
'createacct-yourpasswordagain-ph',
1026 'cssclass' =>
'mw-userlogin-rememberme',
1027 'name' =>
'wpRemember',
1028 'label-message' => $this->msg(
'userlogin-remembermypassword' )
1029 ->numParams( $expirationDays ),
1030 'id' =>
'wpRemember',
1038 'default' => $this->msg(
'pt-login-' . $continuePart .
'button' )->text(),
1039 'id' =>
'wpLoginAttempt',
1042 'linkcontainer' => [
1045 'cssclass' =>
'mw-form-related-link-container mw-userlogin-help',
1050 ->inContentLanguage()
1052 ], $this->msg(
'userlogin-helplink2' )->text() ),
1063 $fieldDefinitions[
'username'] += [
1066 'cssclass' =>
'loginText mw-userlogin-username',
1068 'autocomplete' =>
'username',
1071 $fieldDefinitions[
'password'] += [
1072 'type' =>
'password',
1074 'name' =>
'wpPassword',
1075 'cssclass' =>
'loginPassword mw-userlogin-password',
1080 if ( $this->mEntryError ) {
1082 if ( $this->mEntryErrorType ===
'error' ) {
1083 $defaultHtml = Html::errorBox( $this->mEntryError );
1084 } elseif ( $this->mEntryErrorType ===
'warning' ) {
1085 $defaultHtml = Html::warningBox( $this->mEntryError );
1087 $fieldDefinitions[
'entryError'] = [
1089 'default' => $defaultHtml,
1095 if ( !$this->showExtraInformation() ) {
1096 unset( $fieldDefinitions[
'linkcontainer'], $fieldDefinitions[
'signupend'] );
1098 if ( $this->isSignup() && $this->showExtraInformation() ) {
1101 $signupendMsg = $this->msg(
'signupend' );
1102 $signupendHttpsMsg = $this->msg(
'signupend-https' );
1103 if ( !$signupendMsg->isDisabled() ) {
1104 $usingHTTPS = $this->
getRequest()->getProtocol() ===
'https';
1105 $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
1106 ? $signupendHttpsMsg->parse() : $signupendMsg->parse();
1107 $fieldDefinitions[
'signupend'] = [
1110 'default' => Html::rawElement(
'div', [
'id' =>
'signupend' ], $signupendText ),
1115 if ( !$this->isSignup() && $this->showExtraInformation() ) {
1117 if ( $passwordReset->isAllowed( $this->getUser() )->isGood() ) {
1118 $fieldDefinitions[
'passwordReset'] = [
1121 'cssclass' =>
'mw-form-related-link-container',
1122 'default' => $this->getLinkRenderer()->makeLink(
1124 $this->msg(
'userlogin-resetpassword-link' )->text()
1131 if ( $this->showCreateAccountLink() ) {
1133 $linkTitle = $this->getTitleFor( $this->isSignup() ?
'Userlogin' :
'CreateAccount' );
1134 $linkq =
wfArrayToCgi( $this->getPreservedParams( [
'reset' =>
true ] ) );
1135 $isLoggedIn = $this->
getUser()->isRegistered()
1136 && !$this->
getUser()->isTemp();
1138 $fieldDefinitions[
'createOrLogin'] = [
1141 'linkQuery' => $linkq,
1142 'default' =>
function (
$params ) use ( $isLoggedIn, $linkTitle ) {
1143 $buttonClasses =
'cdx-button cdx-button--action-progressive '
1144 .
'cdx-button--fake-button cdx-button--fake-button--enabled';
1146 return Html::rawElement(
'div',
1147 [
'id' =>
'mw-createaccount' . ( !$isLoggedIn ?
'-cta' :
'' ),
1148 'class' => ( $isLoggedIn ?
'mw-form-related-link-container' :
'mw-ui-vform-field' ) ],
1149 ( $isLoggedIn ?
'' : $this->msg(
'userlogin-noaccount' )->escaped() )
1152 'id' =>
'mw-createaccount-join' . ( $isLoggedIn ?
'-loggedin' :
'' ),
1153 'href' => $linkTitle->getLocalURL(
$params[
'linkQuery'] ),
1154 'class' => [
'mw-authentication-popup-link', $buttonClasses => !$isLoggedIn ],
1155 'target' =>
'_self',
1159 $isLoggedIn ?
'userlogin-createanother' :
'userlogin-joinproject'
1169 return $fieldDefinitions;
1195 private function showCreateAccountLink() {
1196 return $this->isSignup() ||
1197 $this->
getContext()->getAuthority()->isAllowed(
'createaccount' );
1201 return $this->isSignup() ?
'wpCreateaccountToken' :
'wpLoginToken';
1211 $msg = $this->msg(
'loginlanguagelinks' )->inContentLanguage();
1212 if ( $msg->isBlank() ) {
1215 $langs = explode(
"\n", $msg->text() );
1217 foreach ( $langs as $lang ) {
1218 $lang = trim( $lang,
'* ' );
1219 $parts = explode(
'|', $lang );
1220 if ( count( $parts ) >= 2 ) {
1221 $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
1225 return count( $links ) > 0 ? $this->msg(
'loginlanguagelabel' )->rawParams(
1226 $this->getLanguage()->pipeList( $links ) )->escaped() :
'';
1238 if ( $this->getLanguage()->getCode() == $lang ) {
1240 return htmlspecialchars( $text );
1242 $query = $this->getPreservedParams();
1243 $query[
'uselang'] = $lang;
1247 ->getLanguage( $lang );
1248 $attr[
'lang'] = $attr[
'hreflang'] = $targetLanguage->getHtmlCode();
1249 $attr[
'class'] =
'mw-authentication-popup-link';
1251 return $this->getLinkRenderer()->makeKnownLink(
1252 $this->getPageTitle(),
1270 isset( $formDescriptor[
'username'] ) &&
1271 !isset( $formDescriptor[
'username'][
'default'] ) &&
1275 if ( $user->isRegistered() && !$user->isTemp() ) {
1276 $formDescriptor[
'username'][
'default'] = $user->getName();
1278 $formDescriptor[
'username'][
'default'] =
1279 $this->
getRequest()->getSession()->suggestLoginUsername();
1285 if ( !$this->needsSubmitButton( $requests ) ) {
1286 unset( $formDescriptor[
'createaccount'], $formDescriptor[
'loginattempt'] );
1289 if ( !$this->isSignup() ) {
1293 isset( $formDescriptor[
'username'] )
1294 && empty( $formDescriptor[
'username'][
'default'] )
1295 && !$this->
getRequest()->getCheck(
'wpName' )
1297 $formDescriptor[
'username'][
'autofocus'] =
true;
1298 } elseif ( isset( $formDescriptor[
'password'] ) ) {
1299 $formDescriptor[
'password'][
'autofocus'] =
true;
1303 $this->addTabIndex( $formDescriptor );
1312 $noticeContent = $this->msg(
'createacct-temp-warning', $this->
getUser()->getName() )->parse();
1313 return Html::noticeBox(
1317 'mw-userLogin-icon--user-temporary'
1324class_alias( LoginSignupSpecialPage::class,
'LoginSignupSpecialPage' );
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....
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
global $wgInitialSessionId
array $params
The job parameters.
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.
Helper functions for the login form that need to be shared with other special pages (such as CentralA...
static getValidErrorMessages()
Returns an array of all valid error messages.
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.
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 EmailConfirmToEdit
Name constant for the EmailConfirmToEdit setting, for use with Config::get()
const SecureLogin
Name constant for the SecureLogin setting, for use with Config::get()
A special page subclass for authentication-related special pages.
string $subPage
Subpage of the special page.
getToken()
Returns the CSRF token.
getContinueAction( $action)
Gets the _CONTINUE version of an action.
isContinued()
Returns true if this is not the first step of the authentication.
isActionAllowed( $action)
Checks whether AuthManager is ready to perform the action.
trySubmit()
Attempts to do an authentication step with the submitted data.
loadAuth( $subPage, $authAction=null, $reset=false)
Load or initialize $authAction, $authRequests and $subPage.
getDefaultAction( $subPage)
Get the default action for this special page if none is given via URL/POST data.
getRequest()
Get the WebRequest being used for this instance.
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.
logAuthResult( $success, $status=null)
Logs to the authmanager-stats channel.
postProcessFormDescriptor(&$formDescriptor, $requests)
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.
showSuccessPage( $type, $title, $msgname, $injected_html, $extraMessages)
Show the success page.
getAuthForm(array $requests, $action)
Generates a form from the given request.
getTokenName()
Returns the name of the CSRF token (under which it should be found in the POST or GET data).
getBenefitsContainerHtml()
The HTML to be shown in the "benefits to signing in / creating an account" section of the signup/logi...
mainLoginForm(array $requests, $msg='', $msgtype='error')
getPreservedParams( $options=[])
Returns URL query parameters which should be preserved between authentication requests....
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 ...
getFieldDefinitions(array $fieldInfo)
Create a HTMLForm descriptor for the core login fields.
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.
hasSessionCookie()
Check if a session cookie is present.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
getPageHtml( $formHtml)
Add page elements which are outside the form.
User $targetUser
FIXME another flag for passing data.
load( $subPage)
Load data from request.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
static getTitleFor( $name, $subpage=false, $fragment='')
Get a localised Title object for a specified special page name If you don't need a full Title object,...
getUser()
Shortcut to get the User executing this instance.
getPageTitle( $subpage=false)
Get a self-referential title object.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
getConfig()
Shortcut to get main config object.
getContext()
Gets the context this SpecialPage is executed in.
setContext( $context)
Sets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getOutput()
Get the OutputPage being used for this instance.
getName()
Get the canonical, unlocalized name of this special page without namespace.
getFullTitle()
Return the full title, including $par.
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...
The base class for all skins.
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
Generic operation result class Has warning/error list, boolean status and arbitrary value.