Merge "skins: Remove 'usemsgcache' and deprecate getDynamicStylesheetQuery"
[lhc/web/wiklou.git] / includes / skins / Skin.php
index b8cd921..ed4045d 100644 (file)
@@ -21,6 +21,8 @@
  */
 
 use MediaWiki\MediaWikiServices;
+use Wikimedia\WrappedString;
+use Wikimedia\WrappedStringList;
 
 /**
  * @defgroup Skins Skins
@@ -210,15 +212,9 @@ abstract class Skin extends ContextSource {
                        'syndicate' => [],
                ];
 
-               // Support for high-density display images if enabled
-               if ( $config->get( 'ResponsiveImages' ) ) {
-                       $modules['core'][] = 'mediawiki.hidpi';
-               }
-
                // Preload jquery.tablesorter for mediawiki.page.ready
                if ( strpos( $out->getHTML(), 'sortable' ) !== false ) {
                        $modules['content'][] = 'jquery.tablesorter';
-                       $modules['styles']['content'][] = 'jquery.tablesorter.styles';
                }
 
                // Preload jquery.makeCollapsible for mediawiki.page.ready
@@ -396,38 +392,35 @@ abstract class Skin extends ContextSource {
 
        /**
         * Outputs the HTML generated by other functions.
-        * @param OutputPage $out
+        * @param OutputPage|null $out
         */
        abstract function outputPage( OutputPage $out = null );
 
        /**
         * @param array $data
-        * @return string
+        * @param string|null $nonce OutputPage::getCSPNonce()
+        * @return string|WrappedString HTML
         */
