32use Wikimedia\ScopedCallback;
54 private $reasonValidatorResult =
null;
77 abstract protected function successfulAction( $direct =
false, $extraMessages =
null );
89 parent::__construct( $name, $restriction );
95 protected function setRequest( array $data, $wasPosted =
null ) {
96 parent::setRequest( $data, $wasPosted );
97 $this->mLoadedRequest =
false;
103 private function loadRequestParameters() {
104 if ( $this->mLoadedRequest ) {
107 $this->mLoadedRequest =
true;
110 $this->mPosted = $request->wasPosted();
111 $this->mAction = $request->getRawVal(
'action' );
112 $this->mFromHTTP = $request->getBool(
'fromhttp',
false )
113 || $request->getBool(
'wpFromhttp',
false );
114 $this->mStickHTTPS = $this->
getConfig()->get( MainConfigNames::ForceHTTPS )
115 || ( !$this->mFromHTTP && $request->getProtocol() ===
'https' )
116 || $request->getBool(
'wpForceHttps',
false );
117 $this->mLanguage = $request->getText(
'uselang' );
118 $this->mReturnTo = $request->getVal(
'returnto',
'' );
119 $this->mReturnToQuery = $request->getVal(
'returntoquery',
'' );
128 $this->loadRequestParameters();
129 if ( $this->mLoaded ) {
132 $this->mLoaded =
true;
135 $securityLevel = $this->
getRequest()->getText(
'force' );
138 MediaWikiServices::getInstance()->
getAuthManager()->securitySensitiveOperationStatus(
146 $this->mToken = $request->getVal( $this->
getTokenName() );
149 $entryError = $this->
msg( $request->getVal(
'error',
'' ) );
150 $entryWarning = $this->
msg( $request->getVal(
'warning',
'' ) );
155 $this->
msg(
'loginreqlink' )->text(),
158 'returnto' => $this->mReturnTo,
159 'returntoquery' => $this->mReturnToQuery,
160 'uselang' => $this->mLanguage ?:
null,
161 'fromhttp' => $this->
getConfig()->get( MainConfigNames::SecureLogin ) &&
162 $this->mFromHTTP ?
'1' :
null,
167 if ( $entryError->exists()
170 $this->mEntryErrorType =
'error';
171 $this->mEntryError = $entryError->rawParams( $loginreqlink )->parse();
173 } elseif ( $entryWarning->exists()
176 $this->mEntryErrorType =
'warning';
177 $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->parse();
180 # 1. When switching accounts, it sucks to get automatically logged out
181 # 2. Do not return to PasswordReset after a successful password change
182 # but goto Wiki start page (Main_Page) instead ( T35997 )
183 $returnToTitle = Title::newFromText( $this->mReturnTo );
184 if ( is_object( $returnToTitle )
185 && ( $returnToTitle->isSpecial(
'Userlogout' )
186 || $returnToTitle->isSpecial(
'PasswordReset' ) )
188 $this->mReturnTo =
'';
189 $this->mReturnToQuery =
'';
194 $params = parent::getPreservedParams( $withToken );
196 'returnto' => $this->mReturnTo ?:
null,
197 'returntoquery' => $this->mReturnToQuery ?:
null,
199 if ( $this->
getConfig()->
get( MainConfigNames::SecureLogin ) && !$this->
isSignup() ) {
200 $params[
'fromhttp'] = $this->mFromHTTP ?
'1' :
null;
207 $this->loadRequestParameters();
208 return parent::beforeExecute(
$subPage );
216 if ( $this->mPosted ) {
217 $time = microtime(
true );
218 $profilingScope =
new ScopedCallback(
function () use ( $time ) {
219 $time = microtime(
true ) - $time;
220 $statsd = MediaWikiServices::getInstance()->getStatsdDataFactory();
221 $statsd->timing(
"timing.login.ui.{$this->authAction}", $time * 1000 );
225 $authManager = MediaWikiServices::getInstance()->getAuthManager();
226 $session = SessionManager::getGlobalSession();
233 $this->
getOutput()->disableClientCache();
240 if ( !$this->
isSignup() && !$authManager->canAuthenticateNow() ) {
241 if ( !$session->canSetUser() ) {
242 throw new ErrorPageError(
'cannotloginnow-title',
'cannotloginnow-text', [
243 $session->getProvider()->describe( $this->getLanguage() )
246 throw new ErrorPageError(
'cannotlogin-title',
'cannotlogin-text' );
247 } elseif ( $this->
isSignup() && !$authManager->canCreateAccounts() ) {
248 throw new ErrorPageError(
'cannotcreateaccount-title',
'cannotcreateaccount-text' );
269 if ( !$this->
isSignup() && !$this->mPosted && !$this->securityLevel &&
270 ( $this->mReturnTo !==
'' || $this->mReturnToQuery !==
'' ) &&
278 if ( $this->
getRequest()->getProtocol() !==
'https' ) {
282 ( $this->mEntryErrorType ===
'error' ?
'error'
283 :
'warning' ) => $this->mEntryError,
291 $this->
getOutput()->addVaryHeader(
'X-Forwarded-Proto' );
298 if ( substr( $url, 0, 8 ) ===
'https://' ) {
299 $this->mSecureLoginUrl = $url;
308 $this->
mainLoginForm( [],
'authpage-cannot-' . $this->authAction );
312 if ( $this->canBypassForm( $button_name ) ) {
315 if ( $button_name ) {
316 $this->
getRequest()->setVal( $button_name,
true );
322 if ( !$status || !$status->isGood() ) {
323 $this->
mainLoginForm( $this->authRequests, $status ? $status->getMessage() :
'',
'error' );
328 $response = $status->getValue();
332 switch ( $response->status ) {
333 case AuthenticationResponse::PASS:
335 $this->proxyAccountCreation = $this->
isSignup() && $this->
getUser()->isNamed();
339 !$this->proxyAccountCreation
340 && $response->loginRequest
341 && $authManager->canAuthenticateNow()
344 $response2 = $authManager->beginAuthentication( [ $response->loginRequest ],
346 if ( $response2->status !== AuthenticationResponse::PASS ) {
347 LoggerFactory::getInstance(
'login' )
348 ->error(
'Could not log in after account creation' );
349 $this->
successfulAction(
true, Status::newFatal(
'createacct-loginerror' ) );
354 if ( !$this->proxyAccountCreation ) {
361 case AuthenticationResponse::FAIL:
363 case AuthenticationResponse::RESTART:
364 unset( $this->authForm );
365 if ( $response->status === AuthenticationResponse::FAIL ) {
367 $messageType =
'error';
370 $messageType =
'warning';
372 $this->
logAuthResult(
false, $response->message ? $response->message->getKey() :
'-' );
374 $this->
mainLoginForm( $this->authRequests, $response->message, $messageType );
376 case AuthenticationResponse::REDIRECT:
377 unset( $this->authForm );
378 $this->
getOutput()->redirect( $response->redirectTarget );
380 case AuthenticationResponse::UI:
381 unset( $this->authForm );
382 $this->authAction = $this->
isSignup() ? AuthManager::ACTION_CREATE_CONTINUE
383 : AuthManager::ACTION_LOGIN_CONTINUE;
384 $this->authRequests = $response->neededRequests;
385 $this->
mainLoginForm( $response->neededRequests, $response->message, $response->messageType );
388 throw new LogicException(
'invalid AuthenticationResponse' );
405 private function canBypassForm( &$button_name ) {
410 $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
411 foreach ( $fields as $fieldname => $field ) {
412 if ( !isset( $field[
'type'] ) ) {
415 if ( !empty( $field[
'skippable'] ) ) {
418 if ( $field[
'type'] ===
'button' ) {
419 if ( $button_name !==
null ) {
423 $button_name = $fieldname;
425 } elseif ( $field[
'type'] !==
'null' ) {
442 $type,
$title, $msgname, $injected_html, $extraMessages
445 $out->setPageTitle(
$title );
449 if ( $extraMessages ) {
450 $extraMessages = Status::wrap( $extraMessages );
451 $out->addWikiTextAsInterface(
452 $extraMessages->getWikiText(
false,
false, $this->getLanguage() )
456 $out->addHTML( $injected_html );
459 $helper->showReturnToPage(
$type, $this->mReturnTo, $this->mReturnToQuery, $this->mStickHTTPS );
478 $type, $returnTo =
'', $returnToQuery =
'', $stickHTTPS =
false
481 $helper->showReturnToPage(
$type, $returnTo, $returnToQuery, $stickHTTPS );
491 $context = RequestContext::getMain();
493 if ( $context !== $localContext ) {
498 $user = $context->getRequest()->getSession()->getUser();
501 $context->setUser( $user );
503 $wgLang = $context->getLanguage();
520 protected function mainLoginForm( array $requests, $msg =
'', $msgtype =
'error' ) {
528 $this->authForm =
null;
529 $requests = MediaWikiServices::getInstance()->getAuthManager()
530 ->getAuthenticationRequests( $this->authAction, $user );
534 $out->addModuleStyles( [
536 'mediawiki.ui.button',
537 'mediawiki.ui.checkbox',
538 'mediawiki.ui.input',
539 'mediawiki.special.userlogin.common.styles'
543 $out->addJsConfigVars(
'wgCreateacctImgcaptchaHelp',
544 $this->
msg(
'createacct-imgcaptcha-help' )->parse() );
547 $out->addModules(
'mediawiki.special.createaccount' );
548 $out->addModuleStyles( [
549 'mediawiki.special.userlogin.signup.styles'
553 $out->addModuleStyles( [
554 'mediawiki.special.userlogin.login.styles'
557 $out->disallowUserJs();
559 $form = $this->
getAuthForm( $requests, $this->authAction, $msg, $msgtype );
560 $form->prepareForm();
562 $submitStatus = Status::newGood();
563 if ( $msg && $msgtype ===
'warning' ) {
564 $submitStatus->warning( $msg );
565 } elseif ( $msg && $msgtype ===
'error' ) {
566 $submitStatus->fatal( $msg );
572 $this->
getUser()->isRegistered() &&
574 $this->authAction !== AuthManager::ACTION_LOGIN_CONTINUE
576 $reauthMessage = $this->securityLevel ?
'userlogin-reauth' :
'userlogin-loggedin';
577 $submitStatus->warning( $reauthMessage, $this->
getUser()->
getName() );
580 $formHtml = $form->getHTML( $submitStatus );
592 $loginPrompt = $this->
isSignup() ?
'' : Html::rawElement(
'div',
593 [
'id' =>
'userloginprompt' ], $this->
msg(
'loginprompt' )->parseAsBlock() );
594 $languageLinks = $this->
getConfig()->get( MainConfigNames::LoginLanguageSelector )
596 $signupStartMsg = $this->
msg(
'signupstart' );
597 $signupStart = ( $this->
isSignup() && !$signupStartMsg->isDisabled() )
598 ? Html::rawElement(
'div', [
'id' =>
'signupstart' ], $signupStartMsg->parseAsBlock() ) :
'';
599 if ( $languageLinks ) {
600 $languageLinks = Html::rawElement(
'div', [
'id' =>
'languagelinks' ],
601 Html::rawElement(
'p', [], $languageLinks )
605 return Html::rawElement(
'div', [
'class' =>
'mw-ui-container' ],
609 . Html::rawElement(
'div', [
'id' =>
'userloginForm' ], $formHtml )
622 $benefitsContainer =
'';
630 for ( $benefitIdx = 1; $benefitIdx <= $benefitCount; $benefitIdx++ ) {
631 $headUnescaped = $this->
msg(
"createacct-benefit-head$benefitIdx" )->text();
632 $iconClass = $this->
msg(
"createacct-benefit-icon$benefitIdx" )->text();
633 $benefitList .= Html::rawElement(
'div', [
'class' =>
"mw-number-text $iconClass" ],
634 Html::rawElement(
'h3', [],
635 $this->
msg(
"createacct-benefit-head$benefitIdx" )->escaped()
637 . Html::rawElement(
'p', [],
638 $this->
msg(
"createacct-benefit-body$benefitIdx" )->params( $headUnescaped )->escaped()
642 $benefitsContainer = Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-container' ],
643 Html::rawElement(
'h2', [], $this->
msg(
'createacct-benefit-heading' )->escaped() )
644 . Html::rawElement(
'div', [
'class' =>
'mw-createacct-benefits-list' ], $benefitList )
647 return $benefitsContainer;
658 protected function getAuthForm( array $requests, $action, $msg =
'', $msgType =
'error' ) {
661 if ( isset( $this->authForm ) ) {
662 return $this->authForm;
665 $usingHTTPS = $this->getRequest()->getProtocol() ===
'https';
668 $fieldInfo = AuthenticationRequest::mergeFieldInfo( $requests );
670 $formDescriptor = $this->fieldInfoToFormDescriptor( $requests, $fieldInfo, $this->authAction );
671 $this->postProcessFormDescriptor( $formDescriptor, $requests );
674 if ( $context->getRequest() !== $this->getRequest() ) {
677 $context->setRequest( $this->getRequest() );
679 $form = HTMLForm::factory(
'vform', $formDescriptor, $context );
681 $form->addHiddenField(
'authAction', $this->authAction );
682 if ( $this->mLanguage ) {
683 $form->addHiddenField(
'uselang', $this->mLanguage );
685 $form->addHiddenField(
'force', $this->securityLevel );
686 $form->addHiddenField( $this->getTokenName(), $this->getToken()->toString() );
687 $config = $this->getConfig();
688 if ( $config->get( MainConfigNames::SecureLogin ) &&
689 !$config->get( MainConfigNames::ForceHTTPS ) ) {
691 if ( !$this->isSignup() ) {
692 $form->addHiddenField(
'wpForceHttps', (
int)$this->mStickHTTPS );
693 $form->addHiddenField(
'wpFromhttp', $usingHTTPS );
698 $form->setAction( $this->getPageTitle()->getLocalURL( $this->getReturnToQueryStringFragment() ) );
699 $form->setName(
'userlogin' . ( $this->isSignup() ?
'2' :
'' ) );
700 if ( $this->isSignup() ) {
701 $form->setId(
'userlogin2' );
704 $form->suppressDefaultSubmit();
706 $this->authForm = $form;
713 array $requests, array $fieldInfo, array &$formDescriptor, $action
715 $formDescriptor = self::mergeDefaultFormDescriptor( $fieldInfo, $formDescriptor,
716 $this->getFieldDefinitions( $fieldInfo ) );
726 return $this->authAction !== $this->getContinueAction( $this->authAction )
727 && !$this->securityLevel;
736 $isLoggedIn = $this->
getUser()->isRegistered();
737 $continuePart = $this->isContinued() ?
'continue-' :
'';
738 $anotherPart = $isLoggedIn ?
'another-' :
'';
740 $expiration = $this->getRequest()->getSession()->getProvider()->getRememberUserDuration();
741 $expirationDays = ceil( $expiration / ( 3600 * 24 ) );
742 $secureLoginLink =
'';
743 if ( $this->mSecureLoginUrl ) {
744 $secureLoginLink = Html::element(
'a', [
745 'href' => $this->mSecureLoginUrl,
746 'class' =>
'mw-ui-flush-right mw-secure',
747 ], $this->msg(
'userlogin-signwithsecure' )->text() );
749 $usernameHelpLink =
'';
750 if ( !$this->msg(
'createacct-helpusername' )->isDisabled() ) {
751 $usernameHelpLink = Html::rawElement(
'span', [
752 'class' =>
'mw-ui-flush-right',
753 ], $this->msg(
'createacct-helpusername' )->parse() );
756 if ( $this->isSignup() ) {
757 $config = $this->getConfig();
758 $hideIf = isset( $fieldInfo[
'mailpassword'] ) ? [
'hide-if' => [
'===',
'mailpassword',
'1' ] ] : [];
759 $fieldDefinitions = [
765 'default' => Html::element(
'div', [
'id' =>
'mw-createacct-status-area' ] ),
769 'label-raw' => $this->msg(
'userlogin-yourname' )->escaped() . $usernameHelpLink,
771 'placeholder-message' => $isLoggedIn ?
'createacct-another-username-ph'
772 :
'userlogin-yourname-ph',
777 'label-message' =>
'createaccountmail',
778 'name' =>
'wpCreateaccountMail',
779 'id' =>
'wpCreateaccountMail',
782 'id' =>
'wpPassword2',
783 'autocomplete' =>
'new-password',
784 'placeholder-message' =>
'createacct-yourpassword-ph',
785 'help-message' =>
'createacct-useuniquepass',
789 'type' =>
'password',
790 'label-message' =>
'createacct-yourpasswordagain',
792 'cssclass' =>
'loginPassword',
794 'autocomplete' =>
'new-password',
795 'validation-callback' =>
function ( $value, $alldata ) {
796 if ( empty( $alldata[
'mailpassword'] ) && !empty( $alldata[
'password'] ) ) {
798 return $this->msg(
'htmlform-required' );
799 } elseif ( $value !== $alldata[
'password'] ) {
800 return $this->msg(
'badretype' );
805 'placeholder-message' =>
'createacct-yourpasswordagain-ph',
809 'label-message' => $config->get( MainConfigNames::EmailConfirmToEdit )
810 ?
'createacct-emailrequired' :
'createacct-emailoptional',
812 'cssclass' =>
'loginText',
815 'autocomplete' =>
'email',
817 'required' => $config->get( MainConfigNames::EmailConfirmToEdit ),
818 'validation-callback' =>
function ( $value, $alldata ) {
822 $this->getConfig()->get( MainConfigNames::EmailConfirmToEdit )
826 return $this->msg(
'noemailtitle' );
827 } elseif ( !$value && !empty( $alldata[
'mailpassword'] ) ) {
829 return $this->msg(
'noemailcreate' );
830 } elseif ( $value && !Sanitizer::validateEmail( $value ) ) {
831 return $this->msg(
'invalidemailaddress' );
832 } elseif ( is_string( $value ) && strlen( $value ) > 255 ) {
833 return $this->msg(
'changeemail-maxlength' );
840 'placeholder-message' =>
'createacct-' . $anotherPart .
'email-ph',
844 'help-message' => $isLoggedIn ?
'createacct-another-realname-tip'
845 :
'prefs-help-realname',
846 'label-message' =>
'createacct-realname',
847 'cssclass' =>
'loginText',
849 'id' =>
'wpRealName',
850 'autocomplete' =>
'name',
855 'label-message' =>
'createacct-reason',
856 'cssclass' =>
'loginText',
859 'validation-callback' =>
function ( $value, $alldata ) {
862 if ( $value && Sanitizer::validateEmail( $value ) ) {
863 if ( $this->reasonValidatorResult !==
null ) {
864 return $this->reasonValidatorResult;
866 $this->reasonValidatorResult =
true;
867 $authManager = MediaWikiServices::getInstance()->getAuthManager();
868 if ( !$authManager->getAuthenticationSessionData(
'reason-retry',
false ) ) {
869 $authManager->setAuthenticationSessionData(
'reason-retry',
true );
870 $this->reasonValidatorResult = $this->msg(
'createacct-reason-confirm' );
872 return $this->reasonValidatorResult;
876 'placeholder-message' =>
'createacct-reason-ph',
886 'default' => $this->msg(
'createacct-' . $anotherPart . $continuePart .
888 'name' =>
'wpCreateaccount',
889 'id' =>
'wpCreateaccount',
893 if ( !$this->msg(
'createacct-username-help' )->isDisabled() ) {
894 $fieldDefinitions[
'username'][
'help-message'] =
'createacct-username-help';
900 $passwordRequest = AuthenticationRequest::getRequestByClass( $this->authRequests,
901 PasswordAuthenticationRequest::class );
902 $changePassword = $passwordRequest && $passwordRequest->action == AuthManager::ACTION_CHANGE;
903 $fieldDefinitions = [
906 'label-raw' => $this->msg(
'userlogin-yourname' )->escaped() . $secureLoginLink,
908 'placeholder-message' =>
'userlogin-yourname-ph',
909 ] + ( $changePassword ? [
912 'baseField' =>
'password',
915 'cssclass' =>
'mw-htmlform-hidden-field',
920 'autocomplete' =>
'new-password',
921 'placeholder-message' =>
'createacct-yourpassword-ph',
922 'help-message' =>
'createacct-useuniquepass',
924 'id' =>
'wpPassword1',
925 'autocomplete' =>
'current-password',
926 'placeholder-message' =>
'userlogin-yourpassword-ph',
930 'type' =>
'password',
931 'autocomplete' =>
'new-password',
932 'placeholder-message' =>
'createacct-yourpasswordagain-ph',
938 'cssclass' =>
'mw-userlogin-rememberme',
939 'name' =>
'wpRemember',
940 'label-message' => $this->msg(
'userlogin-remembermypassword' )
941 ->numParams( $expirationDays ),
942 'id' =>
'wpRemember',
950 'default' => $this->msg(
'pt-login-' . $continuePart .
'button' )->text(),
951 'id' =>
'wpLoginAttempt',
957 'cssclass' =>
'mw-form-related-link-container mw-userlogin-help',
960 'default' => Html::element(
'a', [
962 ->inContentLanguage()
964 ], $this->msg(
'userlogin-helplink2' )->text() ),
975 $fieldDefinitions[
'username'] += [
978 'cssclass' =>
'loginText',
980 'autocomplete' =>
'username',
983 $fieldDefinitions[
'password'] += [
984 'type' =>
'password',
986 'name' =>
'wpPassword',
987 'cssclass' =>
'loginPassword',
992 if ( $this->mEntryError ) {
994 if ( $this->mEntryErrorType ===
'error' ) {
995 $defaultHtml = Html::errorBox( $this->mEntryError );
996 } elseif ( $this->mEntryErrorType ===
'warning' ) {
997 $defaultHtml = Html::warningBox( $this->mEntryError );
999 $fieldDefinitions[
'entryError'] = [
1001 'default' => $defaultHtml,
1007 if ( $this->isSignup() && $this->
getUser()->isTemp() ) {
1008 $fieldDefinitions[
'tempWarning'] = [
1010 'default' => Html::warningBox(
1011 $this->msg(
'createacct-temp-warning' )->parse()
1018 if ( !$this->showExtraInformation() ) {
1019 unset( $fieldDefinitions[
'linkcontainer'], $fieldDefinitions[
'signupend'] );
1021 if ( $this->isSignup() && $this->showExtraInformation() ) {
1024 $signupendMsg = $this->msg(
'signupend' );
1025 $signupendHttpsMsg = $this->msg(
'signupend-https' );
1026 if ( !$signupendMsg->isDisabled() ) {
1027 $usingHTTPS = $this->getRequest()->getProtocol() ===
'https';
1028 $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
1029 ? $signupendHttpsMsg->parse() : $signupendMsg->parse();
1030 $fieldDefinitions[
'signupend'] = [
1033 'default' => Html::rawElement(
'div', [
'id' =>
'signupend' ], $signupendText ),
1038 if ( !$this->isSignup() && $this->showExtraInformation() ) {
1039 $passwordReset = MediaWikiServices::getInstance()->getPasswordReset();
1040 if ( $passwordReset->isAllowed( $this->getUser() )->isGood() ) {
1041 $fieldDefinitions[
'passwordReset'] = [
1044 'cssclass' =>
'mw-form-related-link-container',
1045 'default' => $this->getLinkRenderer()->makeLink(
1047 $this->msg(
'userlogin-resetpassword-link' )->text()
1054 if ( $this->showCreateAccountLink() ) {
1056 $linkTitle = $this->getTitleFor( $this->isSignup() ?
'Userlogin' :
'CreateAccount' );
1057 $linkq = $this->getReturnToQueryStringFragment();
1059 if ( $this->mLanguage ) {
1060 $linkq .=
'&uselang=' . urlencode( $this->mLanguage );
1062 $isLoggedIn = $this->
getUser()->isRegistered()
1063 && !$this->
getUser()->isTemp();
1065 $fieldDefinitions[
'createOrLogin'] = [
1068 'linkQuery' => $linkq,
1069 'default' =>
function ( $params ) use ( $isLoggedIn, $linkTitle ) {
1070 return Html::rawElement(
'div',
1071 [
'id' =>
'mw-createaccount' . ( !$isLoggedIn ?
'-cta' :
'' ),
1072 'class' => ( $isLoggedIn ?
'mw-form-related-link-container' :
'mw-ui-vform-field' ) ],
1073 ( $isLoggedIn ?
'' : $this->msg(
'userlogin-noaccount' )->escaped() )
1074 . Html::element(
'a',
1076 'id' =>
'mw-createaccount-join' . ( $isLoggedIn ?
'-loggedin' :
'' ),
1077 'href' => $linkTitle->getLocalURL( $params[
'linkQuery'] ),
1078 'class' => ( $isLoggedIn ?
'' :
'mw-ui-button' ),
1082 $isLoggedIn ?
'userlogin-createanother' :
'userlogin-joinproject'
1092 return $fieldDefinitions;
1105 $config = $this->getConfig();
1106 return $config->get( MainConfigNames::DisableCookieCheck ) || (
1107 $config->get(
'InitialSessionId' ) &&
1108 $this->getRequest()->getSession()->getId() === (string)$config->get(
'InitialSessionId' )
1119 if ( $this->mReturnTo !==
'' ) {
1120 $returnto =
'returnto=' .
wfUrlencode( $this->mReturnTo );
1121 if ( $this->mReturnToQuery !==
'' ) {
1122 $returnto .=
'&returntoquery=' .
wfUrlencode( $this->mReturnToQuery );
1133 private function showCreateAccountLink() {
1134 return $this->isSignup() ||
1135 $this->
getContext()->getAuthority()->isAllowed(
'createaccount' );
1139 return $this->isSignup() ?
'wpCreateaccountToken' :
'wpLoginToken';
1149 $msg = $this->msg(
'loginlanguagelinks' )->inContentLanguage();
1150 if ( $msg->isBlank() ) {
1153 $langs = explode(
"\n", $msg->text() );
1155 foreach ( $langs as
$lang ) {
1157 $parts = explode(
'|',
$lang );
1158 if ( count( $parts ) >= 2 ) {
1159 $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
1163 return count( $links ) > 0 ? $this->msg(
'loginlanguagelabel' )->rawParams(
1164 $this->getLanguage()->pipeList( $links ) )->escaped() :
'';
1176 if ( $this->getLanguage()->getCode() ==
$lang ) {
1178 return htmlspecialchars( $text );
1180 $query = [
'uselang' =>
$lang ];
1181 if ( $this->mReturnTo !==
'' ) {
1182 $query[
'returnto'] = $this->mReturnTo;
1183 $query[
'returntoquery'] = $this->mReturnToQuery;
1187 $targetLanguage = MediaWikiServices::getInstance()->getLanguageFactory()
1188 ->getLanguage(
$lang );
1189 $attr[
'lang'] = $attr[
'hreflang'] = $targetLanguage->getHtmlCode();
1191 return $this->getLinkRenderer()->makeKnownLink(
1192 $this->getPageTitle(),
1210 isset( $formDescriptor[
'username'] ) &&
1211 !isset( $formDescriptor[
'username'][
'default'] ) &&
1215 if ( $user->isRegistered() && !$user->isTemp() ) {
1216 $formDescriptor[
'username'][
'default'] = $user->getName();
1218 $formDescriptor[
'username'][
'default'] =
1219 $this->getRequest()->getSession()->suggestLoginUsername();
1225 if ( !$this->needsSubmitButton( $requests ) ) {
1226 unset( $formDescriptor[
'createaccount'], $formDescriptor[
'loginattempt'] );
1229 if ( !$this->isSignup() ) {
1233 isset( $formDescriptor[
'username'] )
1234 && empty( $formDescriptor[
'username'][
'default'] )
1235 && !$this->getRequest()->getCheck(
'wpName' )
1237 $formDescriptor[
'username'][
'autofocus'] =
true;
1238 } elseif ( isset( $formDescriptor[
'password'] ) ) {
1239 $formDescriptor[
'password'][
'autofocus'] =
true;
1243 $this->addTabIndex( $formDescriptor );
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,...
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode $wgLang
A special page subclass for authentication-related special pages.
getContinueAction( $action)
Gets the _CONTINUE version of an action.
isActionAllowed( $action)
Checks whether AuthManager is ready to perform the action.
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.
string $subPage
Subpage of the special page.
isContinued()
Returns true if this is not the first step of the authentication.
getRequest()
Get the WebRequest being used for this instance.
trySubmit()
Attempts to do an authentication step with the submitted data.
getToken()
Returns the CSRF token.
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.
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.
Holds shared logic for login and account creation pages.
mainLoginForm(array $requests, $msg='', $msgtype='error')
getPreservedParams( $withToken=false)
Returns URL query parameters which can be used to reload the page (or leave and return) while preserv...
logAuthResult( $success, $status=null)
Logs to the authmanager-stats channel.
onAuthChangeFormFields(array $requests, array $fieldInfo, array &$formDescriptor, $action)
Change the form descriptor that determines how a field will look in the authentication form....
setSessionUserForCurrentRequest()
Replace some globals to make sure the fact that the user has just been logged in is reflected in the ...
getBenefitsContainerHtml()
The HTML to be shown in the "benefits to signing in / creating an account" section of the signup/logi...
showSuccessPage( $type, $title, $msgname, $injected_html, $extraMessages)
Show the success page.
getFieldDefinitions(array $fieldInfo)
Create a HTMLForm descriptor for the core login fields.
getReturnToQueryStringFragment()
Returns a string that can be appended to the URL (without encoding) to preserve the return target.
User $targetUser
FIXME another flag for passing data.
successfulAction( $direct=false, $extraMessages=null)
showExtraInformation()
Show extra information such as password recovery information, link from login to signup,...
getPageHtml( $formHtml)
Add page elements which are outside the form.
hasSessionCookie()
Check if a session cookie is present.
__construct( $name, $restriction='')
getAuthForm(array $requests, $action, $msg='', $msgType='error')
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).
makeLanguageSelectorLink( $text, $lang)
Create a language selector link for a particular language Links back to this page preserving type and...
bool $proxyAccountCreation
True if the user if creating an account for someone else.
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
postProcessFormDescriptor(&$formDescriptor, $requests)
setRequest(array $data, $wasPosted=null)
Override the POST data, GET data from the real request is preserved.
showReturnToPage( $type, $returnTo='', $returnToQuery='', $stickHTTPS=false)
Add a "return to" link or redirect to it.
makeLanguageSelector()
Produce a bar of links which allow the user to select another language during login/registration but ...
load( $subPage)
Load data from request.
A class containing constants representing the names of configuration variables.
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
setContext( $context)
Sets the context this SpecialPage is executed in.
getName()
Get the name of this Special Page.
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
getOutput()
Get the OutputPage being used for this instance.
getUser()
Shortcut to get the User executing this instance.
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
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,...
getContext()
Gets the context this SpecialPage is executed in.
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
getConfig()
Shortcut to get main config object.
getPageTitle( $subpage=false)
Get a self-referential title object.
getFullTitle()
Return the full title, including $par.
static setUser( $user)
Reset the stub global user to a different "real" user object, while ensuring that any method calls on...
static newFromName( $name, $validate='valid')
$wgUseMediaWikiUIEverywhere
Config variable stub for the UseMediaWikiUIEverywhere setting, for use by phpdoc and IDEs.
if(!isset( $args[0])) $lang