Merge "Make login/signup footer available to AuthChangeFormFields hook"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 23 Aug 2016 15:25:13 +0000 (15:25 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 23 Aug 2016 15:25:13 +0000 (15:25 +0000)
1  2 
includes/specialpage/LoginSignupSpecialPage.php

@@@ -585,7 -585,7 +585,7 @@@ abstract class LoginSignupSpecialPage e
                $this->fakeTemplate = $fakeTemplate; // FIXME there should be a saner way to pass this to the hook
                // this will call onAuthChangeFormFields()
                $formDescriptor = static::fieldInfoToFormDescriptor( $requests, $fieldInfo, $this->authAction );
 -              $this->postProcessFormDescriptor( $formDescriptor );
 +              $this->postProcessFormDescriptor( $formDescriptor, $requests );
  
                $context = $this->getContext();
                if ( $context->getRequest() !== $this->getRequest() ) {
                        $form->setId( 'userlogin2' );
                }
  
-               // add pre/post text
-               // header used by ConfirmEdit, CondfirmAccount, Persona, WikimediaIncubator, SemanticSignup
-               // should be above the error message but HTMLForm doesn't support that
-               $form->addHeaderText( $fakeTemplate->get( 'header' ) );
-               // FIXME the old form used this for error/warning messages which does not play well with
-               // HTMLForm (maybe it could with a subclass?); for now only display it for signups
-               // (where the JS username validation needs it) and alway empty
-               if ( $this->isSignup() ) {
-                       // used by the mediawiki.special.userlogin.signup.js module
-                       $statusAreaAttribs = [ 'id' => 'mw-createacct-status-area' ];
-                       // $statusAreaAttribs += $msg ? [ 'class' => "{$msgType}box" ] : [ 'style' => 'display: none;' ];
-                       $form->addHeaderText( Html::element( 'div', $statusAreaAttribs ) );
-               }
-               // header used by MobileFrontend
-               $form->addHeaderText( $fakeTemplate->get( 'formheader' ) );
-               // blank signup footer for site customization
-               if ( $this->isSignup() && $this->showExtraInformation() ) {
-                       // Use signupend-https for HTTPS requests if it's not blank, signupend otherwise
-                       $signupendMsg = $this->msg( 'signupend' );
-                       $signupendHttpsMsg = $this->msg( 'signupend-https' );
-                       if ( !$signupendMsg->isDisabled() ) {
-                               $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
-                                       ? $signupendHttpsMsg ->parse() : $signupendMsg->parse();
-                               $form->addPostText( Html::rawElement( 'div', [ 'id' => 'signupend' ], $signupendText ) );
-                       }
-               }
                // warning header for non-standard workflows (e.g. security reauthentication)
                if ( !$this->isSignup() && $this->getUser()->isLoggedIn() ) {
                        $reauthMessage = $this->securityLevel ? 'userlogin-reauth' : 'userlogin-loggedin';
                                $this->msg( $reauthMessage )->params( $this->getUser()->getName() )->parse() ) );
                }
  
