MediaWiki  master
LoginSignupSpecialPage.php
Go to the documentation of this file.
1 <?php
30 use Wikimedia\ScopedCallback;
31 
38  protected $mReturnTo;
39  protected $mPosted;
40  protected $mAction;
41  protected $mLanguage;
42  protected $mReturnToQuery;
43  protected $mToken;
44  protected $mStickHTTPS;
45  protected $mFromHTTP;
46  protected $mEntryError = '';
47  protected $mEntryErrorType = 'error';
48 
49  protected $mLoaded = false;
50  protected $mLoadedRequest = false;
51  protected $mSecureLoginUrl;
52 
54  protected $securityLevel;
55 
61  protected $targetUser;
62 
64  protected $authForm;
65 
66  abstract protected function isSignup();
67 
74  abstract protected function successfulAction( $direct = false, $extraMessages = null );
75 
81  abstract protected function logAuthResult( $success, $status = null );
82 
83  public function __construct( $name ) {
85  parent::__construct( $name );
86 
87  // Override UseMediaWikiEverywhere to true, to force login and create form to use mw ui
89  }
90 
91  protected function setRequest( array $data, $wasPosted = null ) {
92  parent::setRequest( $data, $wasPosted );
93  $this->mLoadedRequest = false;
94  }
95 
99  private function loadRequestParameters() {
100  if ( $this->mLoadedRequest ) {
101  return;
102  }
103  $this->mLoadedRequest = true;
104  $request = $this->getRequest();
105 
106  $this->mPosted = $request->wasPosted();
107  $this->mAction = $request->getVal( 'action' );
108  $this->mFromHTTP = $request->getBool( 'fromhttp', false )
109  || $request->getBool( 'wpFromhttp', false );
110  $this->mStickHTTPS = ( !$this->mFromHTTP && $request->getProtocol() === 'https' )
111  || $request->getBool( 'wpForceHttps', false );
112  $this->mLanguage = $request->getText( 'uselang' );
113  $this->mReturnTo = $request->getVal( 'returnto', '' );
114  $this->mReturnToQuery = $request->getVal( 'returntoquery', '' );
115  }
116 
122  protected function load( $subPage ) {
123  global $wgSecureLogin;
124 
125  $this->loadRequestParameters();
126  if ( $this->mLoaded ) {
127  return;
128  }
129  $this->mLoaded = true;
130  $request = $this->getRequest();
131 
132  $securityLevel = $this->getRequest()->getText( 'force' );
133  if (
134  $securityLevel && AuthManager::singleton()->securitySensitiveOperationStatus(
135  $securityLevel ) === AuthManager::SEC_REAUTH
136  ) {
137  $this->securityLevel = $securityLevel;
138  }
139 
140  $this->loadAuth( $subPage );
141 
142  $this->mToken = $request->getVal( $this->getTokenName() );
143 
144  // Show an error or warning passed on from a previous page
145  $entryError = $this->msg( $request->getVal( 'error', '' ) );
146  $entryWarning = $this->msg( $request->getVal( 'warning', '' ) );
147  // bc: provide login link as a parameter for messages where the translation
148  // was not updated
149  $loginreqlink = $this->getLinkRenderer()->makeKnownLink(
150  $this->getPageTitle(),
151  $this->msg( 'loginreqlink' )->text(),
152  [],
153  [
154  'returnto' => $this->mReturnTo,
155  'returntoquery' => $this->mReturnToQuery,
156  'uselang' => $this->mLanguage ?: null,
157  'fromhttp' => $wgSecureLogin && $this->mFromHTTP ? '1' : null,
158  ]
159  );
160 
161  // Only show valid error or warning messages.
162  if ( $entryError->exists()
163  && in_array( $entryError->getKey(), LoginHelper::getValidErrorMessages(), true )
164  ) {
165  $this->mEntryErrorType = 'error';
166  $this->mEntryError = $entryError->rawParams( $loginreqlink )->parse();
167 
168  } elseif ( $entryWarning->exists()
169  && in_array( $entryWarning->getKey(), LoginHelper::getValidErrorMessages(), true )
170  ) {
171  $this->mEntryErrorType = 'warning';
172  $this->mEntryError = $entryWarning->rawParams( $loginreqlink )->parse();
173  }
174 
175  # 1. When switching accounts, it sucks to get automatically logged out
176  # 2. Do not return to PasswordReset after a successful password change
177  # but goto Wiki start page (Main_Page) instead ( T35997 )
178  $returnToTitle = Title::newFromText( $this->mReturnTo );
179  if ( is_object( $returnToTitle )
180  && ( $returnToTitle->isSpecial( 'Userlogout' )
181  || $returnToTitle->isSpecial( 'PasswordReset' ) )
182  ) {
183  $this->mReturnTo = '';
184  $this->mReturnToQuery = '';
185  }
186  }
187 
188  protected function getPreservedParams( $withToken = false ) {
189  global $wgSecureLogin;
190 
191  $params = parent::getPreservedParams( $withToken );
192  $params += [
193  'returnto' => $this->mReturnTo ?: null,
194  'returntoquery' => $this->mReturnToQuery ?: null,
195  ];
196  if ( $wgSecureLogin && !$this->isSignup() ) {
197  $params['fromhttp'] = $this->mFromHTTP ? '1' : null;
198  }
199  return $params;
200  }
201 
202  protected function beforeExecute( $subPage ) {
203  // finish initializing the class before processing the request - T135924
204  $this->loadRequestParameters();
205  return parent::beforeExecute( $subPage );
206  }
207 
212  public function execute( $subPage ) {
213  if ( $this->mPosted ) {
214  $time = microtime( true );
215  $profilingScope = new ScopedCallback( function () use ( $time ) {
216  $time = microtime( true ) - $time;
217  $statsd = MediaWikiServices::getInstance()->getStatsdDataFactory();
218  $statsd->timing( "timing.login.ui.{$this->authAction}", $time * 1000 );
219  } );
220  }
221 
222  $authManager = AuthManager::singleton();
223  $session = SessionManager::getGlobalSession();
224 
225  // Session data is used for various things in the authentication process, so we must make
226  // sure a session cookie or some equivalent mechanism is set.
227  $session->persist();
228  // Explicitly disable cache to ensure cookie blocks may be set (T152462).
229  // (Technically redundant with sessions persisting from this page.)
230  $this->getOutput()->enableClientCache( false );
231 
232  $this->load( $subPage );
233  $this->setHeaders();
234  $this->checkPermissions();
235 
236  // Make sure the system configuration allows log in / sign up
237  if ( !$this->isSignup() && !$authManager->canAuthenticateNow() ) {
238  if ( !$session->canSetUser() ) {
239  throw new ErrorPageError( 'cannotloginnow-title', 'cannotloginnow-text', [
240  $session->getProvider()->describe( RequestContext::getMain()->getLanguage() )
241  ] );
242  }
243  throw new ErrorPageError( 'cannotlogin-title', 'cannotlogin-text' );
244  } elseif ( $this->isSignup() && !$authManager->canCreateAccounts() ) {
245  throw new ErrorPageError( 'cannotcreateaccount-title', 'cannotcreateaccount-text' );
246  }
247 
248  /*
249  * In the case where the user is already logged in, and was redirected to
250  * the login form from a page that requires login, do not show the login
251  * page. The use case scenario for this is when a user opens a large number
252  * of tabs, is redirected to the login page on all of them, and then logs
253  * in on one, expecting all the others to work properly.
254  *
255  * However, do show the form if it was visited intentionally (no 'returnto'
256  * is present). People who often switch between several accounts have grown
257  * accustomed to this behavior.
258  *
259  * Also make an exception when force=<level> is set in the URL, which means the user must
260  * reauthenticate for security reasons.
261  */
262  if ( !$this->isSignup() && !$this->mPosted && !$this->securityLevel &&
263  ( $this->mReturnTo !== '' || $this->mReturnToQuery !== '' ) &&
264  $this->getUser()->isLoggedIn()
265  ) {
266  $this->successfulAction();
267  return;
268  }
269 
270  // If logging in and not on HTTPS, either redirect to it or offer a link.
271  global $wgSecureLogin;
272  if ( $this->getRequest()->getProtocol() !== 'https' ) {
273  $title = $this->getFullTitle();
274  $query = $this->getPreservedParams( false ) + [
275  'title' => null,
276  ( $this->mEntryErrorType === 'error' ? 'error'
277  : 'warning' ) => $this->mEntryError,
278  ] + $this->getRequest()->getQueryValues();
279  $url = $title->getFullURL( $query, false, PROTO_HTTPS );
280  if ( $wgSecureLogin && !$this->mFromHTTP &&
281  wfCanIPUseHTTPS( $this->getRequest()->getIP() )
282  ) {
283  // Avoid infinite redirect
284  $url = wfAppendQuery( $url, 'fromhttp=1' );
285  $this->getOutput()->redirect( $url );
286  // Since we only do this redir to change proto, always vary
287  $this->getOutput()->addVaryHeader( 'X-Forwarded-Proto' );
288 
289  return;
290  } else {
291  // A wiki without HTTPS login support should set $wgServer to
292  // http://somehost, in which case the secure URL generated
293  // above won't actually start with https://
294  if ( substr( $url, 0, 8 ) === 'https://' ) {
295  $this->mSecureLoginUrl = $url;
296  }
297  }
298  }
299 
300  if ( !$this->isActionAllowed( $this->authAction ) ) {
301  // FIXME how do we explain this to the user? can we handle session loss better?
302  // messages used: authpage-cannot-login, authpage-cannot-login-continue,
303  // authpage-cannot-create, authpage-cannot-create-continue
304  $this->mainLoginForm( [], 'authpage-cannot-' . $this->authAction );
305  return;
306  }
307 
308  if ( $this->canBypassForm( $button_name ) ) {
309  $this->setRequest( [], true );
310  $this->getRequest()->setVal( $this->getTokenName(), $this->getToken() );
311  if ( $button_name ) {
312  $this->getRequest()->setVal( $button_name, true );
313  }
314  }
315 
316  $status = $this->trySubmit();
317 
318  if ( !$status || !$status->isGood() ) {
319  $this->mainLoginForm( $this->authRequests, $status ? $status->getMessage() : '', 'error' );
320  return;
321  }
322 
324  $response = $status->getValue();
325 
326  $returnToUrl = $this->getPageTitle( 'return' )
327  ->getFullURL( $this->getPreservedParams( true ), false, PROTO_HTTPS );
328  switch ( $response->status ) {
329  case AuthenticationResponse::PASS:
330  $this->logAuthResult( true );
331  $this->proxyAccountCreation = $this->isSignup() && !$this->getUser()->isAnon();
332  $this->targetUser = User::newFromName( $response->username );
333 
334  if (
335  !$this->proxyAccountCreation
336  && $response->loginRequest
337  && $authManager->canAuthenticateNow()
338  ) {
339  // successful registration; log the user in instantly
340  $response2 = $authManager->beginAuthentication( [ $response->loginRequest ],
341  $returnToUrl );
342  if ( $response2->status !== AuthenticationResponse::PASS ) {
343  LoggerFactory::getInstance( 'login' )
344  ->error( 'Could not log in after account creation' );
345  $this->successfulAction( true, Status::newFatal( 'createacct-loginerror' ) );
346  break;
347  }
348  }
349 
350  if ( !$this->proxyAccountCreation ) {
351  // Ensure that the context user is the same as the session user.
353  }
354 
355  $this->successfulAction( true );
356  break;
357  case AuthenticationResponse::FAIL:
358  // fall through
359  case AuthenticationResponse::RESTART:
360  unset( $this->authForm );
361  if ( $response->status === AuthenticationResponse::FAIL ) {
362  $action = $this->getDefaultAction( $subPage );
363  $messageType = 'error';
364  } else {
365  $action = $this->getContinueAction( $this->authAction );
366  $messageType = 'warning';
367  }
368  $this->logAuthResult( false, $response->message ? $response->message->getKey() : '-' );
369  $this->loadAuth( $subPage, $action, true );
370  $this->mainLoginForm( $this->authRequests, $response->message, $messageType );
371  break;
372  case AuthenticationResponse::REDIRECT:
373  unset( $this->authForm );
374  $this->getOutput()->redirect( $response->redirectTarget );
375  break;
376  case AuthenticationResponse::UI:
377  unset( $this->authForm );
378  $this->authAction = $this->isSignup() ? AuthManager::ACTION_CREATE_CONTINUE
379  : AuthManager::ACTION_LOGIN_CONTINUE;
380  $this->authRequests = $response->neededRequests;
381  $this->mainLoginForm( $response->neededRequests, $response->message, $response->messageType );
382  break;
383  default:
384  throw new LogicException( 'invalid AuthenticationResponse' );
385  }
386  }
387 
401  private function canBypassForm( &$button_name ) {
402  $button_name = null;
403  if ( $this->isContinued() ) {
404  return false;
405  }
406  $fields = AuthenticationRequest::mergeFieldInfo( $this->authRequests );
407  foreach ( $fields as $fieldname => $field ) {
408  if ( !isset( $field['type'] ) ) {
409  return false;
410  }
411  if ( !empty( $field['skippable'] ) ) {
412  continue;
413  }
414  if ( $field['type'] === 'button' ) {
415  if ( $button_name !== null ) {
416  $button_name = null;
417  return false;
418  } else {
419  $button_name = $fieldname;
420  }
421  } elseif ( $field['type'] !== 'null' ) {
422  return false;
423  }
424  }
425  return true;
426  }
427 
437  protected function showSuccessPage(
438  $type, $title, $msgname, $injected_html, $extraMessages
439  ) {
440  $out = $this->getOutput();
441  $out->setPageTitle( $title );
442  if ( $msgname ) {
443  $out->addWikiMsg( $msgname, wfEscapeWikiText( $this->getUser()->getName() ) );
444  }
445  if ( $extraMessages ) {
446  $extraMessages = Status::wrap( $extraMessages );
447  $out->addWikiTextAsInterface(
448  $extraMessages->getWikiText( false, false, $this->getLanguage() )
449  );
450  }
451 
452  $out->addHTML( $injected_html );
453 
454  $helper = new LoginHelper( $this->getContext() );
455  $helper->showReturnToPage( $type, $this->mReturnTo, $this->mReturnToQuery, $this->mStickHTTPS );
456  }
457 
473  public function showReturnToPage(
474  $type, $returnTo = '', $returnToQuery = '', $stickHTTPS = false
475  ) {
476  $helper = new LoginHelper( $this->getContext() );
477  $helper->showReturnToPage( $type, $returnTo, $returnToQuery, $stickHTTPS );
478  }
479 
484  protected function setSessionUserForCurrentRequest() {
485  global $wgUser, $wgLang;
486 
488  $localContext = $this->getContext();
489  if ( $context !== $localContext ) {
490  // remove AuthManagerSpecialPage context hack
491  $this->setContext( $context );
492  }
493 
494  $user = $context->getRequest()->getSession()->getUser();
495 
496  $wgUser = $user;
497  $context->setUser( $user );
498 
499  $wgLang = $context->getLanguage();
500  }
501 
516  protected function mainLoginForm( array $requests, $msg = '', $msgtype = 'error' ) {
517  $user = $this->getUser();
518  $out = $this->getOutput();
519 
520  // FIXME how to handle empty $requests - restart, or no form, just an error message?
521  // no form would be better for no session type errors, restart is better when can* fails.
522  if ( !$requests ) {
523  $this->authAction = $this->getDefaultAction( $this->subPage );
524  $this->authForm = null;
525  $requests = AuthManager::singleton()->getAuthenticationRequests( $this->authAction, $user );
526  }
527 
528  // Generic styles and scripts for both login and signup form
529  $out->addModuleStyles( [
530  'mediawiki.ui',
531  'mediawiki.ui.button',
532  'mediawiki.ui.checkbox',
533  'mediawiki.ui.input',
534  'mediawiki.special.userlogin.common.styles'
535  ] );
536  if ( $this->isSignup() ) {
537  // XXX hack pending RL or JS parse() support for complex content messages T27349
538  $out->addJsConfigVars( 'wgCreateacctImgcaptchaHelp',
539  $this->msg( 'createacct-imgcaptcha-help' )->parse() );
540 
541  // Additional styles and scripts for signup form
542  $out->addModules( [
543  'mediawiki.special.userlogin.signup.js'
544  ] );
545  $out->addModuleStyles( [
546  'mediawiki.special.userlogin.signup.styles'
547  ] );
548  } else {
549  // Additional styles for login form
550  $out->addModuleStyles( [
551  'mediawiki.special.userlogin.login.styles'
552  ] );
553  }
554  $out->disallowUserJs(); // just in case...
555 
556  $form = $this->getAuthForm( $requests, $this->authAction, $msg, $msgtype );
557  $form->prepareForm();
558 
559  $submitStatus = Status::newGood();
560  if ( $msg && $msgtype === 'warning' ) {
561  $submitStatus->warning( $msg );
562  } elseif ( $msg && $msgtype === 'error' ) {
563  $submitStatus->fatal( $msg );
564  }
565 
566  // warning header for non-standard workflows (e.g. security reauthentication)
567  if (
568  !$this->isSignup() &&
569  $this->getUser()->isLoggedIn() &&
570  $this->authAction !== AuthManager::ACTION_LOGIN_CONTINUE
571  ) {
572  $reauthMessage = $this->securityLevel ? 'userlogin-reauth' : 'userlogin-loggedin';
573  $submitStatus->warning( $reauthMessage, $this->getUser()->getName() );
574  }
575 
576  $formHtml = $form->getHTML( $submitStatus );
577 
578  $out->addHTML( $this->getPageHtml( $formHtml ) );
579  }
580 
587  protected function getPageHtml( $formHtml ) {
589 
590  $loginPrompt = $this->isSignup() ? '' : Html::rawElement( 'div',
591  [ 'id' => 'userloginprompt' ], $this->msg( 'loginprompt' )->parseAsBlock() );
592  $languageLinks = $wgLoginLanguageSelector ? $this->makeLanguageSelector() : '';
593  $signupStartMsg = $this->msg( 'signupstart' );
594  $signupStart = ( $this->isSignup() && !$signupStartMsg->isDisabled() )
595  ? Html::rawElement( 'div', [ 'id' => 'signupstart' ], $signupStartMsg->parseAsBlock() ) : '';
596  if ( $languageLinks ) {
597  $languageLinks = Html::rawElement( 'div', [ 'id' => 'languagelinks' ],
598  Html::rawElement( 'p', [], $languageLinks )
599  );
600  }
601 
602  $benefitsContainer = '';
603  if ( $this->isSignup() && $this->showExtraInformation() ) {
604  // messages used:
605  // createacct-benefit-icon1 createacct-benefit-head1 createacct-benefit-body1
606  // createacct-benefit-icon2 createacct-benefit-head2 createacct-benefit-body2
607  // createacct-benefit-icon3 createacct-benefit-head3 createacct-benefit-body3
608  $benefitCount = 3;
609  $benefitList = '';
610  for ( $benefitIdx = 1; $benefitIdx <= $benefitCount; $benefitIdx++ ) {
611  $headUnescaped = $this->msg( "createacct-benefit-head$benefitIdx" )->text();
612  $iconClass = $this->msg( "createacct-benefit-icon$benefitIdx" )->text();
613  $benefitList .= Html::rawElement( 'div', [ 'class' => "mw-number-text $iconClass" ],
614  Html::rawElement( 'h3', [],
615  $this->msg( "createacct-benefit-head$benefitIdx" )->escaped()
616  )
617  . Html::rawElement( 'p', [],
618  $this->msg( "createacct-benefit-body$benefitIdx" )->params( $headUnescaped )->escaped()
619  )
620  );
621  }
622  $benefitsContainer = Html::rawElement( 'div', [ 'class' => 'mw-createacct-benefits-container' ],
623  Html::rawElement( 'h2', [], $this->msg( 'createacct-benefit-heading' )->escaped() )
624  . Html::rawElement( 'div', [ 'class' => 'mw-createacct-benefits-list' ],
625  $benefitList
626  )
627  );
628  }
629 
630  $html = Html::rawElement( 'div', [ 'class' => 'mw-ui-container' ],
631  $loginPrompt
632  . $languageLinks
633  . $signupStart
634  . Html::rawElement( 'div', [ 'id' => 'userloginForm' ],
635  $formHtml
636  )
637  . $benefitsContainer
638  );
639 
640  return $html;
641  }
642 
651  protected function getAuthForm( array $requests, $action, $msg = '', $msgType = 'error' ) {
652  global $wgSecureLogin;
653  // FIXME merge this with parent
654 
655  if ( isset( $this->authForm ) ) {
656  return $this->authForm;
657  }
658 
659  $usingHTTPS = $this->getRequest()->getProtocol() === 'https';
660 
661  // get basic form description from the auth logic
662  $fieldInfo = AuthenticationRequest::mergeFieldInfo( $requests );
663  // this will call onAuthChangeFormFields()
664  $formDescriptor = static::fieldInfoToFormDescriptor( $requests, $fieldInfo, $this->authAction );
665  $this->postProcessFormDescriptor( $formDescriptor, $requests );
666 
667  $context = $this->getContext();
668  if ( $context->getRequest() !== $this->getRequest() ) {
669  // We have overridden the request, need to make sure the form uses that too.
670  $context = new DerivativeContext( $this->getContext() );
671  $context->setRequest( $this->getRequest() );
672  }
673  $form = HTMLForm::factory( 'vform', $formDescriptor, $context );
674 
675  $form->addHiddenField( 'authAction', $this->authAction );
676  if ( $this->mLanguage ) {
677  $form->addHiddenField( 'uselang', $this->mLanguage );
678  }
679  $form->addHiddenField( 'force', $this->securityLevel );
680  $form->addHiddenField( $this->getTokenName(), $this->getToken()->toString() );
681  if ( $wgSecureLogin ) {
682  // If using HTTPS coming from HTTP, then the 'fromhttp' parameter must be preserved
683  if ( !$this->isSignup() ) {
684  $form->addHiddenField( 'wpForceHttps', (int)$this->mStickHTTPS );
685  $form->addHiddenField( 'wpFromhttp', $usingHTTPS );
686  }
687  }
688 
689  // set properties of the form itself
690  $form->setAction( $this->getPageTitle()->getLocalURL( $this->getReturnToQueryStringFragment() ) );
691  $form->setName( 'userlogin' . ( $this->isSignup() ? '2' : '' ) );
692  if ( $this->isSignup() ) {
693  $form->setId( 'userlogin2' );
694  }
695 
696  $form->suppressDefaultSubmit();
697 
698  $this->authForm = $form;
699 
700  return $form;
701  }
702 
703  public function onAuthChangeFormFields(
704  array $requests, array $fieldInfo, array &$formDescriptor, $action
705  ) {
706  $coreFieldDescriptors = $this->getFieldDefinitions();
707 
708  // keep the ordering from getCoreFieldDescriptors() where there is no explicit weight
709  foreach ( $coreFieldDescriptors as $fieldName => $coreField ) {
710  $requestField = $formDescriptor[$fieldName] ?? [];
711 
712  // remove everything that is not in the fieldinfo, is not marked as a supplemental field
713  // to something in the fieldinfo, and is not an info field or a submit button
714  if (
715  !isset( $fieldInfo[$fieldName] )
716  && (
717  !isset( $coreField['baseField'] )
718  || !isset( $fieldInfo[$coreField['baseField']] )
719  )
720  && (
721  !isset( $coreField['type'] )
722  || !in_array( $coreField['type'], [ 'submit', 'info' ], true )
723  )
724  ) {
725  $coreFieldDescriptors[$fieldName] = null;
726  continue;
727  }
728 
729  // core message labels should always take priority
730  if (
731  isset( $coreField['label'] )
732  || isset( $coreField['label-message'] )
733  || isset( $coreField['label-raw'] )
734  ) {
735  unset( $requestField['label'], $requestField['label-message'], $coreField['label-raw'] );
736  }
737 
738  $coreFieldDescriptors[$fieldName] += $requestField;
739  }
740 
741  $formDescriptor = array_filter( $coreFieldDescriptors + $formDescriptor );
742  return true;
743  }
744 
751  protected function showExtraInformation() {
752  return $this->authAction !== $this->getContinueAction( $this->authAction )
754  }
755 
760  protected function getFieldDefinitions() {
761  global $wgEmailConfirmToEdit;
762 
763  $isLoggedIn = $this->getUser()->isLoggedIn();
764  $continuePart = $this->isContinued() ? 'continue-' : '';
765  $anotherPart = $isLoggedIn ? 'another-' : '';
766  // @phan-suppress-next-line PhanUndeclaredMethod
767  $expiration = $this->getRequest()->getSession()->getProvider()->getRememberUserDuration();
768  $expirationDays = ceil( $expiration / ( 3600 * 24 ) );
769  $secureLoginLink = '';
770  if ( $this->mSecureLoginUrl ) {
771  $secureLoginLink = Html::element( 'a', [
772  'href' => $this->mSecureLoginUrl,
773  'class' => 'mw-ui-flush-right mw-secure',
774  ], $this->msg( 'userlogin-signwithsecure' )->text() );
775  }
776  $usernameHelpLink = '';
777  if ( !$this->msg( 'createacct-helpusername' )->isDisabled() ) {
778  $usernameHelpLink = Html::rawElement( 'span', [
779  'class' => 'mw-ui-flush-right',
780  ], $this->msg( 'createacct-helpusername' )->parse() );
781  }
782 
783  if ( $this->isSignup() ) {
784  $fieldDefinitions = [
785  'statusarea' => [
786  // used by the mediawiki.special.userlogin.signup.js module for error display
787  // FIXME merge this with HTMLForm's normal status (error) area
788  'type' => 'info',
789  'raw' => true,
790  'default' => Html::element( 'div', [ 'id' => 'mw-createacct-status-area' ] ),
791  'weight' => -105,
792  ],
793  'username' => [
794  'label-raw' => $this->msg( 'userlogin-yourname' )->escaped() . $usernameHelpLink,
795  'id' => 'wpName2',
796  'placeholder-message' => $isLoggedIn ? 'createacct-another-username-ph'
797  : 'userlogin-yourname-ph',
798  ],
799  'mailpassword' => [
800  // create account without providing password, a temporary one will be mailed
801  'type' => 'check',
802  'label-message' => 'createaccountmail',
803  'name' => 'wpCreateaccountMail',
804  'id' => 'wpCreateaccountMail',
805  ],
806  'password' => [
807  'id' => 'wpPassword2',
808  'placeholder-message' => 'createacct-yourpassword-ph',
809  'hide-if' => [ '===', 'wpCreateaccountMail', '1' ],
810  ],
811  'domain' => [],
812  'retype' => [
813  'baseField' => 'password',
814  'type' => 'password',
815  'label-message' => 'createacct-yourpasswordagain',
816  'id' => 'wpRetype',
817  'cssclass' => 'loginPassword',
818  'size' => 20,
819  'validation-callback' => function ( $value, $alldata ) {
820  if ( empty( $alldata['mailpassword'] ) && !empty( $alldata['password'] ) ) {
821  if ( !$value ) {
822  return $this->msg( 'htmlform-required' );
823  } elseif ( $value !== $alldata['password'] ) {
824  return $this->msg( 'badretype' );
825  }
826  }
827  return true;
828  },
829  'hide-if' => [ '===', 'wpCreateaccountMail', '1' ],
830  'placeholder-message' => 'createacct-yourpasswordagain-ph',
831  ],
832  'email' => [
833  'type' => 'email',
834  'label-message' => $wgEmailConfirmToEdit ? 'createacct-emailrequired'
835  : 'createacct-emailoptional',
836  'id' => 'wpEmail',
837  'cssclass' => 'loginText',
838  'size' => '20',
839  // FIXME will break non-standard providers
840  'required' => $wgEmailConfirmToEdit,
841  'validation-callback' => function ( $value, $alldata ) {
842  global $wgEmailConfirmToEdit;
843 
844  // AuthManager will check most of these, but that will make the auth
845  // session fail and this won't, so nicer to do it this way
846  if ( !$value && $wgEmailConfirmToEdit ) {
847  // no point in allowing registration without email when email is
848  // required to edit
849  return $this->msg( 'noemailtitle' );
850  } elseif ( !$value && !empty( $alldata['mailpassword'] ) ) {
851  // cannot send password via email when there is no email address
852  return $this->msg( 'noemailcreate' );
853  } elseif ( $value && !Sanitizer::validateEmail( $value ) ) {
854  return $this->msg( 'invalidemailaddress' );
855  }
856  return true;
857  },
858  'placeholder-message' => 'createacct-' . $anotherPart . 'email-ph',
859  ],
860  'realname' => [
861  'type' => 'text',
862  'help-message' => $isLoggedIn ? 'createacct-another-realname-tip'
863  : 'prefs-help-realname',
864  'label-message' => 'createacct-realname',
865  'cssclass' => 'loginText',
866  'size' => 20,
867  'id' => 'wpRealName',
868  ],
869  'reason' => [
870  // comment for the user creation log
871  'type' => 'text',
872  'label-message' => 'createacct-reason',
873  'cssclass' => 'loginText',
874  'id' => 'wpReason',
875  'size' => '20',
876  'placeholder-message' => 'createacct-reason-ph',
877  ],
878  'createaccount' => [
879  // submit button
880  'type' => 'submit',
881  'default' => $this->msg( 'createacct-' . $anotherPart . $continuePart .
882  'submit' )->text(),
883  'name' => 'wpCreateaccount',
884  'id' => 'wpCreateaccount',
885  'weight' => 100,
886  ],
887  ];
888  } else {
889  $fieldDefinitions = [
890  'username' => [
891  'label-raw' => $this->msg( 'userlogin-yourname' )->escaped() . $secureLoginLink,
892  'id' => 'wpName1',
893  'placeholder-message' => 'userlogin-yourname-ph',
894  ],
895  'password' => [
896  'id' => 'wpPassword1',
897  'placeholder-message' => 'userlogin-yourpassword-ph',
898  ],
899  'domain' => [],
900  'rememberMe' => [
901  // option for saving the user token to a cookie
902  'type' => 'check',
903  'name' => 'wpRemember',
904  'label-message' => $this->msg( 'userlogin-remembermypassword' )
905  ->numParams( $expirationDays ),
906  'id' => 'wpRemember',
907  ],
908  'loginattempt' => [
909  // submit button
910  'type' => 'submit',
911  'default' => $this->msg( 'pt-login-' . $continuePart . 'button' )->text(),
912  'id' => 'wpLoginAttempt',
913  'weight' => 100,
914  ],
915  'linkcontainer' => [
916  // help link
917  'type' => 'info',
918  'cssclass' => 'mw-form-related-link-container mw-userlogin-help',
919  // 'id' => 'mw-userlogin-help', // FIXME HTMLInfoField ignores this
920  'raw' => true,
921  'default' => Html::element( 'a', [
922  'href' => Skin::makeInternalOrExternalUrl( $this->msg( 'helplogin-url' )
923  ->inContentLanguage()
924  ->text() ),
925  ], $this->msg( 'userlogin-helplink2' )->text() ),
926  'weight' => 200,
927  ],
928  // button for ResetPasswordSecondaryAuthenticationProvider
929  'skipReset' => [
930  'weight' => 110,
931  'flags' => [],
932  ],
933  ];
934  }
935 
936  $fieldDefinitions['username'] += [
937  'type' => 'text',
938  'name' => 'wpName',
939  'cssclass' => 'loginText',
940  'size' => 20,
941  // 'required' => true,
942  ];
943  $fieldDefinitions['password'] += [
944  'type' => 'password',
945  // 'label-message' => 'userlogin-yourpassword', // would override the changepassword label
946  'name' => 'wpPassword',
947  'cssclass' => 'loginPassword',
948  'size' => 20,
949  // 'required' => true,
950  ];
951 
952  if ( $this->mEntryError ) {
953  $fieldDefinitions['entryError'] = [
954  'type' => 'info',
955  'default' => Html::rawElement( 'div', [ 'class' => $this->mEntryErrorType . 'box', ],
956  $this->mEntryError ),
957  'raw' => true,
958  'rawrow' => true,
959  'weight' => -100,
960  ];
961  }
962  if ( !$this->showExtraInformation() ) {
963  unset( $fieldDefinitions['linkcontainer'], $fieldDefinitions['signupend'] );
964  }
965  if ( $this->isSignup() && $this->showExtraInformation() ) {
966  // blank signup footer for site customization
967  // uses signupend-https for HTTPS requests if it's not blank, signupend otherwise
968  $signupendMsg = $this->msg( 'signupend' );
969  $signupendHttpsMsg = $this->msg( 'signupend-https' );
970  if ( !$signupendMsg->isDisabled() ) {
971  $usingHTTPS = $this->getRequest()->getProtocol() === 'https';
972  $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
973  ? $signupendHttpsMsg->parse() : $signupendMsg->parse();
974  $fieldDefinitions['signupend'] = [
975  'type' => 'info',
976  'raw' => true,
977  'default' => Html::rawElement( 'div', [ 'id' => 'signupend' ], $signupendText ),
978  'weight' => 225,
979  ];
980  }
981  }
982  if ( !$this->isSignup() && $this->showExtraInformation() ) {
983  $passwordReset = MediaWikiServices::getInstance()->getPasswordReset();
984  if ( $passwordReset->isAllowed( $this->getUser() )->isGood() ) {
985  $fieldDefinitions['passwordReset'] = [
986  'type' => 'info',
987  'raw' => true,
988  'cssclass' => 'mw-form-related-link-container',
989  'default' => $this->getLinkRenderer()->makeLink(
990  SpecialPage::getTitleFor( 'PasswordReset' ),
991  $this->msg( 'userlogin-resetpassword-link' )->text()
992  ),
993  'weight' => 230,
994  ];
995  }
996 
997  // Don't show a "create account" link if the user can't.
998  if ( $this->showCreateAccountLink() ) {
999  // link to the other action
1000  $linkTitle = $this->getTitleFor( $this->isSignup() ? 'Userlogin' : 'CreateAccount' );
1001  $linkq = $this->getReturnToQueryStringFragment();
1002  // Pass any language selection on to the mode switch link
1003  if ( $this->mLanguage ) {
1004  $linkq .= '&uselang=' . urlencode( $this->mLanguage );
1005  }
1006  $loggedIn = $this->getUser()->isLoggedIn();
1007 
1008  $fieldDefinitions['createOrLogin'] = [
1009  'type' => 'info',
1010  'raw' => true,
1011  'linkQuery' => $linkq,
1012  'default' => function ( $params ) use ( $loggedIn, $linkTitle ) {
1013  return Html::rawElement( 'div',
1014  [ 'id' => 'mw-createaccount' . ( !$loggedIn ? '-cta' : '' ),
1015  'class' => ( $loggedIn ? 'mw-form-related-link-container' : 'mw-ui-vform-field' ) ],
1016  ( $loggedIn ? '' : $this->msg( 'userlogin-noaccount' )->escaped() )
1017  . Html::element( 'a',
1018  [
1019  'id' => 'mw-createaccount-join' . ( $loggedIn ? '-loggedin' : '' ),
1020  'href' => $linkTitle->getLocalURL( $params['linkQuery'] ),
1021  'class' => ( $loggedIn ? '' : 'mw-ui-button' ),
1022  'tabindex' => 100,
1023  ],
1024  $this->msg(
1025  $loggedIn ? 'userlogin-createanother' : 'userlogin-joinproject'
1026  )->text()
1027  )
1028  );
1029  },
1030  'weight' => 235,
1031  ];
1032  }
1033  }
1034 
1035  return $fieldDefinitions;
1036  }
1037 
1047  protected function hasSessionCookie() {
1049 
1050  return $wgDisableCookieCheck || (
1052  $this->getRequest()->getSession()->getId() === (string)$wgInitialSessionId
1053  );
1054  }
1055 
1061  protected function getReturnToQueryStringFragment() {
1062  $returnto = '';
1063  if ( $this->mReturnTo !== '' ) {
1064  $returnto = 'returnto=' . wfUrlencode( $this->mReturnTo );
1065  if ( $this->mReturnToQuery !== '' ) {
1066  $returnto .= '&returntoquery=' . wfUrlencode( $this->mReturnToQuery );
1067  }
1068  }
1069  return $returnto;
1070  }
1071 
1077  private function showCreateAccountLink() {
1078  if ( $this->isSignup() ) {
1079  return true;
1080  } elseif ( MediaWikiServices::getInstance()
1082  ->userHasRight( $this->getUser(), 'createaccount' )
1083  ) {
1084  return true;
1085  } else {
1086  return false;
1087  }
1088  }
1089 
1090  protected function getTokenName() {
1091  return $this->isSignup() ? 'wpCreateaccountToken' : 'wpLoginToken';
1092  }
1093 
1100  protected function makeLanguageSelector() {
1101  $msg = $this->msg( 'loginlanguagelinks' )->inContentLanguage();
1102  if ( $msg->isBlank() ) {
1103  return '';
1104  }
1105  $langs = explode( "\n", $msg->text() );
1106  $links = [];
1107  foreach ( $langs as $lang ) {
1108  $lang = trim( $lang, '* ' );
1109  $parts = explode( '|', $lang );
1110  if ( count( $parts ) >= 2 ) {
1111  $links[] = $this->makeLanguageSelectorLink( $parts[0], trim( $parts[1] ) );
1112  }
1113  }
1114 
1115  return count( $links ) > 0 ? $this->msg( 'loginlanguagelabel' )->rawParams(
1116  $this->getLanguage()->pipeList( $links ) )->escaped() : '';
1117  }
1118 
1127  protected function makeLanguageSelectorLink( $text, $lang ) {
1128  if ( $this->getLanguage()->getCode() == $lang ) {
1129  // no link for currently used language
1130  return htmlspecialchars( $text );
1131  }
1132  $query = [ 'uselang' => $lang ];
1133  if ( $this->mReturnTo !== '' ) {
1134  $query['returnto'] = $this->mReturnTo;
1135  $query['returntoquery'] = $this->mReturnToQuery;
1136  }
1137 
1138  $attr = [];
1139  $targetLanguage = MediaWikiServices::getInstance()->getLanguageFactory()
1140  ->getLanguage( $lang );
1141  $attr['lang'] = $attr['hreflang'] = $targetLanguage->getHtmlCode();
1142 
1143  return $this->getLinkRenderer()->makeKnownLink(
1144  $this->getPageTitle(),
1145  $text,
1146  $attr,
1147  $query
1148  );
1149  }
1150 
1151  protected function getGroupName() {
1152  return 'login';
1153  }
1154 
1159  protected function postProcessFormDescriptor( &$formDescriptor, $requests ) {
1160  // Pre-fill username (if not creating an account, T46775).
1161  if (
1162  isset( $formDescriptor['username'] ) &&
1163  !isset( $formDescriptor['username']['default'] ) &&
1164  !$this->isSignup()
1165  ) {
1166  $user = $this->getUser();
1167  if ( $user->isLoggedIn() ) {
1168  $formDescriptor['username']['default'] = $user->getName();
1169  } else {
1170  $formDescriptor['username']['default'] =
1171  $this->getRequest()->getSession()->suggestLoginUsername();
1172  }
1173  }
1174 
1175  // don't show a submit button if there is nothing to submit (i.e. the only form content
1176  // is other submit buttons, for redirect flows)
1177  if ( !$this->needsSubmitButton( $requests ) ) {
1178  unset( $formDescriptor['createaccount'], $formDescriptor['loginattempt'] );
1179  }
1180 
1181  if ( !$this->isSignup() ) {
1182  // FIXME HACK don't focus on non-empty field
1183  // maybe there should be an autofocus-if similar to hide-if?
1184  if (
1185  isset( $formDescriptor['username'] )
1186  && empty( $formDescriptor['username']['default'] )
1187  && !$this->getRequest()->getCheck( 'wpName' )
1188  ) {
1189  $formDescriptor['username']['autofocus'] = true;
1190  } elseif ( isset( $formDescriptor['password'] ) ) {
1191  $formDescriptor['password']['autofocus'] = true;
1192  }
1193  }
1194 
1195  $this->addTabIndex( $formDescriptor );
1196  }
1197 }
LoginSignupSpecialPage\getTokenName
getTokenName()
Returns the name of the CSRF token (under which it should be found in the POST or GET data).
Definition: LoginSignupSpecialPage.php:1090
SpecialPage\getPageTitle
getPageTitle( $subpage=false)
Get a self-referential title object.
Definition: SpecialPage.php:672
LoginSignupSpecialPage\$mEntryErrorType
$mEntryErrorType
Definition: LoginSignupSpecialPage.php:47
LoginSignupSpecialPage\setRequest
setRequest(array $data, $wasPosted=null)
Override the POST data, GET data from the real request is preserved.
Definition: LoginSignupSpecialPage.php:91
SpecialPage\msg
msg( $key,... $params)
Wrapper around wfMessage that sets the current context.
Definition: SpecialPage.php:792
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:317
LoginSignupSpecialPage\postProcessFormDescriptor
postProcessFormDescriptor(&$formDescriptor, $requests)
Definition: LoginSignupSpecialPage.php:1159
wfCanIPUseHTTPS
wfCanIPUseHTTPS( $ip)
Determine whether the client at a given source IP is likely to be able to access the wiki via HTTPS.
Definition: GlobalFunctions.php:2935
StatusValue\newFatal
static newFatal( $message,... $parameters)
Factory function for fatal errors.
Definition: StatusValue.php:69
LoginSignupSpecialPage\__construct
__construct( $name)
Definition: LoginSignupSpecialPage.php:83
AuthManagerSpecialPage\addTabIndex
addTabIndex(&$formDescriptor)
Adds a sequential tabindex starting from 1 to all form elements.
Definition: AuthManagerSpecialPage.php:605
$response
$response
Definition: opensearch_desc.php:38
SpecialPage\getOutput
getOutput()
Get the OutputPage being used for this instance.
Definition: SpecialPage.php:719
LoginSignupSpecialPage\$mReturnTo
$mReturnTo
Definition: LoginSignupSpecialPage.php:38
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:130
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:35
LoginSignupSpecialPage\showSuccessPage
showSuccessPage( $type, $title, $msgname, $injected_html, $extraMessages)
Show the success page.
Definition: LoginSignupSpecialPage.php:437
LoginSignupSpecialPage\$mReturnToQuery
$mReturnToQuery
Definition: LoginSignupSpecialPage.php:42
true
return true
Definition: router.php:92
LoginSignupSpecialPage\showCreateAccountLink
showCreateAccountLink()
Whether the login/create account form should display a link to the other form (in addition to whateve...
Definition: LoginSignupSpecialPage.php:1077
LoginSignupSpecialPage\load
load( $subPage)
Load data from request.
Definition: LoginSignupSpecialPage.php:122
$wgUseMediaWikiUIEverywhere
$wgUseMediaWikiUIEverywhere
Temporary variable that applies MediaWiki UI wherever it can be supported.
Definition: DefaultSettings.php:3288
wfUrlencode
wfUrlencode( $s)
We want some things to be included as literal characters in our title URLs for prettiness,...
Definition: GlobalFunctions.php:309
SpecialPage\checkPermissions
checkPermissions()
Checks if userCanExecute, and if not throws a PermissionsError.
Definition: SpecialPage.php:315
LoginSignupSpecialPage\makeLanguageSelectorLink
makeLanguageSelectorLink( $text, $lang)
Create a language selector link for a particular language Links back to this page preserving type and...
Definition: LoginSignupSpecialPage.php:1127
LoginSignupSpecialPage\beforeExecute
beforeExecute( $subPage)
Gets called before.
Definition: LoginSignupSpecialPage.php:202
User\newFromName
static newFromName( $name, $validate='valid')
Static factory method for creation from username.
Definition: User.php:537
LoginSignupSpecialPage\$mStickHTTPS
$mStickHTTPS
Definition: LoginSignupSpecialPage.php:44
SpecialPage\getTitleFor
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,...
Definition: SpecialPage.php:83
SpecialPage\getLanguage
getLanguage()
Shortcut to get user's language.
Definition: SpecialPage.php:749
$success
$success
Definition: NoLocalSettings.php:42
SpecialPage\getName
getName()
Get the name of this Special Page.
Definition: SpecialPage.php:153
AuthManagerSpecialPage
A special page subclass for authentication-related special pages.
Definition: AuthManagerSpecialPage.php:14
LoginSignupSpecialPage\setSessionUserForCurrentRequest
setSessionUserForCurrentRequest()
Replace some globals to make sure the fact that the user has just been logged in is reflected in the ...
Definition: LoginSignupSpecialPage.php:484
LoginHelper
Helper functions for the login form that need to be shared with other special pages (such as CentralA...
Definition: LoginHelper.php:8
LoginSignupSpecialPage\getReturnToQueryStringFragment
getReturnToQueryStringFragment()
Returns a string that can be appended to the URL (without encoding) to preserve the return target.
Definition: LoginSignupSpecialPage.php:1061
AuthManagerSpecialPage\trySubmit
trySubmit()
Attempts to do an authentication step with the submitted data.
Definition: AuthManagerSpecialPage.php:398
wfAppendQuery
wfAppendQuery( $url, $query)
Append a query string to an existing URL, which may or may not already have query string parameters a...
Definition: GlobalFunctions.php:439
AuthManagerSpecialPage\$subPage
string $subPage
Subpage of the special page.
Definition: AuthManagerSpecialPage.php:35
LoginSignupSpecialPage\$mEntryError
$mEntryError
Definition: LoginSignupSpecialPage.php:46
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:30
$wgLoginLanguageSelector
$wgLoginLanguageSelector
Show a bar of language selection links in the user login and user registration forms; edit the "login...
Definition: DefaultSettings.php:3179
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
getPermissionManager
getPermissionManager()
Status\wrap
static wrap( $sv)
Succinct helper method to wrap a StatusValue.
Definition: Status.php:58
LoginSignupSpecialPage\logAuthResult
logAuthResult( $success, $status=null)
Logs to the authmanager-stats channel.
LoginSignupSpecialPage
Holds shared logic for login and account creation pages.
Definition: LoginSignupSpecialPage.php:37
SpecialPage\getFullTitle
getFullTitle()
Return the full title, including $par.
Definition: SpecialPage.php:768
LoginSignupSpecialPage\$proxyAccountCreation
bool $proxyAccountCreation
True if the user if creating an account for someone else.
Definition: LoginSignupSpecialPage.php:59
MediaWiki\Auth\AuthenticationResponse
This is a value object to hold authentication response data.
Definition: AuthenticationResponse.php:37
$wgLang
$wgLang
Definition: Setup.php:842
AuthManagerSpecialPage\loadAuth
loadAuth( $subPage, $authAction=null, $reset=false)
Load or initialize $authAction, $authRequests and $subPage.
Definition: AuthManagerSpecialPage.php:232
LoginSignupSpecialPage\$mPosted
$mPosted
Definition: LoginSignupSpecialPage.php:39
LoginSignupSpecialPage\mainLoginForm
mainLoginForm(array $requests, $msg='', $msgtype='error')
Definition: LoginSignupSpecialPage.php:516
$title
$title
Definition: testCompression.php:36
SpecialPage\setHeaders
setHeaders()
Sets headers - this should be called from the execute() method of all derived classes!
Definition: SpecialPage.php:537
SpecialPage\getUser
getUser()
Shortcut to get the User executing this instance.
Definition: SpecialPage.php:729
LoginSignupSpecialPage\makeLanguageSelector
makeLanguageSelector()
Produce a bar of links which allow the user to select another language during login/registration but ...
Definition: LoginSignupSpecialPage.php:1100
LoginSignupSpecialPage\hasSessionCookie
hasSessionCookie()
Check if a session cookie is present.
Definition: LoginSignupSpecialPage.php:1047
LoginSignupSpecialPage\loadRequestParameters
loadRequestParameters()
Load basic request parameters for this Special page.
Definition: LoginSignupSpecialPage.php:99
LoginSignupSpecialPage\$mFromHTTP
$mFromHTTP
Definition: LoginSignupSpecialPage.php:45
PROTO_HTTPS
const PROTO_HTTPS
Definition: Defines.php:200
SpecialPage\getContext
getContext()
Gets the context this SpecialPage is executed in.
Definition: SpecialPage.php:692
LoginSignupSpecialPage\$mLoaded
$mLoaded
Definition: LoginSignupSpecialPage.php:49
StatusValue\newGood
static newGood( $value=null)
Factory function for good results.
Definition: StatusValue.php:81
LoginSignupSpecialPage\$mAction
$mAction
Definition: LoginSignupSpecialPage.php:40
MediaWiki\Session\SessionManager
This serves as the entry point to the MediaWiki session handling system.
Definition: SessionManager.php:50
LoginSignupSpecialPage\canBypassForm
canBypassForm(&$button_name)
Determine if the login form can be bypassed.
Definition: LoginSignupSpecialPage.php:401
LoginSignupSpecialPage\$mLanguage
$mLanguage
Definition: LoginSignupSpecialPage.php:41
LoginSignupSpecialPage\$mToken
$mToken
Definition: LoginSignupSpecialPage.php:43
wfEscapeWikiText
wfEscapeWikiText( $text)
Escapes the given text so that it may be output using addWikiText() without any linking,...
Definition: GlobalFunctions.php:1550
LoginSignupSpecialPage\$authForm
HTMLForm $authForm
Definition: LoginSignupSpecialPage.php:64
LoginSignupSpecialPage\getPageHtml
getPageHtml( $formHtml)
Add page elements which are outside the form.
Definition: LoginSignupSpecialPage.php:587
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:447
AuthManagerSpecialPage\getDefaultAction
getDefaultAction( $subPage)
Get the default action for this special page, if none is given via URL/POST data.
MediaWiki\Auth\AuthManager
This serves as the entry point to the authentication system.
Definition: AuthManager.php:85
AuthManagerSpecialPage\getContinueAction
getContinueAction( $action)
Gets the _CONTINUE version of an action.
Definition: AuthManagerSpecialPage.php:280
$wgEmailConfirmToEdit
$wgEmailConfirmToEdit
Should editors be required to have a validated e-mail address before being allowed to edit?
Definition: DefaultSettings.php:5084
$context
$context
Definition: load.php:40
LoginSignupSpecialPage\isSignup
isSignup()
SpecialPage\getLinkRenderer
getLinkRenderer()
Definition: SpecialPage.php:904
$wgDisableCookieCheck
$wgDisableCookieCheck
By default, MediaWiki checks if the client supports cookies during the login process,...
Definition: DefaultSettings.php:6048
AuthManagerSpecialPage\isActionAllowed
isActionAllowed( $action)
Checks whether AuthManager is ready to perform the action.
Definition: AuthManagerSpecialPage.php:303
LoginSignupSpecialPage\getGroupName
getGroupName()
Under which header this special page is listed in Special:SpecialPages See messages 'specialpages-gro...
Definition: LoginSignupSpecialPage.php:1151
LoginSignupSpecialPage\showReturnToPage
showReturnToPage( $type, $returnTo='', $returnToQuery='', $stickHTTPS=false)
Add a "return to" link or redirect to it.
Definition: LoginSignupSpecialPage.php:473
AuthManagerSpecialPage\needsSubmitButton
needsSubmitButton(array $requests)
Returns true if the form built from the given AuthenticationRequests needs a submit button.
Definition: AuthManagerSpecialPage.php:567
SpecialPage\setContext
setContext( $context)
Sets the context this SpecialPage is executed in.
Definition: SpecialPage.php:682
LoginSignupSpecialPage\getPreservedParams
getPreservedParams( $withToken=false)
Returns URL query parameters which can be used to reload the page (or leave and return) while preserv...
Definition: LoginSignupSpecialPage.php:188
AuthManagerSpecialPage\isContinued
isContinued()
Returns true if this is not the first step of the authentication.
Definition: AuthManagerSpecialPage.php:267
AuthManagerSpecialPage\getRequest
getRequest()
Get the WebRequest being used for this instance.
Definition: AuthManagerSpecialPage.php:64
LoginSignupSpecialPage\$mLoadedRequest
$mLoadedRequest
Definition: LoginSignupSpecialPage.php:50
AuthManagerSpecialPage\getToken
getToken()
Returns the CSRF token.
Definition: AuthManagerSpecialPage.php:625
LoginSignupSpecialPage\$mSecureLoginUrl
$mSecureLoginUrl
Definition: LoginSignupSpecialPage.php:51
LoginSignupSpecialPage\$targetUser
User $targetUser
FIXME another flag for passing data.
Definition: LoginSignupSpecialPage.php:61
LoginSignupSpecialPage\execute
execute( $subPage)
Definition: LoginSignupSpecialPage.php:212
LoginSignupSpecialPage\successfulAction
successfulAction( $direct=false, $extraMessages=null)
LoginSignupSpecialPage\$securityLevel
string $securityLevel
Definition: LoginSignupSpecialPage.php:54
LoginSignupSpecialPage\onAuthChangeFormFields
onAuthChangeFormFields(array $requests, array $fieldInfo, array &$formDescriptor, $action)
Change the form descriptor that determines how a field will look in the authentication form.
Definition: LoginSignupSpecialPage.php:703
ErrorPageError
An error page which can definitely be safely rendered using the OutputPage.
Definition: ErrorPageError.php:27
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:52
LoginHelper\getValidErrorMessages
static getValidErrorMessages()
Returns an array of all valid error messages.
Definition: LoginHelper.php:37
$wgSecureLogin
$wgSecureLogin
This is to let user authenticate using https when they come from http.
Definition: DefaultSettings.php:4934
LoginSignupSpecialPage\showExtraInformation
showExtraInformation()
Show extra information such as password recovery information, link from login to signup,...
Definition: LoginSignupSpecialPage.php:751
HTMLForm\factory
static factory( $displayFormat,... $arguments)
Construct a HTMLForm object for given display type.
Definition: HTMLForm.php:307
$wgInitialSessionId
$wgInitialSessionId
Definition: Setup.php:771
MediaWiki\Auth\AuthenticationRequest
This is a value object for authentication requests.
Definition: AuthenticationRequest.php:37
LoginSignupSpecialPage\getAuthForm
getAuthForm(array $requests, $action, $msg='', $msgType='error')
Generates a form from the given request.
Definition: LoginSignupSpecialPage.php:651
Skin\makeInternalOrExternalUrl
static makeInternalOrExternalUrl( $name)
If url string starts with http, consider as external URL, else internal.
Definition: Skin.php:1222
LoginSignupSpecialPage\getFieldDefinitions
getFieldDefinitions()
Create a HTMLForm descriptor for the core login fields.
Definition: LoginSignupSpecialPage.php:760
HTMLForm
Object handling generic submission, CSRF protection, layout and other logic for UI forms in a reusabl...
Definition: HTMLForm.php:131
$type
$type
Definition: testCompression.php:50