Mark as FIXME. This three calls leak a png filename in sys_get_temp_dir() each,
[lhc/web/wiklou.git] / includes / OutputPage.php
index 463cdaf..eb25e6a 100644 (file)
@@ -67,7 +67,7 @@ class OutputPage extends ContextSource {
         * Contains the page subtitle. Special pages usually have some links here.
         * Don't confuse with site subtitle added by skins.
         */
-       var $mSubtitle = '';
+       private $mSubtitle = array();
 
        var $mRedirect = '';
        var $mStatusCode;
@@ -820,19 +820,54 @@ class OutputPage extends ContextSource {
        /**
         * Replace the subtile with $str
         *
-        * @param $str String: new value of the subtitle
+        * @param $str String|Message: new value of the subtitle
         */
        public function setSubtitle( $str ) {
-               $this->mSubtitle = /*$this->parse(*/ $str /*)*/; // @bug 2514
+               $this->clearSubtitle();
+               $this->addSubtitle( $str );
        }
 
        /**
         * Add $str to the subtitle
         *
-        * @param $str String to add to the subtitle
+        * @deprecated in 1.19; use addSubtitle() instead
+        * @param $str String|Message to add to the subtitle
         */
        public function appendSubtitle( $str ) {
-               $this->mSubtitle .= /*$this->parse(*/ $str /*)*/; // @bug 2514
+               $this->addSubtitle( $str );
+       }
+
+       /**
+        * Add $str to the subtitle
+        *
+        * @param $str String|Message to add to the subtitle
+        */
+       public function addSubtitle( $str ) {
+               if ( $str instanceof Message ) {
+                       $this->mSubtitle[] = $str->setContext( $this->getContext() )->parse();
+               } else {
+                       $this->mSubtitle[] = $str;
+               }
+       }
+
+       /**
+        * Add a subtitle containing a backlink to a page
+        *
+        * @param $title Title to link to
+        */
+       public function addBacklinkSubtitle( Title $title ) {
+               $query = array();
+               if ( $title->isRedirect() ) {
+                       $query['redirect'] = 'no';
+               }
+               $this->addSubtitle( $this->msg( 'backlinksubtitle' )->rawParams( Linker::link( $title, null, array(), $query ) ) );
+       }
+
+       /**
+        * Clear the subtitles
+        */
+       public function clearSubtitle() {
+               $this->mSubtitle = array();
        }
 
        /**
@@ -841,7 +876,7 @@ class OutputPage extends ContextSource {
         * @return String
         */
        public function getSubtitle() {
-               return $this->mSubtitle;
+               return implode( "<br />\n\t\t\t\t", $this->mSubtitle );
        }
 
        /**
@@ -1640,7 +1675,7 @@ class OutputPage extends ContextSource {
                                $this->mVaryHeader[$header] = $option;
                        }
                }
-               $this->mVaryHeader[$header] = array_unique( $this->mVaryHeader[$header] );
+               $this->mVaryHeader[$header] = array_unique( (array)$this->mVaryHeader[$header] );
        }
 
        /**
@@ -1924,6 +1959,33 @@ class OutputPage extends ContextSource {
                throw new UserBlockedError( $this->getUser()->mBlock );
        }
 
+       /**
+        * Prepare this object to display an error page; disable caching and
+        * indexing, clear the current text and redirect, set the page's title
+        * and optionally an custom HTML title (content of the <title> tag).
+        *
+        * @param $pageTitle String|Message will be passed directly to setPageTitle()
+        * @param $htmlTitle String|Message will be passed directly to setHTMLTitle();
+        *                   optional, if not passed the <title> attribute will be
+        *                   based on $pageTitle
+        */
+       public function prepareErrorPage( $pageTitle, $htmlTitle = false ) {
+               if ( $this->getTitle() ) {
+                       $this->mDebugtext .= 'Original title: ' . $this->getTitle()->getPrefixedText() . "\n";
+               }
+
+               $this->setPageTitle( $pageTitle );
+               if ( $htmlTitle !== false ) {
+                       $this->setHTMLTitle( $htmlTitle );
+               }
+               $this->setRobotPolicy( 'noindex,nofollow' );
+               $this->setArticleRelated( false );
+               $this->enableClientCache( false );
+               $this->mRedirect = '';
+               $this->clearSubtitle();
+               $this->clearHTML();
+       }
+
        /**
         * Output a standard error page
         *
@@ -1935,16 +1997,7 @@ class OutputPage extends ContextSource {
         * @param $params Array: message parameters; ignored if $msg is a Message object
         */
        public function showErrorPage( $title, $msg, $params = array() ) {
-               if ( $this->getTitle() ) {
-                       $this->mDebugtext .= 'Original title: ' . $this->getTitle()->getPrefixedText() . "\n";
-               }
-               $this->setPageTitle( $this->msg( $title ) );
-               $this->setHTMLTitle( $this->msg( 'errorpagetitle' ) );
-               $this->setRobotPolicy( 'noindex,nofollow' );
-               $this->setArticleRelated( false );
-               $this->enableClientCache( false );
-               $this->mRedirect = '';
-               $this->mBodytext = '';
+               $this->prepareErrorPage( $this->msg( $title ), $this->msg( 'errorpagetitle' ) );
 
                if ( $msg instanceof Message ){
                        $this->addHTML( $msg->parse() );
@@ -1962,16 +2015,64 @@ class OutputPage extends ContextSource {
         * @param $action String: action that was denied or null if unknown
         */
        public function showPermissionsErrorPage( $errors, $action = null ) {
-               $this->mDebugtext .= 'Original title: ' .
-               $this->getTitle()->getPrefixedText() . "\n";
-               $this->setPageTitle( $this->msg( 'permissionserrors' ) );
-               $this->setHTMLTitle( $this->msg('permissionserrors' ) );
-               $this->setRobotPolicy( 'noindex,nofollow' );
-               $this->setArticleRelated( false );
-               $this->enableClientCache( false );
-               $this->mRedirect = '';
-               $this->mBodytext = '';
-               $this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
+               global $wgGroupPermissions;
+
+               // For some action (read, edit, create and upload), display a "login to do this action"
+               // error if all of the following conditions are met:
+               // 1. the user is not logged in
+               // 2. the only error is insufficient permissions (i.e. no block or something else)
+               // 3. the error can be avoided simply by logging in
+               if ( in_array( $action, array( 'read', 'edit', 'createpage', 'createtalk', 'upload' ) )
+                       && $this->getUser()->isAnon() && count( $errors ) == 1 && isset( $errors[0][0] )
+                       && ( $errors[0][0] == 'badaccess-groups' || $errors[0][0] == 'badaccess-group0' )
+                       && ( ( isset( $wgGroupPermissions['user'][$action] ) && $wgGroupPermissions['user'][$action] )
+                       || ( isset( $wgGroupPermissions['autoconfirmed'][$action] ) && $wgGroupPermissions['autoconfirmed'][$action] ) )
+               ) {
+                       $displayReturnto = null;
+                       $returnto = $this->getTitle();
+                       if ( $action == 'edit' ) {
+                               $msg = 'whitelistedittext';
+                               $displayReturnto = $returnto;
+                       } elseif ( $action == 'createpage' || $action == 'createtalk' ) {
+                               $msg = 'nocreatetext';
+                       } elseif ( $action == 'upload' ) {
+                               $msg = 'uploadnologintext';
+                       } else { # Read
+                               $msg = 'loginreqpagetext';
+                               $displayReturnto = Title::newMainPage();
+                       }
+
+                       $query = array();
+                       if ( $returnto ) {
+                               $query['returnto'] = $returnto->getPrefixedText();
+                               $request = $this->getRequest();
+                               if ( !$request->wasPosted() ) {
+                                       $returntoquery = $request->getValues();
+                                       unset( $returntoquery['title'] );
+                                       unset( $returntoquery['returnto'] );
+                                       unset( $returntoquery['returntoquery'] );
+                                       $query['returntoquery'] = wfArrayToCGI( $returntoquery );
+                               }
+                       }
+                       $loginLink = Linker::linkKnown(
+                               SpecialPage::getTitleFor( 'Userlogin' ),
+                               $this->msg( 'loginreqlink' )->escaped(),
+                               array(),
+                               $query
+                       );
+
+                       $this->prepareErrorPage( $this->msg( 'loginreqtitle' ) );
+                       $this->addHTML( $this->msg( $msg )->rawParams( $loginLink )->parse() );
+
+                       # Don't return to a page the user can't read otherwise
+                       # we'll end up in a pointless loop
+                       if ( $displayReturnto && $displayReturnto->userCanRead() ) {
+                               $this->returnToMain( null, $displayReturnto );
+                       }
+               } else {
+                       $this->prepareErrorPage( $this->msg( 'permissionserrors' ) );
+                       $this->addWikiText( $this->formatPermissionsErrorMessage( $errors, $action ) );
+               }
        }
 
        /**
@@ -1981,11 +2082,7 @@ class OutputPage extends ContextSource {
         * @param $version Mixed: the version of MediaWiki needed to use the page
         */
        public function versionRequired( $version ) {
-               $this->setPageTitle( $this->msg( 'versionrequired' ) );
-               $this->setHTMLTitle( $this->msg( 'versionrequired', $version ) );
-               $this->setRobotPolicy( 'noindex,nofollow' );
-               $this->setArticleRelated( false );
-               $this->mBodytext = '';
+               $this->prepareErrorPage( $this->msg( 'versionrequired', $version ) );
 
                $this->addWikiMsg( 'versionrequiredtext', $version );
                $this->returnToMain();
@@ -2002,33 +2099,11 @@ class OutputPage extends ContextSource {
 
        /**
         * Produce the stock "please login to use the wiki" page
+        *
+        * @deprecated in 1.19; throw the exception directly
         */
        public function loginToUse() {
-               if( $this->getUser()->isLoggedIn() ) {
-                       throw new PermissionsError( 'read' );
-               }
-
-               $this->setPageTitle( $this->msg( 'loginreqtitle' ) );
-               $this->setHTMLTitle( $this->msg( 'errorpagetitle' ) );
-               $this->setRobotPolicy( 'noindex,nofollow' );
-               $this->setArticleRelated( false );
-
-               $loginTitle = SpecialPage::getTitleFor( 'Userlogin' );
-               $loginLink = Linker::linkKnown(
-                       $loginTitle,
-                       $this->msg( 'loginreqlink' )->escaped(),
-                       array(),
-                       array( 'returnto' => $this->getTitle()->getPrefixedText() )
-               );
-               $this->addHTML( $this->msg( 'loginreqpagetext' )->rawParams( $loginLink )->parse() .
-                       "\n<!--" . $this->getTitle()->getPrefixedUrl() . '-->' );
-
-               # Don't return to the main page if the user can't read it
-               # otherwise we'll end up in a pointless loop
-               $mainPage = Title::newMainPage();
-               if( $mainPage->userCanRead() ) {
-                       $this->returnToMain( null, $mainPage );
-               }
+               throw new PermissionsError( 'read' );
        }
 
        /**
@@ -2101,10 +2176,8 @@ class OutputPage extends ContextSource {
                if ( !empty( $reasons ) ) {
                        // Permissions error
                        if( $source ) {
-                               $this->setPageTitle( $this->msg( 'viewsource' ) );
-                               $this->setSubtitle(
-                                       $this->msg( 'viewsourcefor', Linker::linkKnown( $this->getTitle() ) )->text()
-                               );
+                               $this->setPageTitle( $this->msg( 'viewsource-title', $this->getTitle()->getPrefixedText() ) );
+                               $this->addBacklinkSubtitle( $this->getTitle() );
                        } else {
                                $this->setPageTitle( $this->msg( 'badaccess' ) );
                        }
@@ -2176,12 +2249,9 @@ $templates
        }
 
        public function showFatalError( $message ) {
-               $this->setPageTitle( $this->msg( 'internalerror' ) );
-               $this->setRobotPolicy( 'noindex,nofollow' );
-               $this->setArticleRelated( false );
-               $this->enableClientCache( false );
-               $this->mRedirect = '';
-               $this->mBodytext = $message;
+               $this->prepareErrorPage( $this->msg( 'internalerror' ) );
+
+               $this->addHTML( $message );
        }
 
        public function showUnexpectedValueError( $name, $val ) {
@@ -2693,7 +2763,7 @@ $templates
                // Use the 'ResourceLoaderGetConfigVars' hook if the variable is not
                // page-dependant but site-wide (without state).
                // Alternatively, you may want to use OutputPage->addJsConfigVars() instead.
-               wfRunHooks( 'MakeGlobalVariablesScript', array( &$vars, &$this ) );
+               wfRunHooks( 'MakeGlobalVariablesScript', array( &$vars, $this ) );
 
                // Merge in variables from addJsConfigVars last
                return array_merge( $vars, $this->mJsConfigVars );
@@ -2805,9 +2875,10 @@ $templates
                }
 
                # Universal edit button
-               if ( $wgUniversalEditButton ) {
-                       if ( $this->isArticleRelated() && $this->getTitle() && $this->getTitle()->quickUserCan( 'edit' )
-                               && ( $this->getTitle()->exists() || $this->getTitle()->quickUserCan( 'create' ) ) ) {
+               if ( $wgUniversalEditButton && $this->isArticleRelated() ) {
+                       $user = $this->getUser();
+                       if ( $this->getTitle()->quickUserCan( 'edit', $user )
+                               && ( $this->getTitle()->exists() || $this->getTitle()->quickUserCan( 'create', $user ) ) ) {
                                // Original UniversalEditButton
                                $msg = $this->msg( 'edit' )->text();
                                $tags[] = Html::element( 'link', array(
@@ -2859,28 +2930,29 @@ $templates
                        ) );
                }
 
-               $lang = $this->getTitle()->getPageLanguage();
 
                # Language variants
-               if ( !$wgDisableLangConversion && $wgCanonicalLanguageLinks
-                       && $lang->hasVariants() ) {
-
-                       $urlvar = $lang->getURLVariant();
-
-                       if ( !$urlvar ) {
-                               $variants = $lang->getVariants();
-                               foreach ( $variants as $_v ) {
+               if ( !$wgDisableLangConversion && $wgCanonicalLanguageLinks ) {
+                       $lang = $this->getTitle()->getPageLanguage();
+                       if ( $lang->hasVariants() ) {
+
+                               $urlvar = $lang->getURLVariant();
+
+                               if ( !$urlvar ) {
+                                       $variants = $lang->getVariants();
+                                       foreach ( $variants as $_v ) {
+                                               $tags[] = Html::element( 'link', array(
+                                                       'rel' => 'alternate',
+                                                       'hreflang' => $_v,
+                                                       'href' => $this->getTitle()->getLocalURL( '', $_v ) )
+                                               );
+                                       }
+                               } else {
                                        $tags[] = Html::element( 'link', array(
-                                               'rel' => 'alternate',
-                                               'hreflang' => $_v,
-                                               'href' => $this->getTitle()->getLocalURL( '', $_v ) )
-                                       );
+                                               'rel' => 'canonical',
+                                               'href' => $this->getTitle()->getCanonicalUrl()
+                                       ) );
                                }
-                       } else {
-                               $tags[] = Html::element( 'link', array(
-                                       'rel' => 'canonical',
-                                       'href' => $this->getTitle()->getCanonicalUrl()
-                               ) );
                        }
                }
 
@@ -2928,9 +3000,6 @@ $templates
                        # like to promote instead of the RC feed (maybe like a "Recent New Articles"
                        # or "Breaking news" one). For this, we see if $wgOverrideSiteFeed is defined.
                        # If so, use it instead.
-
-                       $rctitle = SpecialPage::getTitleFor( 'Recentchanges' );
-
                        if ( $wgOverrideSiteFeed ) {
                                foreach ( $wgOverrideSiteFeed as $type => $feedUrl ) {
                                        // Note, this->feedLink escapes the url.
@@ -2940,11 +3009,11 @@ $templates
                                                $this->msg( "site-{$type}-feed", $wgSitename )->text()
                                        );
                                }
-                       } elseif ( $this->getTitle()->getPrefixedText() != $rctitle->getPrefixedText() ) {
+                       } elseif ( !$this->getTitle()->isSpecial( 'Recentchanges' ) ) {
                                foreach ( $wgAdvertisedFeedTypes as $format ) {
                                        $tags[] = $this->feedLink(
                                                $format,
-                                               $rctitle->getLocalURL( "feed={$format}" ),
+                                               $this->getTitle()->getLocalURL( "feed={$format}" ),
                                                $this->msg( "site-{$format}-feed", $wgSitename )->text() # For grep: 'site-rss-feed', 'site-atom-feed'.
                                        );
                                }