-       static function makeVariablesScript( $data ) {
+       public static function makeVariablesScript( $data, $nonce = null ) {
                if ( $data ) {
                        return ResourceLoader::makeInlineScript(
-                               ResourceLoader::makeConfigSetScript( $data )
+                               ResourceLoader::makeConfigSetScript( $data ),
+                               $nonce
                        );
-               } else {
-                       return '';
                }
+               return '';
        }
 
        /**
         * Get the query to generate a dynamic stylesheet
         *
+        * @deprecated since 1.32 Use action=raw&ctype=text/css directly.
         * @return array
         */
        public static function getDynamicStylesheetQuery() {
-               global $wgSquidMaxage;
-
                return [
                                'action' => 'raw',
-                               'maxage' => $wgSquidMaxage,
-                               'usemsgcache' => 'yes',
                                'ctype' => 'text/css',
-                               'smaxage' => $wgSquidMaxage,
                        ];
        }
 
@@ -452,7 +445,8 @@ abstract class Skin extends ContextSource {
                if ( $title->isSpecialPage() ) {
                        $type = 'ns-special';
                        // T25315: provide a class based on the canonical special page name without subpages
-                       list( $canonicalName ) = SpecialPageFactory::resolveAlias( $title->getDBkey() );
+                       list( $canonicalName ) = MediaWikiServices::getInstance()->getSpecialPageFactory()->
+                               resolveAlias( $title->getDBkey() );
                        if ( $canonicalName ) {
                                $type .= ' ' . Sanitizer::escapeClass( "mw-special-$canonicalName" );
                        } else {
@@ -505,6 +499,10 @@ abstract class Skin extends ContextSource {
 
        /**
         * Whether the logo should be preloaded with an HTTP link header or not
+        *
+        * @deprecated since 1.32 Redundant. It now happens automatically based on whether
+        *  the skin loads a stylesheet based on ResourceLoaderSkinModule, which all
+        *  skins that use wgLogo in CSS do, and other's would not.
         * @since 1.29
         * @return bool
         */
@@ -535,7 +533,7 @@ abstract class Skin extends ContextSource {
                        $t = $embed . implode( "{$pop}{$embed}", $allCats['normal'] ) . $pop;
 
                        $msg = $this->msg( 'pagecategories' )->numParams( count( $allCats['normal'] ) )->escaped();
-                       $linkPage = wfMessage( 'pagecategorieslink' )->inContentLanguage()->text();
+                       $linkPage = $this->msg( 'pagecategorieslink' )->inContentLanguage()->text();
                        $title = Title::newFromText( $linkPage );
                        $link = $title ? Linker::link( $title, $msg ) : $msg;
                        $s .= '<div id="mw-normal-catlinks" class="mw-normal-catlinks">' .
@@ -674,16 +672,22 @@ abstract class Skin extends ContextSource {
        /**
         * This gets called shortly before the "</body>" tag.
         *
-        * @return string HTML-wrapped JS code to be put before "</body>"
+        * @return string|WrappedStringList HTML containing scripts to put before `</body>`
         */
        function bottomScripts() {
                // TODO and the suckage continues. This function is really just a wrapper around
                // OutputPage::getBottomScripts() which takes a Skin param. This should be cleaned
                // up at some point
-               $bottomScriptText = $this->getOutput()->getBottomScripts();
-               Hooks::run( 'SkinAfterBottomScripts', [ $this, &$bottomScriptText ] );
-
-               return $bottomScriptText;
+               $chunks = [ $this->getOutput()->getBottomScripts() ];
+
+               // Keep the hook appendage separate to preserve WrappedString objects.
+               // This enables BaseTemplate::getTrail() to merge them where possible.
+               $extraHtml = '';
+               Hooks::run( 'SkinAfterBottomScripts', [ $this, &$extraHtml ] );
+               if ( $extraHtml !== '' ) {
+                       $chunks[] = $extraHtml;
+               }
+               return WrappedString::join( "\n", $chunks );
        }
 
        /**
@@ -736,7 +740,7 @@ abstract class Skin extends ContextSource {
        }
 
        /**
-        * @param OutputPage $out Defaults to $this->getOutput() if left as null
+        * @param OutputPage|null $out Defaults to $this->getOutput() if left as null
         * @return string
         */
        function subPageSubtitle( $out = null ) {
@@ -967,7 +971,7 @@ abstract class Skin extends ContextSource {
                if ( is_string( $icon ) ) {
                        $html = $icon;
                } else { // Assuming array
-                       $url = isset( $icon["url"] ) ? $icon["url"] : null;
+                       $url = $icon["url"] ?? null;
                        unset( $icon["url"] );
                        if ( isset( $icon["src"] ) && $withImage === 'withImage' ) {
                                // do this the lazy way, just pass icon data as an attribute array
@@ -1094,25 +1098,25 @@ abstract class Skin extends ContextSource {
        }
 
        /**
-        * Return a fully resolved style path url to images or styles stored in the current skins's folder.
-        * This method returns a url resolved using the configured skin style path
-        * and includes the style version inside of the url.
+        * Return a fully resolved style path URL to images or styles stored in the
+        * current skin's folder. This method returns a URL resolved using the
+        * configured skin style path.
         *
         * Requires $stylename to be set, otherwise throws MWException.
         *
         * @param string $name The name or path of a skin resource file
-        * @return string The fully resolved style path url including styleversion
+        * @return string The fully resolved style path URL
         * @throws MWException
         */
        function getSkinStylePath( $name ) {
-               global $wgStylePath, $wgStyleVersion;
+               global $wgStylePath;
 
                if ( $this->stylename === null ) {
                        $class = static::class;
                        throw new MWException( "$class::\$stylename must be set to use getSkinStylePath()" );
                }
 
-               return "$wgStylePath/{$this->stylename}/$name?$wgStyleVersion";
+               return "$wgStylePath/{$this->stylename}/$name";
        }
 
        /* these are used extensively in SkinTemplate, but also some other places */
@@ -1303,7 +1307,7 @@ abstract class Skin extends ContextSource {
                                [
                                        'checkKeys' => [
                                                // Unless there is both no exact $code override nor an i18n definition
-                                               // in the the software, the only MediaWiki page to check is for $code.
+                                               // in the software, the only MediaWiki page to check is for $code.
                                                $msgCache->getCheckKey( $this->getLanguage()->getCode() )
                                        ],
                                        'lockTSE' => 30
@@ -1327,7 +1331,7 @@ abstract class Skin extends ContextSource {
         * @param string $message
         */
        public function addToSidebar( &$bar, $message ) {
-               $this->addToSidebarPlain( $bar, wfMessage( $message )->inContentLanguage()->plain() );
+               $this->addToSidebarPlain( $bar, $this->msg( $message )->inContentLanguage()->plain() );
        }
 
        /**
@@ -1445,7 +1449,7 @@ abstract class Skin extends ContextSource {
 
                if ( count( $newtalks ) == 1 && $newtalks[0]['wiki'] === wfWikiID() ) {
                        $uTalkTitle = $user->getTalkPage();
-                       $lastSeenRev = isset( $newtalks[0]['rev'] ) ? $newtalks[0]['rev'] : null;
+                       $lastSeenRev = $newtalks[0]['rev'] ?? null;
                        $nofAuthors = 0;
                        if ( $lastSeenRev !== null ) {
                                $plural = true; // Default if we have a last seen revision: if unknown, use plural
@@ -1468,7 +1472,7 @@ abstract class Skin extends ContextSource {
                                $uTalkTitle,
                                $this->msg( 'newmessageslinkplural' )->params( $plural )->escaped(),
                                [],
-                               [ 'redirect' => 'no' ]
+                               $uTalkTitle->isRedirect() ? [ 'redirect' => 'no' ] : []
                        );
 
                        $newMessagesDiffLink = Linker::linkKnown(
@@ -1523,7 +1527,7 @@ abstract class Skin extends ContextSource {
         *   should fall back to the next notice in its sequence
         */
        private function getCachedNotice( $name ) {
-               global $wgRenderHashAppend, $wgContLang;
+               global $wgRenderHashAppend;
 
                $needParse = false;
 
@@ -1544,7 +1548,8 @@ abstract class Skin extends ContextSource {
                        $notice = $msg->plain();
                }
 
-               $cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
+               $services = MediaWikiServices::getInstance();
+               $cache = $services->getMainWANObjectCache();
                $parsed = $cache->getWithSetCallback(
                        // Use the extra hash appender to let eg SSL variants separately cache
                        // Key is verified with md5 hash of unparsed wikitext
@@ -1556,12 +1561,13 @@ abstract class Skin extends ContextSource {
                        }
                );
 
+               $contLang = $services->getContentLanguage();
                return Html::rawElement(
                        'div',
                        [
                                'id' => 'localNotice',
-                               'lang' => $wgContLang->getHtmlCode(),
-                               'dir' => $wgContLang->getDir()
+                               'lang' => $contLang->getHtmlCode(),
+                               'dir' => $contLang->getDir()
                        ],
                        $parsed
                );
@@ -1596,14 +1602,14 @@ abstract class Skin extends ContextSource {
        }
 
        /**
-        * Create a section edit link.  This supersedes editSectionLink() and
-        * editSectionLinkForOther().
+        * Create a section edit link.
         *
+        * @suppress SecurityCheck-XSS $links has keys of different taint types
         * @param Title $nt The title being linked to (may not be the same as
         *   the current page, if the section is included from a template)
         * @param string $section The designation of the section being pointed to,
         *   to be included in the link, like "&section=$section"
-        * @param string $tooltip The tooltip to use for the link: will be escaped
+        * @param string|null $tooltip The tooltip to use for the link: will be escaped
         *   and wrapped in the 'editsectionhint' message
         * @param string $lang Language code
         * @return string HTML to use for edit link
@@ -1616,13 +1622,13 @@ abstract class Skin extends ContextSource {
 
                $attribs = [];
                if ( !is_null( $tooltip ) ) {
-                       $attribs['title'] = wfMessage( 'editsectionhint' )->rawParams( $tooltip )
+                       $attribs['title'] = $this->msg( 'editsectionhint' )->rawParams( $tooltip )
                                ->inLanguage( $lang )->text();
                }
 
                $links = [
                        'editsection' => [
-                               'text' => wfMessage( 'editsection' )->inLanguage( $lang )->escaped(),
+                               'text' => $this->msg( 'editsection' )->inLanguage( $lang )->escaped(),
                                'targetTitle' => $nt,
                                'attribs' => $attribs,
                                'query' => [ 'action' => 'edit', 'section' => $section ],
@@ -1647,7 +1653,7 @@ abstract class Skin extends ContextSource {
 
                $result .= implode(
                        '<span class="mw-editsection-divider">'
-                               . wfMessage( 'pipe-separator' )->inLanguage( $lang )->escaped()
+                               . $this->msg( 'pipe-separator' )->inLanguage( $lang )->escaped()
                                . '</span>',
                        $linksHtml
                );