wikimedia/mediawiki-core

View on GitHub
includes/specials/helpers/LoginHelper.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php

use MediaWiki\Context\ContextSource;
use MediaWiki\Context\IContextSource;
use MediaWiki\HookContainer\HookRunner;
use MediaWiki\HookContainer\ProtectedHookAccessorTrait;
use MediaWiki\MainConfigNames;
use MediaWiki\MediaWikiServices;
use MediaWiki\Title\Title;

/**
 * Helper functions for the login form that need to be shared with other special pages
 * (such as CentralAuth's SpecialCentralLogin).
 * @since 1.27
 */
class LoginHelper extends ContextSource {
    use ProtectedHookAccessorTrait;

    /**
     * Valid error and warning messages
     *
     * Special:Userlogin can show an error or warning message on the form when
     * coming from another page. This is done via the ?error= or ?warning= GET
     * parameters.
     *
     * This array is the list of valid message keys. Further keys can be added by the
     * LoginFormValidErrorMessages hook. All other values will be ignored.
     *
     * @var string[]
     */
    public static $validErrorMessages = [
        'exception-nologin-text',
        'exception-nologin-text-for-temp-user',
        'watchlistanontext',
        'watchlistanontext-for-temp-user',
        'changeemail-no-info',
        'confirmemail_needlogin',
        'prefsnologintext2',
        'prefsnologintext2-for-temp-user',
        'specialmute-login-required',
        'specialmute-login-required-for-temp-user',
    ];

    /**
     * Returns an array of all valid error messages.
     *
     * @return array
     * @see LoginHelper::$validErrorMessages
     */
    public static function getValidErrorMessages() {
        static $messages = null;
        if ( !$messages ) {
            $messages = self::$validErrorMessages;
            ( new HookRunner( MediaWikiServices::getInstance()->getHookContainer() ) )
                ->onLoginFormValidErrorMessages( $messages );
        }

        return $messages;
    }

    public function __construct( IContextSource $context ) {
        $this->setContext( $context );
    }

    /**
     * Show a return link or redirect to it.
     * Extensions can change where the link should point or inject content into the page
     * (which will change it from redirect to link mode).
     *
     * @param string $type One of the following:
     *    - error: display a return to link ignoring $wgRedirectOnLogin
     *    - success: display a return to link using $wgRedirectOnLogin if needed
     *    - successredirect: send an HTTP redirect using $wgRedirectOnLogin if needed
     *    - signup: used during signup, functionally identical to 'success'
     * @param string $returnTo Title of page to return to. Overriden by $wgRedirectOnLogin
     *   when that is set (and $type is not 'error').
     * @param array|string $returnToQuery Query parameters to return to.
     * @param bool $stickHTTPS Keep redirect link on HTTPS. Ignored (treated as
     *   true) if $wgForceHTTPS is true.
     * @param string $returnToAnchor A string to append to the URL, presumed to
     *   be either a fragment including the leading hash or an empty string.
     */
    public function showReturnToPage(
        $type, $returnTo = '', $returnToQuery = '', $stickHTTPS = false, $returnToAnchor = ''
    ) {
        $config = $this->getConfig();
        if ( $type !== 'error' && $config->get( MainConfigNames::RedirectOnLogin ) !== null ) {
            $returnTo = $config->get( MainConfigNames::RedirectOnLogin );
            $returnToQuery = [];
        } elseif ( is_string( $returnToQuery ) ) {
            $returnToQuery = wfCgiToArray( $returnToQuery );
        }
        if ( $returnToAnchor !== '' && $returnToAnchor[0] !== '#' ) {
            $returnToAnchor = '';
        }

        // Allow modification of redirect behavior
        $oldReturnTo = $returnTo;
        $oldReturnToQuery = $returnToQuery;
        $this->getHookRunner()->onPostLoginRedirect( $returnTo, $returnToQuery, $type );
        if ( $returnTo !== $oldReturnTo || $returnToQuery !== $oldReturnToQuery ) {
            // PostLoginRedirect does not handle $returnToAnchor, and changing hooks is hard.
            // At least don't add the anchor if the hook changed the URL.
            $returnToAnchor = '';
        }

        $returnToTitle = Title::newFromText( $returnTo ) ?: Title::newMainPage();

        if ( $config->get( MainConfigNames::ForceHTTPS )
            || ( $config->get( MainConfigNames::SecureLogin ) && $stickHTTPS )
        ) {
            $options = [ 'https' ];
            $proto = PROTO_HTTPS;
        } elseif ( $config->get( MainConfigNames::SecureLogin ) && !$stickHTTPS ) {
            $options = [ 'http' ];
            $proto = PROTO_HTTP;
        } else {
            $options = [];
            $proto = PROTO_RELATIVE;
        }

        if ( $type === 'successredirect' ) {
            $redirectUrl = $returnToTitle->getFullUrlForRedirect( $returnToQuery, $proto )
                . $returnToAnchor;
            $this->getOutput()->redirect( $redirectUrl );
        } else {
            $this->getOutput()->addReturnTo( $returnToTitle, $returnToQuery, null, $options );
        }
    }
}