Followup cf5f641: pass $params by reference again
[lhc/web/wiklou.git] / includes / OutputPage.php
index 5176c2b..24b9e46 100644 (file)
@@ -122,6 +122,9 @@ class OutputPage extends ContextSource {
        /** @var array */
        protected $mCategories = array();
 
+       /** @var array */
+       protected $mIndicators = array();
+
        /** @var array Array of Interwiki Prefixed (non DB key) Titles (e.g. 'fr:Test page') */
        private $mLanguageLinks = array();
 
@@ -179,12 +182,14 @@ class OutputPage extends ContextSource {
 
        protected $mFeedLinksAppendQuery = null;
 
-       /**
-        * @var int
-        * The level of 'untrustworthiness' allowed for modules loaded on this page.
+       /** @var array
+        * What level of 'untrustworthiness' is allowed in CSS/JS modules loaded on this page?
         * @see ResourceLoaderModule::$origin
+        * ResourceLoaderModule::ORIGIN_ALL is assumed unless overridden;
         */
-       protected $mAllowedModuleOrigin = ResourceLoaderModule::ORIGIN_ALL;
+       protected $mAllowedModules = array(
+               ResourceLoaderModule::TYPE_COMBINED => ResourceLoaderModule::ORIGIN_ALL,
+       );
 
        /** @var bool Whether output is disabled.  If this is true, the 'output' method will do nothing. */
        protected $mDoNothing = false;
@@ -361,6 +366,16 @@ class OutputPage extends ContextSource {
                array_push( $this->mMetatags, array( $name, $val ) );
        }
 
+       /**
+        * Returns the current <meta> tags
+        *
+        * @since 1.25
+        * @return array
+        */
+       public function getMetaTags() {
+               return $this->mMetatags;
+       }
+
        /**
         * Add a new \<link\> tag to the page header.
         *
@@ -372,6 +387,16 @@ class OutputPage extends ContextSource {
                array_push( $this->mLinktags, $linkarr );
        }
 
+       /**
+        * Returns the current <link> tags
+        *
+        * @since 1.25
+        * @return array
+        */
+       public function getLinkTags() {
+               return $this->mLinktags;
+       }
+
        /**
         * Add a new \<link\> with "rel" attribute set to "meta"
         *
@@ -393,6 +418,17 @@ class OutputPage extends ContextSource {
                $this->mCanonicalUrl = $url;
        }
 
+       /**
+        * Returns the URL to be used for the <link rel=canonical> if
+        * one is set.
+        *
+        * @since 1.25
+        * @return bool|string
+        */
+       public function getCanonicalUrl() {
+               return $this->mCanonicalUrl;
+       }
+
        /**
         * Get the value of the "rel" attribute for metadata links
         *
@@ -750,7 +786,7 @@ class OutputPage extends ContextSource {
                        // bug 44570: the core page itself may not change, but resources might
                        $modifiedTimes['sepoch'] = wfTimestamp( TS_MW, time() - $config->get( 'SquidMaxage' ) );
                }
-               wfRunHooks( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
+               Hooks::run( 'OutputPageCheckLastModified', array( &$modifiedTimes ) );
 
                $maxModified = max( $modifiedTimes );
                $this->mLastModified = wfTimestamp( TS_RFC2822, $maxModified );
@@ -997,17 +1033,29 @@ class OutputPage extends ContextSource {
        }
 
        /**
-        * Add a subtitle containing a backlink to a page
+        * Build message object for a subtitle containing a backlink to a page
         *
         * @param Title $title Title to link to
         * @param array $query Array of additional parameters to include in the link
+        * @return Message
+        * @since 1.25
         */
-       public function addBacklinkSubtitle( Title $title, $query = array() ) {
+       public static function buildBacklinkSubtitle( Title $title, $query = array() ) {
                if ( $title->isRedirect() ) {
                        $query['redirect'] = 'no';
                }
-               $this->addSubtitle( $this->msg( 'backlinksubtitle' )
-                       ->rawParams( Linker::link( $title, null, array(), $query ) ) );
+               return wfMessage( 'backlinksubtitle' )
+                       ->rawParams( Linker::link( $title, null, array(), $query ) );
+       }
+
+       /**
+        * Add a subtitle containing a backlink to a page
+        *
+        * @param Title $title Title to link to
+        * @param array $query Array of additional parameters to include in the link
+        */
+       public function addBacklinkSubtitle( Title $title, $query = array() ) {
+               $this->addSubtitle( self::buildBacklinkSubtitle( $title, $query ) );
        }
 
        /**
@@ -1277,7 +1325,7 @@ class OutputPage extends ContextSource {
                }
 
                # Add the remaining categories to the skin
-               if ( wfRunHooks(
+               if ( Hooks::run(
                        'OutputPageMakeCategoryLinks',
                        array( &$this, $categories, &$this->mCategoryLinks ) )
                ) {
@@ -1330,53 +1378,85 @@ class OutputPage extends ContextSource {
        }
 
        /**
-        * Restrict the page to loading modules bundled the software.
+        * Add an array of indicators, with their identifiers as array keys and HTML contents as values.
+        *
+        * In case of duplicate keys, existing values are overwritten.
         *
-        * Disallows the queue to contain any modules which can be modified by wiki
-        * users to load on this page.
+        * @param array $indicators
+        * @since 1.25
         */
-       public function disallowUserJs() {
-               $this->reduceAllowedModuleOrigin( ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL );
+       public function setIndicators( array $indicators ) {
+               $this->mIndicators = $indicators + $this->mIndicators;
+               // Keep ordered by key
+               ksort( $this->mIndicators );
        }
 
        /**
-        * Get the level of JavaScript / CSS untrustworthiness allowed on this page.
+        * Get the indicators associated with this page.
         *
-        * @see ResourceLoaderModule::$origin
-        * @param string $type Unused: Module origin allowance used to be fragmented by
-        *  ResourceLoaderModule TYPE_ constants.
-        * @return int ResourceLoaderModule ORIGIN_ class constant
+        * The array will be internally ordered by item keys.
+        *
+        * @return array Keys: identifiers, values: HTML contents
+        * @since 1.25
         */
-       public function getAllowedModules( $type = null ) {
-               return $this->mAllowedModuleOrigin;
+       public function getIndicators() {
+               return $this->mIndicators;
        }
 
        /**
-        * Set the highest level of CSS/JS untrustworthiness allowed
-        *
-        * @deprecated since 1.24 Raising level of allowed untrusted content is no longer supported.
-        *  Use reduceAllowedModuleOrigin() instead.
+        * Do not allow scripts which can be modified by wiki users to load on this page;
+        * only allow scripts bundled with, or generated by, the software.
+        * Site-wide styles are controlled by a config setting, since they can be
+        * used to create a custom skin/theme, but not user-specific ones.
         *
+        * @todo this should be given a more accurate name
+        */
+       public function disallowUserJs() {
+               $this->reduceAllowedModules(
+                       ResourceLoaderModule::TYPE_SCRIPTS,
+                       ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL
+               );
+
+               // Site-wide styles are controlled by a config setting, see bug 71621
+               // for background on why. User styles are never allowed.
+               if ( $this->getConfig()->get( 'AllowSiteCSSOnRestrictedPages' ) ) {
+                       $styleOrigin = ResourceLoaderModule::ORIGIN_USER_SITEWIDE;
+               } else {
+                       $styleOrigin = ResourceLoaderModule::ORIGIN_CORE_INDIVIDUAL;
+               }
+               $this->reduceAllowedModules(
+                       ResourceLoaderModule::TYPE_STYLES,
+                       $styleOrigin
+               );
+       }
+
+       /**
+        * Show what level of JavaScript / CSS untrustworthiness is allowed on this page
+        * @see ResourceLoaderModule::$origin
         * @param string $type ResourceLoaderModule TYPE_ constant
-        * @param int $level ResourceLoaderModule ORIGIN_ constant
+        * @return int ResourceLoaderModule ORIGIN_ class constant
         */
-       public function setAllowedModules( $type, $level ) {
-               wfDeprecated( __METHOD__, '1.24' );
-               $this->reduceAllowedModuleOrigin( $level );
+       public function getAllowedModules( $type ) {
+               if ( $type == ResourceLoaderModule::TYPE_COMBINED ) {
+                       return min( array_values( $this->mAllowedModules ) );
+               } else {
+                       return isset( $this->mAllowedModules[$type] )
+                               ? $this->mAllowedModules[$type]
+                               : ResourceLoaderModule::ORIGIN_ALL;
+               }
        }
 
        /**
-        * Limit the highest level of CSS/JS untrustworthiness allowed.
-        *
-        * @deprecated since 1.24 Module allowance is no longer fragmented by content type.
-        *  Use reduceAllowedModuleOrigin() instead.
+        * Set the highest level of CSS/JS untrustworthiness allowed
         *
+        * @deprecated since 1.24 Raising level of allowed untrusted content is no longer supported.
+        *  Use reduceAllowedModules() instead
         * @param string $type ResourceLoaderModule TYPE_ constant
-        * @param int $level ResourceLoaderModule ORIGIN_ class constant
+        * @param int $level ResourceLoaderModule class constant
         */
-       public function reduceAllowedModules( $type, $level ) {
+       public function setAllowedModules( $type, $level ) {
                wfDeprecated( __METHOD__, '1.24' );
-               $this->reduceAllowedModuleOrigin( $level );
+               $this->reduceAllowedModules( $type, $level );
        }
 
        /**
@@ -1385,10 +1465,11 @@ class OutputPage extends ContextSource {
         * If passed the same or a higher level than the current level of untrustworthiness set, the
         * level will remain unchanged.
         *
+        * @param string $type
         * @param int $level ResourceLoaderModule class constant
         */
-       public function reduceAllowedModuleOrigin( $level ) {
-               $this->mAllowedModuleOrigin = min( $this->mAllowedModuleOrigin, $level );
+       public function reduceAllowedModules( $type, $level ) {
+               $this->mAllowedModules[$type] = min( $this->getAllowedModules( $type ), $level );
        }
 
        /**
@@ -1641,6 +1722,7 @@ class OutputPage extends ContextSource {
        public function addParserOutputMetadata( $parserOutput ) {
                $this->mLanguageLinks += $parserOutput->getLanguageLinks();
                $this->addCategoryLinks( $parserOutput->getCategories() );
+               $this->setIndicators( $parserOutput->getIndicators() );
                $this->mNewSectionLink = $parserOutput->getNewSection();
                $this->mHideNewSectionLink = $parserOutput->getHideNewSection();
 
@@ -1683,8 +1765,8 @@ class OutputPage extends ContextSource {
                // Link flags are ignored for now, but may in the future be
                // used to mark individual language links.
                $linkFlags = array();
-               wfRunHooks( 'LanguageLinks', array( $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ) );
-               wfRunHooks( 'OutputPageParserOutput', array( &$this, $parserOutput ) );
+               Hooks::run( 'LanguageLinks', array( $this->getTitle(), &$this->mLanguageLinks, &$linkFlags ) );
+               Hooks::run( 'OutputPageParserOutput', array( &$this, $parserOutput ) );
        }
 
        /**
@@ -1713,7 +1795,7 @@ class OutputPage extends ContextSource {
         */
        public function addParserOutputText( $parserOutput ) {
                $text = $parserOutput->getText();
-               wfRunHooks( 'OutputPageBeforeHTML', array( &$this, &$text ) );
+               Hooks::run( 'OutputPageBeforeHTML', array( &$this, &$text ) );
                $this->addHTML( $text );
        }
 
@@ -1838,7 +1920,7 @@ class OutputPage extends ContextSource {
                                ),
                                $config->get( 'CacheVaryCookies' )
                        );
-                       wfRunHooks( 'GetCacheVaryCookies', array( $this, &$cookies ) );
+                       Hooks::run( 'GetCacheVaryCookies', array( $this, &$cookies ) );
                }
                return $cookies;
        }
@@ -2101,7 +2183,7 @@ class OutputPage extends ContextSource {
                        $redirect = $this->mRedirect;
                        $code = $this->mRedirectCode;
 
-                       if ( wfRunHooks( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
+                       if ( Hooks::run( "BeforePageRedirect", array( $this, &$redirect, &$code ) ) ) {
                                if ( $code == '301' || $code == '303' ) {
                                        if ( !$config->get( 'DebugRedirects' ) ) {
                                                $message = HttpStatus::getMessage( $code );
@@ -2178,7 +2260,7 @@ class OutputPage extends ContextSource {
 
                        // Hook that allows last minute changes to the output page, e.g.
                        // adding of CSS or Javascript by extensions.
-                       wfRunHooks( 'BeforePageDisplay', array( &$this, &$sk ) );
+                       Hooks::run( 'BeforePageDisplay', array( &$this, &$sk ) );
 
                        wfProfileIn( 'Output-skin' );
                        $sk->outputPage();
@@ -2186,7 +2268,7 @@ class OutputPage extends ContextSource {
                }
 
                // This hook allows last minute changes to final overall output by modifying output buffer
-               wfRunHooks( 'AfterFinalPageOutput', array( $this ) );
+               Hooks::run( 'AfterFinalPageOutput', array( $this ) );
 
                $this->sendCacheControl();
 
@@ -2615,7 +2697,7 @@ class OutputPage extends ContextSource {
 
                // Allow skins and extensions to add body attributes they need
                $sk->addToBodyAttributes( $this, $bodyAttrs );
-               wfRunHooks( 'OutputPageBodyAttributes', array( $this, $sk, &$bodyAttrs ) );
+               Hooks::run( 'OutputPageBodyAttributes', array( $this, $sk, &$bodyAttrs ) );
 
                $ret .= Html::openElement( 'body', $bodyAttrs ) . "\n";
 
@@ -3124,6 +3206,7 @@ class OutputPage extends ContextSource {
                        'wgMonthNames' => $lang->getMonthNamesArray(),
                        'wgMonthNamesShort' => $lang->getMonthAbbreviationsArray(),
                        'wgRelevantPageName' => $relevantTitle->getPrefixedDBkey(),
+                       'wgRelevantArticleId' => $relevantTitle->getArticleId(),
                );
 
                if ( $user->isLoggedIn() ) {
@@ -3164,7 +3247,7 @@ class OutputPage extends ContextSource {
                // 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 ) );
+               Hooks::run( 'MakeGlobalVariablesScript', array( &$vars, $this ) );
 
                // Merge in variables from addJsConfigVars last
                return array_merge( $vars, $this->getJsConfigVars() );
@@ -3512,7 +3595,9 @@ class OutputPage extends ContextSource {
                $moduleStyles[] = 'user.groups';
 
                // Per-user custom styles
-               if ( $this->getConfig()->get( 'AllowUserCss' ) && $this->getTitle()->isCssSubpage() && $this->userCanPreview() ) {
+               if ( $this->getConfig()->get( 'AllowUserCss' ) && $this->getTitle()->isCssSubpage()
+                       && $this->userCanPreview()
+               ) {
                        // We're on a preview of a CSS subpage
                        // Exclude this page from the user module in case it's in there (bug 26283)
                        $link = $this->makeResourceLoaderLink( 'user', ResourceLoaderModule::TYPE_STYLES, false,