55use Wikimedia\ScopedCallback;
78 private $reasonValidatorResult =
null;
110 protected function setRequest( array $data, $wasPosted =
null ) {
111 parent::setRequest( $data, $wasPosted );
112 $this->mLoadedRequest =
false;
118 private function loadRequestParameters() {
119 if ( $this->mLoadedRequest ) {
122 $this->mLoadedRequest =
true;
125 $this->mPosted = $request->wasPosted();
126 $this->mAction = $request->getRawVal(
'action' );
127 $this->mFromHTTP = $request->getBool(
'fromhttp',
false )
128 || $request->getBool(
'wpFromhttp',
false );
130 || ( !$this->mFromHTTP && $request->getProtocol() ===
'https' )
131 || $request->getBool(
'wpForceHttps',
false );
132 $this->mLanguage = $request->getText(
'uselang' );
133 $this->mVariant = $request->getText(
'variant' );
134 $this->mReturnTo = $request->getVal(
'returnto',
'' );
135 $this->mReturnToQuery = $request->getVal(
'returntoquery',
'' );
144 $this->loadRequestParameters();
145 if ( $this->mLoaded ) {
148 $this->mLoaded =
true;
151 $securityLevel = $this->
getRequest()->getText(
'force' );
162 $this->mToken = $request->getVal( $this->
getTokenName() );
165 $entryError = $this->
msg( $request->getVal(
'error',
'' ) );
166 $entryWarning = $this->
msg( $request->getVal(
'warning',
'' ) );
171 $this->
msg(
'loginreqlink' )->text(),
174 'returnto' => $this->mReturnTo,
175 'returntoquery' => $this->mReturnToQuery,
176 'uselang' => $this->mLanguage ?:
null,
177 'variant' => $this->mVariant ?:
null,
179 $this->mFromHTTP ?
'1' :
null,
184 if ( $entryError->exists()
187 $this->mEntryErrorType =
'error';
188 $this->mEntryError = $entryError->rawParams( $loginreqlink )->parse();
190 } elseif ( $entryWarning->exists()
193 $this->mEntryErrorType =
'warning';
194 $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->parse();
197 # 1. When switching accounts, it sucks to get automatically logged out
198 # 2. Do not return to PasswordReset after a successful password change
199 # but goto Wiki start page (Main_Page) instead ( T35997 )
200 $returnToTitle = Title::newFromText( $this->mReturnTo );
201 if ( is_object( $returnToTitle )
202 && ( $returnToTitle->isSpecial(
'Userlogout' )
203 || $returnToTitle->isSpecial(
'PasswordReset' ) )
205 $this->mReturnTo =
'';
206 $this->mReturnToQuery =
'';
211 $params = parent::getPreservedParams( $withToken );
213 'returnto' => $this->mReturnTo ?:
null,
214 'returntoquery' => $this->mReturnToQuery ?:
null,
217 $params[
'fromhttp'] = $this->mFromHTTP ?
'1' :
null;
224 $this->loadRequestParameters();
225 return parent::beforeExecute(
$subPage );
233 if ( $this->mPosted ) {
234 $time = microtime(
true );
235 $profilingScope =
new ScopedCallback(
function () use ( $time ) {
236 $time = microtime(
true ) - $time;
238 $statsd->timing(
"timing.login.ui.{$this->authAction}", $time * 1000 );
243 $session = SessionManager::getGlobalSession();
250 $this->
getOutput()->disableClientCache();
257 if ( !$this->
isSignup() && !$authManager->canAuthenticateNow() ) {
258 if ( !$session->canSetUser() ) {
259 throw new ErrorPageError(
'cannotloginnow-title',
'cannotloginnow-text', [
260 $session->getProvider()->describe( $this->getLanguage() )
263 throw new ErrorPageError(
'cannotlogin-title',
'cannotlogin-text' );
264 } elseif ( $this->
isSignup() && !$authManager->canCreateAccounts() ) {
265 throw new ErrorPageError(
'cannotcreateaccount-title',
'cannotcreateaccount-text' );
286 if ( !$this->
isSignup() && !$this->mPosted && !$this->securityLevel &&
287 ( $this->mReturnTo !==
'' || $this->mReturnToQuery !==
'' ) &&
295 if ( $this->
getRequest()->getProtocol() !==
'https' ) {
299 ( $this->mEntryErrorType ===
'error' ?
'error'
300 :
'warning' ) => $this->mEntryError,
302 $url = $title->getFullURL( $query,
false,
PROTO_HTTPS );
308 $this->
getOutput()->addVaryHeader(
'X-Forwarded-Proto' );
315 if ( str_starts_with( $url,
'https://' ) ) {
316 $this->mSecureLoginUrl = $url;
325 $this->
mainLoginForm( [],
'authpage-cannot-' . $this->authAction );
329 if ( $this->canBypassForm( $button_name ) ) {
332 if ( $button_name ) {
333 $this->
getRequest()->setVal( $button_name,
true );
339 if ( !$status || !$status->isGood() ) {
340 $this->
mainLoginForm( $this->authRequests, $status ? $status->getMessage() :
'',
'error' );
345 $response = $status->getValue();
349 switch ( $response->status ) {
350 case AuthenticationResponse::PASS:
352 $this->proxyAccountCreation = $this->
isSignup() && $this->
getUser()->isNamed();
353 $this->targetUser = User::newFromName( $response->username );
356 !$this->proxyAccountCreation
357 && $response->loginRequest
358 && $authManager->canAuthenticateNow()
361 $response2 = $authManager->beginAuthentication( [ $response->loginRequest ],
363 if ( $response2->status !== AuthenticationResponse::PASS ) {
364 LoggerFactory::getInstance(
'login' )
365 ->error(
'Could not log in after account creation' );
366 $this->
successfulAction(
true, Status::newFatal(
'createacct-loginerror' ) );
371 if ( !$this->proxyAccountCreation ) {
378 case AuthenticationResponse::FAIL:
380 case AuthenticationResponse::RESTART:
381 unset( $this->authForm );
382 if ( $response->status === AuthenticationResponse::FAIL ) {
384 $messageType =
'error';
387 $messageType =
'warning';
389 $this->
logAuthResult(
false, $response->message ? $response->message->getKey() :
'-' );
391 $this->
mainLoginForm( $this->authRequests, $response->message, $messageType );
393 case AuthenticationResponse::REDIRECT:
394 unset( $this->authForm );
395 $this->
getOutput()->redirect( $response->redirectTarget );
397 case AuthenticationResponse::UI:
398 unset( $this->authForm );
399 $this->authAction = $this->
isSignup() ? AuthManager::ACTION_CREATE_CONTINUE
400 : AuthManager::ACTION_LOGIN_CONTINUE;
401 $this->authRequests = $response->neededRequests;
402 $this->
mainLoginForm( $response->neededRequests, $response->message, $response->messageType );
405 throw new LogicException(
'invalid AuthenticationResponse' );
422 private function canBypassForm( &$button_name ) {
427 $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
428 foreach ( $fields as $fieldname => $field ) {
429 if ( !isset( $field[
'type'] ) ) {
432 if ( !empty( $field[
'skippable'] ) ) {
435 if ( $field[
'type'] ===
'button' ) {
436 if ( $button_name !==
null ) {
440 $button_name = $fieldname;
442 } elseif ( $field[
'type'] !==
'null' ) {
459 $type, $title, $msgname, $injected_html, $extraMessages
462 if ( is_string( $title ) ) {
463 wfDeprecated( __METHOD__ .
' with string title',
'1.41' );
464 $title = (
new RawMessage(
'$1' ) )->rawParams( $title );
466 $out->setPageTitleMsg( $title );
470 if ( $extraMessages ) {
471 $extraMessages = Status::wrap( $extraMessages );
472 $out->addWikiTextAsInterface(
473 $extraMessages->getWikiText(
false,
false, $this->getLanguage() )
477 $out->addHTML( $injected_html );
480 $helper->showReturnToPage( $type, $this->mReturnTo, $this->mReturnToQuery, $this->mStickHTTPS );
499 $type, $returnTo =
'', $returnToQuery =
'', $stickHTTPS =
false
502 $helper->showReturnToPage( $type, $returnTo, $returnToQuery, $stickHTTPS );
512 $context = RequestContext::getMain();
514 if ( $context !== $localContext ) {
519 $user = $context->getRequest()->getSession()->getUser();
521 StubGlobalUser::setUser( $user );
522 $context->setUser( $user );
524 $wgLang = $context->getLanguage();
541 protected function mainLoginForm( array $requests, $msg =
'', $msgtype =
'error' ) {
549 $this->authForm =
null;
551 ->getAuthenticationRequests( $this->authAction, $user );
555 $out->addModuleStyles( [
556 'mediawiki.special.userlogin.common.styles'
560 $out->addJsConfigVars(
'wgCreateacctImgcaptchaHelp',
561 $this->
msg(
'createacct-imgcaptcha-help' )->parse() );
564 $out->addModules(
'mediawiki.special.createaccount' );
565 $out->addModuleStyles( [
566 'mediawiki.special.userlogin.signup.styles'
570 $out->addModuleStyles( [
571 'mediawiki.special.userlogin.login.styles'
574 $out->disallowUserJs();
576 $form = $this->
getAuthForm( $requests, $this->authAction );
577 $form->prepareForm();
579 $submitStatus = Status::newGood();
580 if ( $msg && $msgtype ===
'warning' ) {
581 $submitStatus->warning( $msg );
582 } elseif ( $msg && $msgtype ===
'error' ) {
583 $submitStatus->fatal( $msg );
589 $this->
getUser()->isRegistered() &&
591 $this->authAction !== AuthManager::ACTION_LOGIN_CONTINUE
593 $reauthMessage = $this->securityLevel ?
'userlogin-reauth' :
'userlogin-loggedin';
594 $submitStatus->warning( $reauthMessage, $this->
getUser()->
getName() );
597 $formHtml = $form->getHTML( $submitStatus );
609 $loginPrompt = $this->
isSignup() ?
'' : Html::rawElement(
'div',
610 [
'id' =>
'userloginprompt' ], $this->
msg(
'loginprompt' )->parseAsBlock() );
613 $signupStartMsg = $this->
msg(
'signupstart' );
614 $signupStart = ( $this->
isSignup() && !$signupStartMsg->isDisabled() )
615 ? Html::rawElement(
'div', [
'id' =>
'signupstart' ], $signupStartMsg->parseAsBlock() ) :
'';
616 if ( $languageLinks ) {
617 $languageLinks = Html::rawElement(
'div', [
'id' =>
'languagelinks' ],
618 Html::rawElement(
'p', [], $languageLinks )
621 if ( $this->
getUser()->isTemp() ) {
626 $formBlock = Html::rawElement(
'div', [
'id' =>
'userloginForm' ], $formHtml );
627 $formAndBenefits = $formBlock;
629 $benefitsContainerHtml =
null;
635 'beforeForm' =>
false,
638 $benefitsContainerHtml, $info, $options
640 if ( $benefitsContainerHtml ===
null ) {
643 $formAndBenefits = $options[
'beforeForm']
644 ? ( $benefitsContainerHtml . $formBlock )
645 : ( $formBlock . $benefitsContainerHtml );
648 return Html::rawElement(
'div', [
'class' =>
'mw-ui-container' ],
665 $benefitsContainer =
'';
666 $this->
getOutput()->addModuleStyles( [
'oojs-ui.styles.icons-user' ] );
668 if ( !$this->
getUser()->isTemp() ) {
675 for ( $benefitIdx = 1; $benefitIdx <= $benefitCount; $benefitIdx++ ) {
676 $headUnescaped = $this->
msg(
"createacct-benefit-head$benefitIdx" )->text();
677 $iconClass = $this->
msg(
"createacct-benefit-icon$benefitIdx" )->text();
678 $benefitList .= Html::rawElement(
'div', [
'class' =>
"mw-number-text $iconClass" ],
679 Html::rawElement(
'h3', [],
680 $this->
msg(
"createacct-benefit-head$benefitIdx" )->escaped()
682 . Html::rawElement(
'p', [],
683 $this->
msg(
"createacct-benefit-body$benefitIdx" )->params( $headUnescaped )->escaped()
687 $benefitsContainer = Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-container' ],
688 Html::rawElement(
'h2', [], $this->
msg(
'createacct-benefit-heading' )->escaped() )
689 . Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-list' ], $benefitList )
695 'oojs-ui.styles.icons-moderation',
696 'oojs-ui.styles.icons-interactions',
701 'icon' =>
'oo-ui-icon-unStar',
702 'description' => $this->
msg(
"benefit-1-description" )->escaped()
705 'icon' =>
'oo-ui-icon-userContributions',
706 'description' => $this->
msg(
"benefit-2-description" )->escaped()
709 'icon' =>
'oo-ui-icon-settings',
710 'description' => $this->
msg(
"benefit-3-description" )->escaped()
713 foreach ( $benefits as $benefit ) {
714 $benefitContent = Html::rawElement(
'div', [
'class' =>
'mw-benefit-item' ],
715 Html::rawElement(
'span', [
'class' => $benefit[
'icon' ] ] )
716 . Html::rawElement(
'p', [], $benefit[
'description'] )
719 $benefitList .= Html::rawElement(
720 'div', [
'class' =>
'mw-benefit-item-wrapper' ], $benefitContent );
723 $benefitsListWrapper = Html::rawElement(
724 'div', [
'class' =>
'mw-benefit-list-wrapper' ], $benefitList );
726 $headingSubheadingWrapper = Html::rawElement(
'div', [
'class' =>
'mw-heading-subheading-wrapper' ],
727 Html::rawElement(
'h2', [], $this->
msg(
'createacct-benefit-heading-temp-user' )->escaped() )
728 . Html::rawElement(
'p', [
'class' =>
'mw-benefit-subheading' ], $this->
msg(
729 'createacct-benefit-subheading-temp-user' )->escaped() )
732 $benefitsContainer = Html::rawElement(
733 'div', [
'class' =>
'mw-createacct-benefits-container' ],
734 $headingSubheadingWrapper
735 . $benefitsListWrapper
739 return $benefitsContainer;
751 if ( isset( $this->authForm ) ) {
752 return $this->authForm;
755 $usingHTTPS = $this->
getRequest()->getProtocol() ===
'https';
758 $fieldInfo = AuthenticationRequest::mergeFieldInfo( $requests );
760 $formDescriptor = $this->fieldInfoToFormDescriptor( $requests, $fieldInfo, $this->authAction );
761 $this->postProcessFormDescriptor( $formDescriptor, $requests );
764 if ( $context->getRequest() !== $this->getRequest() ) {
769 $form = HTMLForm::factory(
'codex', $formDescriptor, $context );
771 $form->addHiddenField(
'authAction', $this->authAction );
772 if ( $this->mLanguage ) {
773 $form->addHiddenField(
'uselang', $this->mLanguage );
775 if ( $this->mVariant ) {
776 $form->addHiddenField(
'variant', $this->mVariant );
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 );
791 $form->setAction( $this->getPageTitle()->getLocalURL( $this->getReturnToQueryStringFragment() ) );
792 $form->setName(
'userlogin' . ( $this->isSignup() ?
'2' :
'' ) );
793 if ( $this->isSignup() ) {
794 $form->setId(
'userlogin2' );
797 $form->suppressDefaultSubmit();
799 $this->authForm = $form;
806 array $requests, array $fieldInfo, array &$formDescriptor, $action
808 $formDescriptor = self::mergeDefaultFormDescriptor( $fieldInfo, $formDescriptor,
809 $this->getFieldDefinitions( $fieldInfo ) );
819 return $this->authAction !== $this->getContinueAction( $this->authAction )
820 && !$this->securityLevel;
829 $isLoggedIn = $this->
getUser()->isRegistered();
830 $continuePart = $this->isContinued() ?
'continue-' :
'';
831 $anotherPart = $isLoggedIn ?
'another-' :
'';
833 $expiration = $this->
getRequest()->getSession()->getProvider()->getRememberUserDuration();
834 $expirationDays = ceil( $expiration / ( 3600 * 24 ) );
835 $secureLoginLink =
'';
836 if ( $this->mSecureLoginUrl ) {
837 $secureLoginLink = Html::element(
'a', [
838 'href' => $this->mSecureLoginUrl,
839 'class' =>
'mw-login-flush-right mw-secure',
840 ], $this->msg(
'userlogin-signwithsecure' )->text() );
842 $usernameHelpLink =
'';
843 if ( !$this->msg(
'createacct-helpusername' )->isDisabled() ) {
844 $usernameHelpLink = Html::rawElement(
'span', [
845 'class' =>
'mw-login-flush-right',
846 ], $this->msg(
'createacct-helpusername' )->parse() );
849 if ( $this->isSignup() ) {
850 $config = $this->getConfig();
851 $hideIf = isset( $fieldInfo[
'mailpassword'] ) ? [
'hide-if' => [
'===',
'mailpassword',
'1' ] ] : [];
852 $fieldDefinitions = [
858 'default' => Html::element(
'div', [
'id' =>
'mw-createacct-status-area' ] ),
862 'label-raw' => $this->msg(
'userlogin-yourname' )->escaped() . $usernameHelpLink,
864 'placeholder-message' => $isLoggedIn ?
'createacct-another-username-ph'
865 :
'userlogin-yourname-ph',
870 'label-message' =>
'createaccountmail',
871 'name' =>
'wpCreateaccountMail',
872 'id' =>
'wpCreateaccountMail',
875 'id' =>
'wpPassword2',
876 'autocomplete' =>
'new-password',
877 'placeholder-message' =>
'createacct-yourpassword-ph',
878 'help-message' =>
'createacct-useuniquepass',
882 'type' =>
'password',
883 'label-message' =>
'createacct-yourpasswordagain',
885 'cssclass' =>
'loginPassword',
887 'autocomplete' =>
'new-password',
888 'validation-callback' =>
function ( $value, $alldata ) {
889 if ( empty( $alldata[
'mailpassword'] ) && !empty( $alldata[
'password'] ) ) {
891 return $this->msg(
'htmlform-required' );
892 } elseif ( $value !== $alldata[
'password'] ) {
893 return $this->msg(
'badretype' );
898 'placeholder-message' =>
'createacct-yourpasswordagain-ph',
903 ?
'createacct-emailrequired' :
'createacct-emailoptional',
905 'cssclass' =>
'loginText',
908 'autocomplete' =>
'email',
911 'validation-callback' =>
function ( $value, $alldata ) {
919 return $this->msg(
'noemailtitle' );
920 } elseif ( !$value && !empty( $alldata[
'mailpassword'] ) ) {
922 return $this->msg(
'noemailcreate' );
924 return $this->msg(
'invalidemailaddress' );
925 } elseif ( is_string( $value ) && strlen( $value ) > 255 ) {
926 return $this->msg(
'changeemail-maxlength' );
933 'placeholder-message' =>
'createacct-' . $anotherPart .
'email-ph',
937 'help-message' => $isLoggedIn ?
'createacct-another-realname-tip'
938 :
'prefs-help-realname',
939 'label-message' =>
'createacct-realname',
940 'cssclass' =>
'loginText',
942 'placeholder-message' =>
'createacct-realname',
943 'id' =>
'wpRealName',
944 'autocomplete' =>
'name',
949 'label-message' =>
'createacct-reason',
950 'cssclass' =>
'loginText',
953 'validation-callback' =>
function ( $value, $alldata ) {
957 if ( $this->reasonValidatorResult !==
null ) {
958 return $this->reasonValidatorResult;
960 $this->reasonValidatorResult =
true;
962 if ( !$authManager->getAuthenticationSessionData(
'reason-retry',
false ) ) {
963 $authManager->setAuthenticationSessionData(
'reason-retry',
true );
964 $this->reasonValidatorResult = $this->msg(
'createacct-reason-confirm' );
966 return $this->reasonValidatorResult;
970 'placeholder-message' =>
'createacct-reason-ph',
980 'default' => $this->msg(
'createacct-' . $anotherPart . $continuePart .
982 'name' =>
'wpCreateaccount',
983 'id' =>
'wpCreateaccount',
987 if ( !$this->msg(
'createacct-username-help' )->isDisabled() ) {
988 $fieldDefinitions[
'username'][
'help-message'] =
'createacct-username-help';
994 $passwordRequest = AuthenticationRequest::getRequestByClass( $this->authRequests,
995 PasswordAuthenticationRequest::class );
996 $changePassword = $passwordRequest && $passwordRequest->action == AuthManager::ACTION_CHANGE;
997 $fieldDefinitions = [
1000 'label-raw' => $this->msg(
'userlogin-yourname' )->escaped() . $secureLoginLink,
1002 'placeholder-message' =>
'userlogin-yourname-ph',
1003 ] + ( $changePassword ? [
1006 'baseField' =>
'password',
1009 'cssclass' =>
'mw-htmlform-hidden-field',
1014 'autocomplete' =>
'new-password',
1015 'placeholder-message' =>
'createacct-yourpassword-ph',
1016 'help-message' =>
'createacct-useuniquepass',
1018 'id' =>
'wpPassword1',
1019 'autocomplete' =>
'current-password',
1020 'placeholder-message' =>
'userlogin-yourpassword-ph',
1024 'type' =>
'password',
1025 'autocomplete' =>
'new-password',
1026 'placeholder-message' =>
'createacct-yourpasswordagain-ph',
1032 'cssclass' =>
'mw-userlogin-rememberme',
1033 'name' =>
'wpRemember',
1034 'label-message' => $this->msg(
'userlogin-remembermypassword' )
1035 ->numParams( $expirationDays ),
1036 'id' =>
'wpRemember',
1044 'default' => $this->msg(
'pt-login-' . $continuePart .
'button' )->text(),
1045 'id' =>
'wpLoginAttempt',
1048 'linkcontainer' => [
1051 'cssclass' =>
'mw-form-related-link-container mw-userlogin-help',
1054 'default' => Html::element(
'a', [
1056 ->inContentLanguage()
1058 ], $this->msg(
'userlogin-helplink2' )->text() ),
1069 $fieldDefinitions[
'username'] += [
1072 'cssclass' =>
'loginText mw-userlogin-username',
1074 'autocomplete' =>
'username',
1077 $fieldDefinitions[
'password'] += [
1078 'type' =>
'password',
1080 'name' =>
'wpPassword',
1081 'cssclass' =>
'loginPassword mw-userlogin-password',
1086 if ( $this->mEntryError ) {
1088 if ( $this->mEntryErrorType ===
'error' ) {
1089 $defaultHtml = Html::errorBox( $this->mEntryError );
1090 } elseif ( $this->mEntryErrorType ===
'warning' ) {
1091 $defaultHtml = Html::warningBox( $this->mEntryError );
1093 $fieldDefinitions[
'entryError'] = [
1095 'default' => $defaultHtml,
1101 if ( !$this->showExtraInformation() ) {
1102 unset( $fieldDefinitions[
'linkcontainer'], $fieldDefinitions[
'signupend'] );
1104 if ( $this->isSignup() && $this->showExtraInformation() ) {
1107 $signupendMsg = $this->msg(
'signupend' );
1108 $signupendHttpsMsg = $this->msg(
'signupend-https' );
1109 if ( !$signupendMsg->isDisabled() ) {
1110 $usingHTTPS = $this->
getRequest()->getProtocol() ===
'https';
1111 $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
1112 ? $signupendHttpsMsg->parse() : $signupendMsg->parse();
1113 $fieldDefinitions[
'signupend'] = [
1116 'default' => Html::rawElement(
'div', [
'id' =>
'signupend' ], $signupendText ),
1121 if ( !$this->isSignup() && $this->showExtraInformation() ) {
1123 if ( $passwordReset->isAllowed( $this->getUser() )->isGood() ) {
1124 $fieldDefinitions[
'passwordReset'] = [
1127 'cssclass' =>
'mw-form-related-link-container',
1128 'default' => $this->getLinkRenderer()->makeLink(
1130 $this->msg(
'userlogin-resetpassword-link' )->text()
1137 if ( $this->showCreateAccountLink() ) {
1139 $linkTitle = $this->getTitleFor( $this->isSignup() ?
'Userlogin' :
'CreateAccount' );
1140 $linkq = $this->getReturnToQueryStringFragment();
1142 if ( $this->mLanguage ) {
1143 $linkq .=
'&uselang=' . urlencode( $this->mLanguage );
1145 if ( $this->mVariant ) {
1146 $linkq .=
'&variant=' . urlencode( $this->mVariant );
1148 $isLoggedIn = $this->
getUser()->isRegistered()
1149 && !$this->
getUser()->isTemp();
1151 $fieldDefinitions[
'createOrLogin'] = [
1154 'linkQuery' => $linkq,
1155 'default' =>
function ( $params ) use ( $isLoggedIn, $linkTitle ) {
1156 $buttonClasses =
'cdx-button cdx-button--action-progressive '
1157 .
'cdx-button--fake-button cdx-button--fake-button--enabled';
1159 return Html::rawElement(
'div',
1160 [
'id' =>
'mw-createaccount' . ( !$isLoggedIn ?
'-cta' :
'' ),
1161 'class' => ( $isLoggedIn ?
'mw-form-related-link-container' :
'mw-ui-vform-field' ) ],
1162 ( $isLoggedIn ?
'' : $this->msg(
'userlogin-noaccount' )->escaped() )
1163 . Html::element(
'a',
1165 'id' =>
'mw-createaccount-join' . ( $isLoggedIn ?
'-loggedin' :
'' ),
1166 'href' => $linkTitle->getLocalURL( $params[
'linkQuery'] ),
1167 'class' => $isLoggedIn ?
'' : $buttonClasses,
1171 $isLoggedIn ?
'userlogin-createanother' :
'userlogin-joinproject'
1181 return $fieldDefinitions;
1194 $config = $this->getConfig();
1195 return $config->get(
'InitialSessionId' ) &&
1196 $this->
getRequest()->getSession()->getId() === (string)$config->get(
'InitialSessionId' );
1206 if ( $this->mReturnTo !==
'' ) {
1207 $returnto =
'returnto=' .
wfUrlencode( $this->mReturnTo );
1208 if ( $this->mReturnToQuery !==
'' ) {
1209 $returnto .=
'&returntoquery=' .
wfUrlencode( $this->mReturnToQuery );
1220 private function showCreateAccountLink() {
1221 return $this->isSignup() ||
1222 $this->
getContext()->getAuthority()->isAllowed(
'createaccount' );
1226 return $this->isSignup() ?
'wpCreateaccountToken' :
'wpLoginToken';
1236 $msg = $this->msg(
'loginlanguagelinks' )->inContentLanguage();
1237 if ( $msg->isBlank() ) {
1240 $langs = explode(
"\n", $msg->text() );
1242 foreach ( $langs as $lang ) {
1243 $lang = trim( $lang,
'* ' );
1244 $parts = explode(
'|', $lang );
1245 if ( count( $parts ) >= 2 ) {
1246 $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
1250 return count( $links ) > 0 ? $this->msg(
'loginlanguagelabel' )->rawParams(
1251 $this->getLanguage()->pipeList( $links ) )->escaped() :
'';
1263 if ( $this->getLanguage()->getCode() == $lang ) {
1265 return htmlspecialchars( $text );
1267 $query = [
'uselang' => $lang ];
1268 if ( $this->mVariant ) {
1269 $query[
'variant'] = $this->mVariant;
1271 if ( $this->mReturnTo !==
'' ) {
1272 $query[
'returnto'] = $this->mReturnTo;
1273 $query[
'returntoquery'] = $this->mReturnToQuery;
1278 ->getLanguage( $lang );
1279 $attr[
'lang'] = $attr[
'hreflang'] = $targetLanguage->getHtmlCode();
1281 return $this->getLinkRenderer()->makeKnownLink(
1282 $this->getPageTitle(),
1300 isset( $formDescriptor[
'username'] ) &&
1301 !isset( $formDescriptor[
'username'][
'default'] ) &&
1305 if ( $user->isRegistered() && !$user->isTemp() ) {
1306 $formDescriptor[
'username'][
'default'] = $user->getName();
1308 $formDescriptor[
'username'][
'default'] =
1309 $this->
getRequest()->getSession()->suggestLoginUsername();
1315 if ( !$this->needsSubmitButton( $requests ) ) {
1316 unset( $formDescriptor[
'createaccount'], $formDescriptor[
'loginattempt'] );
1319 if ( !$this->isSignup() ) {
1323 isset( $formDescriptor[
'username'] )
1324 && empty( $formDescriptor[
'username'][
'default'] )
1325 && !$this->
getRequest()->getCheck(
'wpName' )
1327 $formDescriptor[
'username'][
'autofocus'] =
true;
1328 } elseif ( isset( $formDescriptor[
'password'] ) ) {
1329 $formDescriptor[
'password'][
'autofocus'] =
true;
1333 $this->addTabIndex( $formDescriptor );
1342 $noticeContent = $this->msg(
'createacct-temp-warning', $this->
getUser()->getName() )->parse();
1343 return Html::noticeBox(
1347 'mw-userLogin-icon--user-temporary'
1357class_alias( LoginSignupSpecialPage::class,
'LoginSignupSpecialPage' );
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
wfDeprecated( $function, $version=false, $component=false, $callerOffset=2)
Logs a warning that a deprecated feature was used.
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode) $wgLang
An IContextSource implementation which will inherit context from another source but allow individual ...
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.
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...
getReturnToQueryStringFragment()
Returns a string that can be appended to the URL (without encoding) to preserve the return target.
showReturnToPage( $type, $returnTo='', $returnToQuery='', $stickHTTPS=false)
Add a "return to" link or redirect to it.
showSuccessPage( $type, $title, $msgname, $injected_html, $extraMessages)
Show the success page.
getPreservedParams( $withToken=false)
Returns URL query parameters which can be used to reload the page (or leave and return) while preserv...
setSessionUserForCurrentRequest()
Replace some globals to make sure the fact that the user has just been logged in is reflected in the ...
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')
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,...
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)
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 name of this Special Page.
getFullTitle()
Return the full title, including $par.
The Message class deals with fetching and processing of interface message into a variety of formats.
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...
Group all the pieces relevant to the context of a request into one instance.
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.