-               if ( !$this->isSignup() && $this->showExtraInformation() ) {
-                       $passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
-                       if ( $passwordReset->isAllowed( $this->getUser() ) ) {
-                               $form->addFooterText( Html::rawElement(
-                                       'div',
-                                       [ 'class' => 'mw-ui-vform-field mw-form-related-link-container' ],
-                                       Linker::link(
-                                               SpecialPage::getTitleFor( 'PasswordReset' ),
-                                               $this->msg( 'userlogin-resetpassword-link' )->escaped()
-                                       )
-                               ) );
-                       }
-                       // Don't show a "create account" link if the user can't.
-                       if ( $this->showCreateAccountLink() ) {
-                               // link to the other action
-                               $linkTitle = $this->getTitleFor( $this->isSignup() ? 'Userlogin' :'CreateAccount' );
-                               $linkq = $this->getReturnToQueryStringFragment();
-                               // Pass any language selection on to the mode switch link
-                               if ( $wgLoginLanguageSelector && $this->mLanguage ) {
-                                       $linkq .= '&uselang=' . $this->mLanguage;
-                               }
-                               $loggedIn = $this->getUser()->isLoggedIn();
-                               $createOrLoginHtml = Html::rawElement( 'div',
-                                       [ 'id' => 'mw-createaccount' . ( !$loggedIn ? '-cta' : '' ),
-                                               'class' => ( $loggedIn ? 'mw-form-related-link-container' : 'mw-ui-vform-field' ) ],
-                                       ( $loggedIn ? '' : $this->msg( 'userlogin-noaccount' )->escaped() )
-                                       . Html::element( 'a',
-                                               [
-                                                       'id' => 'mw-createaccount-join' . ( $loggedIn ? '-loggedin' : '' ),
-                                                       'href' => $linkTitle->getLocalURL( $linkq ),
-                                                       'class' => ( $loggedIn ? '' : 'mw-ui-button' ),
-                                                       'tabindex' => 100,
-                                               ],
-                                               $this->msg(
-                                                       ( $this->getUser()->isLoggedIn() ?
-                                                               'userlogin-createanother' :
-                                                               'userlogin-joinproject'
-                                                       ) )->escaped()
-                                       )
-                               );
-                               $form->addFooterText( $createOrLoginHtml );
-                       }
-               }
                $form->suppressDefaultSubmit();
  
                $this->authForm = $form;
                array $requests, array $fieldInfo, array &$formDescriptor, $action
        ) {
                $coreFieldDescriptors = $this->getFieldDefinitions( $this->fakeTemplate );
-               $specialFields = array_merge( [ 'extraInput', 'linkcontainer', 'entryError' ],
+               $specialFields = array_merge( [ 'extraInput' ],
                        array_keys( $this->fakeTemplate->getExtraInputDefinitions() ) );
  
                // keep the ordering from getCoreFieldDescriptors() where there is no explicit weight
                                $formDescriptor[$fieldName] : [];
  
                        // remove everything that is not in the fieldinfo, is not marked as a supplemental field
-                       // to something in the fieldinfo, and is not a generic or B/C field or a submit button
+                       // to something in the fieldinfo, is not B/C for the pre-AuthManager templates,
+                       // and is not an info field or a submit button
                        if (
                                !isset( $fieldInfo[$fieldName] )
                                && (
                                        !isset( $coreField['baseField'] )
                                        || !isset( $fieldInfo[$coreField['baseField']] )
-                               ) && !in_array( $fieldName, $specialFields, true )
-                               && ( !isset( $coreField['type'] ) || $coreField['type'] !== 'submit' )
+                               )
+                               && !in_array( $fieldName, $specialFields, true )
+                               && (
+                                       !isset( $coreField['type'] )
+                                       || !in_array( $coreField['type'], [ 'submit', 'info' ], true )
+                               )
                        ) {
                                $coreFieldDescriptors[$fieldName] = null;
                                continue;
         * @return array
         */
        protected function getFieldDefinitions( $template ) {
-               global $wgEmailConfirmToEdit;
+               global $wgEmailConfirmToEdit, $wgLoginLanguageSelector;
  
                $isLoggedIn = $this->getUser()->isLoggedIn();
                $continuePart = $this->isContinued() ? 'continue-' : '';
                $anotherPart = $isLoggedIn ? 'another-' : '';
-               $expiration = $this->getRequest()->getSession()->getProvider()
-                       ->getRememberUserDuration();
+               $expiration = $this->getRequest()->getSession()->getProvider()->getRememberUserDuration();
                $expirationDays = ceil( $expiration / ( 3600 * 24 ) );
                $secureLoginLink = '';
                if ( $this->mSecureLoginUrl ) {
  
                if ( $this->isSignup() ) {
                        $fieldDefinitions = [
+                               'statusarea' => [
+                                       // used by the mediawiki.special.userlogin.signup.js module for error display
+                                       // FIXME merge this with HTMLForm's normal status (error) area
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'default' => Html::element( 'div', [ 'id' => 'mw-createacct-status-area' ] ),
+                                       'weight' => -105,
+                               ],
                                'username' => [
                                        'label-message' => 'userlogin-yourname',
                                        // FIXME help-message does not match old formatting
                                ],
                        ];
                }
                $fieldDefinitions['username'] += [
                        'type' => 'text',
                        'name' => 'wpName',
                        // 'required' => true,
                ];
  
+               if ( $template->get( 'header' ) || $template->get( 'formheader' ) ) {
+                       // B/C for old extensions that haven't been converted to AuthManager (or have been
+                       // but somebody is using the old version) and still use templates via the
+                       // UserCreateForm/UserLoginForm hook.
+                       // 'header' used by ConfirmEdit, CondfirmAccount, Persona, WikimediaIncubator, SemanticSignup
+                       // 'formheader' used by MobileFrontend
+                       $fieldDefinitions['header'] = [
+                               'type' => 'info',
+                               'raw' => true,
+                               'default' => $template->get( 'header' ) ?: $template->get( 'formheader' ),
+                               'weight' => - 110,
+                       ];
+               }
                if ( $this->mEntryError ) {
                        $fieldDefinitions['entryError'] = [
                                'type' => 'info',
                                'weight' => -100,
                        ];
                }
                if ( !$this->showExtraInformation() ) {
-                       unset( $fieldDefinitions['linkcontainer'] );
+                       unset( $fieldDefinitions['linkcontainer'], $fieldDefinitions['signupend'] );
+               }
+               if ( $this->isSignup() && $this->showExtraInformation() ) {
+                       // blank signup footer for site customization
+                       // uses signupend-https for HTTPS requests if it's not blank, signupend otherwise
+                       $signupendMsg = $this->msg( 'signupend' );
+                       $signupendHttpsMsg = $this->msg( 'signupend-https' );
+                       if ( !$signupendMsg->isDisabled() ) {
+                               $usingHTTPS = $this->getRequest()->getProtocol() === 'https';
+                               $signupendText = ( $usingHTTPS && !$signupendHttpsMsg->isBlank() )
+                                       ? $signupendHttpsMsg ->parse() : $signupendMsg->parse();
+                               $fieldDefinitions['signupend'] = [
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'default' => Html::rawElement( 'div', [ 'id' => 'signupend' ], $signupendText ),
+                                       'weight' => 225,
+                               ];
+                       }
+               }
+               if ( !$this->isSignup() && $this->showExtraInformation() ) {
+                       $passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
+                       if ( $passwordReset->isAllowed( $this->getUser() ) ) {
+                               $fieldDefinitions['passwordReset'] = [
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'cssclass' => 'mw-form-related-link-container',
+                                       'default' => Linker::link(
+                                               SpecialPage::getTitleFor( 'PasswordReset' ),
+                                               $this->msg( 'userlogin-resetpassword-link' )->escaped()
+                                       ),
+                                       'weight' => 230,
+                               ];
+                       }
+                       // Don't show a "create account" link if the user can't.
+                       if ( $this->showCreateAccountLink() ) {
+                               // link to the other action
+                               $linkTitle = $this->getTitleFor( $this->isSignup() ? 'Userlogin' :'CreateAccount' );
+                               $linkq = $this->getReturnToQueryStringFragment();
+                               // Pass any language selection on to the mode switch link
+                               if ( $wgLoginLanguageSelector && $this->mLanguage ) {
+                                       $linkq .= '&uselang=' . $this->mLanguage;
+                               }
+                               $loggedIn = $this->getUser()->isLoggedIn();
+                               $fieldDefinitions['createOrLogin'] = [
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'linkQuery' => $linkq,
+                                       'default' => function ( $params ) use ( $loggedIn, $linkTitle ) {
+                                               return Html::rawElement( 'div',
+                                                       [ 'id' => 'mw-createaccount' . ( !$loggedIn ? '-cta' : '' ),
+                                                               'class' => ( $loggedIn ? 'mw-form-related-link-container' : 'mw-ui-vform-field' ) ],
+                                                       ( $loggedIn ? '' : $this->msg( 'userlogin-noaccount' )->escaped() )
+                                                       . Html::element( 'a',
+                                                               [
+                                                                       'id' => 'mw-createaccount-join' . ( $loggedIn ? '-loggedin' : '' ),
+                                                                       'href' => $linkTitle->getLocalURL( $params['linkQuery'] ),
+                                                                       'class' => ( $loggedIn ? '' : 'mw-ui-button' ),
+                                                                       'tabindex' => 100,
+                                                               ],
+                                                               $this->msg(
+                                                                       $loggedIn ? 'userlogin-createanother' : 'userlogin-joinproject'
+                                                               )->escaped()
+                                                       )
+                                               );
+                                       },
+                                       'weight' => 235,
+                               ];
+                       }
                }
  
                $fieldDefinitions = $this->getBCFieldDefinitions( $fieldDefinitions, $template );
        /**
         * @param array $formDescriptor
         */
 -      protected function postProcessFormDescriptor( &$formDescriptor ) {
 +      protected function postProcessFormDescriptor( &$formDescriptor, $requests ) {
                // Pre-fill username (if not creating an account, T46775).
                if (
                        isset( $formDescriptor['username'] ) &&
  
                // don't show a submit button if there is nothing to submit (i.e. the only form content
                // is other submit buttons, for redirect flows)
 -              if ( !$this->needsSubmitButton( $formDescriptor ) ) {
 +              if ( !$this->needsSubmitButton( $requests ) ) {
                        unset( $formDescriptor['createaccount'], $formDescriptor['loginattempt'] );
                }
  
@@@ -1342,12 -1360,196 +1360,12 @@@ class FakeAuthTemplate extends BaseTemp
        }
  }
  
 -/**
 - * A horrible hack to handle AuthManager's feature flag. For other special pages this is done in
 - * SpecialPageFactory, but LoginForm is used directly by some extensions. Will be killed as soon
 - * as AuthManager is stable.
 - */
 -class LoginForm extends SpecialPage {
 -      private $realLoginForm;
 -
 -      public function __construct( $request = null ) {
 -              global $wgDisableAuthManager;
 -              if ( $wgDisableAuthManager ) {
 -                      $this->realLoginForm = new LoginFormPreAuthManager( $request );
 -              } else {
 -                      $this->realLoginForm = new LoginFormAuthManager( $request );
 -              }
 -      }
 -
 -      // proxy everything
 -
 -      public function __get( $name ) {
 -              return $this->realLoginForm->$name;
 -      }
 -
 -      public function __set( $name, $value ) {
 -              $this->realLoginForm->$name = $value;
 -      }
 -
 -      public function __call( $name, $args ) {
 -              return call_user_func_array( [ $this->realLoginForm, $name ], $args );
 -      }
 -
 -      public static function __callStatic( $name, $args ) {
 -              global $wgDisableAuthManager;
 -              return call_user_func_array( [ $wgDisableAuthManager ? LoginFormPreAuthManager::class
 -                      : LoginFormAuthManager::class, $name ], $args );
 -      }
 -
 -      // all public SpecialPage methods need to be proxied explicitly
 -
 -      public function getName() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getRestriction() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function isListed() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function setListed( $listed ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function listed( $x = null ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function isIncludable() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function including( $x = null ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getLocalName() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function isExpensive() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function isCached() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function isRestricted() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function userCanExecute( User $user ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function displayRestrictionError() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function checkPermissions() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function checkReadOnly() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function requireLogin(
 -              $reasonMsg = 'exception-nologin-text', $titleMsg = 'exception-nologin'
 -      ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function prefixSearchSubpages( $search, $limit, $offset ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function execute( $subPage ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getDescription() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      function getTitle( $subpage = false ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      function getPageTitle( $subpage = false ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function setContext( $context ) {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getContext() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getRequest() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getOutput() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getUser() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getSkin() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getLanguage() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getConfig() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getFullTitle() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function getFinalGroupName() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -      public function doesWrites() {
 -              return call_user_func_array( [ $this->realLoginForm, __FUNCTION__ ], func_get_args() );
 -      }
 -
 -      // no way to proxy constants and static properties
 -
 -      const SUCCESS = 0;
 -      const NO_NAME = 1;
 -      const ILLEGAL = 2;
 -      const WRONG_PLUGIN_PASS = 3;
 -      const NOT_EXISTS = 4;
 -      const WRONG_PASS = 5;
 -      const EMPTY_PASS = 6;
 -      const RESET_PASS = 7;
 -      const ABORTED = 8;
 -      const CREATE_BLOCKED = 9;
 -      const THROTTLED = 10;
 -      const USER_BLOCKED = 11;
 -      const NEED_TOKEN = 12;
 -      const WRONG_TOKEN = 13;
 -      const USER_MIGRATED = 14;
 -
 -      public static $statusCodes = [
 -              self::SUCCESS => 'success',
 -              self::NO_NAME => 'no_name',
 -              self::ILLEGAL => 'illegal',
 -              self::WRONG_PLUGIN_PASS => 'wrong_plugin_pass',
 -              self::NOT_EXISTS => 'not_exists',
 -              self::WRONG_PASS => 'wrong_pass',
 -              self::EMPTY_PASS => 'empty_pass',
 -              self::RESET_PASS => 'reset_pass',
 -              self::ABORTED => 'aborted',
 -              self::CREATE_BLOCKED => 'create_blocked',
 -              self::THROTTLED => 'throttled',
 -              self::USER_BLOCKED => 'user_blocked',
 -              self::NEED_TOKEN => 'need_token',
 -              self::WRONG_TOKEN => 'wrong_token',
 -              self::USER_MIGRATED => 'user_migrated',
 -      ];
 -
 -      public static $validErrorMessages = [
 -              'exception-nologin-text',
 -              'watchlistanontext',
 -              'changeemail-no-info',
 -              'resetpass-no-info',
 -              'confirmemail_needlogin',
 -              'prefsnologintext2',
 -      ];
 -}
 -
  /**
   * LoginForm as a special page has been replaced by SpecialUserLogin and SpecialCreateAccount,
   * but some extensions called its public methods directly, so the class is retained as a
   * B/C wrapper. Anything that used it before should use AuthManager instead.
   */
 -class LoginFormAuthManager extends SpecialPage {
 +class LoginForm extends SpecialPage {
        const SUCCESS = 0;
        const NO_NAME = 1;
        const ILLEGAL = 2;