Merge "mw.Feedback: If the message is posted remotely, link the title correctly"
[lhc/web/wiklou.git] / includes / OutputPage.php
index 785641d..fc7fbf7 100644 (file)
@@ -23,8 +23,9 @@
 use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
 use MediaWiki\Session\SessionManager;
-use WrappedString\WrappedString;
-use WrappedString\WrappedStringList;
+use Wikimedia\RelPath;
+use Wikimedia\WrappedString;
+use Wikimedia\WrappedStringList;
 
 /**
  * This class should be covered by a general architecture document which does
@@ -314,21 +315,16 @@ class OutputPage extends ContextSource {
         * Constructor for OutputPage. This should not be called directly.
         * Instead a new RequestContext should be created and it will implicitly create
         * a OutputPage tied to that context.
-        * @param IContextSource|null $context
+        * @param IContextSource $context
         */
-       function __construct( IContextSource $context = null ) {
-               if ( $context === null ) {
-                       # Extensions should use `new RequestContext` instead of `new OutputPage` now.
-                       wfDeprecated( __METHOD__, '1.18' );
-               } else {
-                       $this->setContext( $context );
-               }
+       function __construct( IContextSource $context ) {
+               $this->setContext( $context );
        }
 
        /**
         * Redirect to $url rather than displaying the normal page
         *
-        * @param string $url URL
+        * @param string $url
         * @param string $responsecode HTTP status code
         */
        public function redirect( $url, $responsecode = '302' ) {
@@ -371,8 +367,8 @@ class OutputPage extends ContextSource {
         * Add a new "<meta>" tag
         * To add an http-equiv meta tag, precede the name with "http:"
         *
-        * @param string $name Tag name
-        * @param string $val Tag value
+        * @param string $name Name of the meta tag
+        * @param string $val Value of the meta tag
         */
        function addMeta( $name, $val ) {
                array_push( $this->mMetatags, [ $name, $val ] );
@@ -1578,10 +1574,14 @@ class OutputPage extends ContextSource {
         * Get/set the ParserOptions object to use for wikitext parsing
         *
         * @param ParserOptions|null $options Either the ParserOption to use or null to only get the
-        *   current ParserOption object
+        *   current ParserOption object. This parameter is deprecated since 1.31.
         * @return ParserOptions
         */
        public function parserOptions( $options = null ) {
+               if ( $options !== null ) {
+                       wfDeprecated( __METHOD__ . ' with non-null $options', '1.31' );
+               }
+
                if ( $options !== null && !empty( $options->isBogus ) ) {
                        // Someone is trying to set a bogus pre-$wgUser PO. Check if it has
                        // been changed somehow, and keep it if so.
@@ -1596,7 +1596,7 @@ class OutputPage extends ContextSource {
 
                if ( !$this->mParserOptions ) {
                        if ( !$this->getContext()->getUser()->isSafeToLoad() ) {
-                               // $wgUser isn't loaded yet, so don't try to get a
+                               // $wgUser isn't unstubbable yet, so don't try to get a
                                // ParserOptions for it. And don't cache this ParserOptions
                                // either.
                                $po = ParserOptions::newFromAnon();
@@ -1784,7 +1784,9 @@ class OutputPage extends ContextSource {
 
                $popts->setTidy( $oldTidy );
 
-               $this->addParserOutput( $parserOutput );
+               $this->addParserOutput( $parserOutput, [
+                       'enableSectionEditLinks' => false,
+               ] );
        }
 
        /**
@@ -1869,9 +1871,10 @@ class OutputPage extends ContextSource {
         *
         * @since 1.24
         * @param ParserOutput $parserOutput
+        * @param array $poOptions Options to ParserOutput::getText()
         */
-       public function addParserOutputContent( $parserOutput ) {
-               $this->addParserOutputText( $parserOutput );
+       public function addParserOutputContent( $parserOutput, $poOptions = [] ) {
+               $this->addParserOutputText( $parserOutput, $poOptions );
 
                $this->addModules( $parserOutput->getModules() );
                $this->addModuleScripts( $parserOutput->getModuleScripts() );
@@ -1885,9 +1888,10 @@ class OutputPage extends ContextSource {
         *
         * @since 1.24
         * @param ParserOutput $parserOutput
+        * @param array $poOptions Options to ParserOutput::getText()
         */
-       public function addParserOutputText( $parserOutput ) {
-               $text = $parserOutput->getText();
+       public function addParserOutputText( $parserOutput, $poOptions = [] ) {
+               $text = $parserOutput->getText( $poOptions );
                // Avoid PHP 7.1 warning of passing $this by reference
                $outputPage = $this;
                Hooks::runWithoutAbort( 'OutputPageBeforeHTML', [ &$outputPage, &$text ] );
@@ -1898,16 +1902,22 @@ class OutputPage extends ContextSource {
         * Add everything from a ParserOutput object.
         *
         * @param ParserOutput $parserOutput
+        * @param array $poOptions Options to ParserOutput::getText()
         */
-       function addParserOutput( $parserOutput ) {
+       function addParserOutput( $parserOutput, $poOptions = [] ) {
                $this->addParserOutputMetadata( $parserOutput );
 
                // Touch section edit links only if not previously disabled
                if ( $parserOutput->getEditSectionTokens() ) {
                        $parserOutput->setEditSectionTokens( $this->mEnableSectionEditLinks );
                }
+               if ( !$this->mEnableSectionEditLinks
+                       && !array_key_exists( 'enableSectionEditLinks', $poOptions )
+               ) {
+                       $poOptions['enableSectionEditLinks'] = false;
+               }
 
-               $this->addParserOutputText( $parserOutput );
+               $this->addParserOutputText( $parserOutput, $poOptions );
        }
 
        /**
@@ -1958,7 +1968,9 @@ class OutputPage extends ContextSource {
                        $popts->setTargetLanguage( $oldLang );
                }
 
-               return $parserOutput->getText();
+               return $parserOutput->getText( [
+                       'enableSectionEditLinks' => false,
+               ] );
        }
 
        /**
@@ -1981,6 +1993,7 @@ class OutputPage extends ContextSource {
         * @deprecated since 1.27 Use setCdnMaxage() instead
         */
        public function setSquidMaxage( $maxage ) {
+               wfDeprecated( __METHOD__, '1.27' );
                $this->setCdnMaxage( $maxage );
        }
 
@@ -2200,7 +2213,7 @@ class OutputPage extends ContextSource {
                                        // IE and some other browsers use BCP 47 standards in
                                        // their Accept-Language header, like "zh-CN" or "zh-Hant".
                                        // We should handle these too.
-                                       $variantBCP47 = wfBCP47( $variant );
+                                       $variantBCP47 = LanguageCode::bcp47( $variant );
                                        if ( $variantBCP47 !== $variant ) {
                                                $aloption[] = 'substr=' . $variantBCP47;
                                        }
@@ -3231,6 +3244,8 @@ class OutputPage extends ContextSource {
                        && ( $relevantTitle->exists() || $relevantTitle->quickUserCan( 'create', $user ) );
 
                foreach ( $title->getRestrictionTypes() as $type ) {
+                       // Following keys are set in $vars:
+                       // wgRestrictionCreate, wgRestrictionEdit, wgRestrictionMove, wgRestrictionUpload
                        $vars['wgRestriction' . ucfirst( $type )] = $title->getRestrictions( $type );
                }
 
@@ -3319,10 +3334,14 @@ class OutputPage extends ContextSource {
                ] );
 
                if ( $config->get( 'ReferrerPolicy' ) !== false ) {
-                       $tags['meta-referrer'] = Html::element( 'meta', [
-                               'name' => 'referrer',
-                               'content' => $config->get( 'ReferrerPolicy' )
-                       ] );
+                       // Per https://w3c.github.io/webappsec-referrer-policy/#unknown-policy-values
+                       // fallbacks should come before the primary value so we need to reverse the array.
+                       foreach ( array_reverse( (array)$config->get( 'ReferrerPolicy' ) ) as $i => $policy ) {
+                               $tags["meta-referrer-$i"] = Html::element( 'meta', [
+                                       'name' => 'referrer',
+                                       'content' => $policy,
+                               ] );
+                       }
                }
 
                $p = "{$this->mIndexPolicy},{$this->mFollowPolicy}";
@@ -3437,7 +3456,7 @@ class OutputPage extends ContextSource {
                                foreach ( $variants as $variant ) {
                                        $tags["variant-$variant"] = Html::element( 'link', [
                                                'rel' => 'alternate',
-                                               'hreflang' => wfBCP47( $variant ),
+                                               'hreflang' => LanguageCode::bcp47( $variant ),
                                                'href' => $this->getTitle()->getLocalURL(
                                                        [ 'variant' => $variant ] )
                                                ]
@@ -3800,7 +3819,7 @@ class OutputPage extends ContextSource {
                        $remotePathPrefix = $remotePath = $uploadPath;
                }
 
-               $path = RelPath\getRelativePath( $path, $remotePath );
+               $path = RelPath::getRelativePath( $path, $remotePath );
                return self::transformFilePath( $remotePathPrefix, $localDir, $path );
        }
 
@@ -3957,6 +3976,7 @@ class OutputPage extends ContextSource {
         * Enables/disables section edit links, doesn't override __NOEDITSECTION__
         * @param bool $flag
         * @since 1.23
+        * @deprecated since 1.31, use $poOptions to addParserOutput() instead.
         */
        public function enableSectionEditLinks( $flag = true ) {
                $this->mEnableSectionEditLinks = $flag;
@@ -3965,6 +3985,7 @@ class OutputPage extends ContextSource {
        /**
         * @return bool
         * @since 1.23
+        * @deprecated since 1.31, use $poOptions to addParserOutput() instead.
         */
        public function sectionEditLinksEnabled() {
                return $this->mEnableSectionEditLinks;
@@ -4026,6 +4047,13 @@ class OutputPage extends ContextSource {
                        return;
                }
 
+               if ( isset( $logo['svg'] ) ) {
+                       // No media queries required if we only have a 1x and svg variant
+                       // because all preload-capable browsers support SVGs
+                       $this->addLinkHeader( '<' . $logo['svg'] . '>;rel=preload;as=image' );
+                       return;
+               }
+
                foreach ( $logo as $dppx => $src ) {
                        // Keys are in this format: "1.5x"
                        $dppx = substr( $dppx, 0, -1 );