Fix meta=languageinfo usage example
[lhc/web/wiklou.git] / includes / resourceloader / ResourceLoader.php
index 8ab7c0c..387e344 100644 (file)
@@ -118,11 +118,10 @@ class ResourceLoader implements LoggerAwareInterface {
                        return;
                }
                $dbr = wfGetDB( DB_REPLICA );
-               $skin = $context->getSkin();
                $lang = $context->getLanguage();
 
                // Batched version of ResourceLoaderModule::getFileDependencies
-               $vary = "$skin|$lang";
+               $vary = ResourceLoaderModule::getVary( $context );
                $res = $dbr->select( 'module_deps', [ 'md_module', 'md_deps' ], [
                                'md_module' => $moduleNames,
                                'md_skin' => $vary,
@@ -196,8 +195,7 @@ class ResourceLoader implements LoggerAwareInterface {
                $cache = ObjectCache::getLocalServerInstance( CACHE_ANYTHING );
 
                $key = $cache->makeGlobalKey(
-                       'resourceloader',
-                       'filter',
+                       'resourceloader-filter',
                        $filter,
                        self::CACHE_VERSION,
                        md5( $data )
@@ -236,17 +234,14 @@ class ResourceLoader implements LoggerAwareInterface {
 
        /**
         * Register core modules and runs registration hooks.
-        * @param Config|null $config [optional]
+        * @param Config|null $config
         * @param LoggerInterface|null $logger [optional]
         */
        public function __construct( Config $config = null, LoggerInterface $logger = null ) {
-               global $IP;
-
                $this->logger = $logger ?: new NullLogger();
 
                if ( !$config ) {
-                       // TODO: Deprecate and remove.
-                       $this->logger->debug( __METHOD__ . ' was called without providing a Config instance' );
+                       wfDeprecated( __METHOD__ . ' without a Config instance', '1.34' );
                        $config = MediaWikiServices::getInstance()->getMainConfig();
                }
                $this->config = $config;
@@ -254,18 +249,8 @@ class ResourceLoader implements LoggerAwareInterface {
                // Add 'local' source first
                $this->addSource( 'local', $config->get( 'LoadScript' ) );
 
-               // Register core modules
-               $this->register( include "$IP/resources/Resources.php" );
-               // Register extension modules
-               $this->register( $config->get( 'ResourceModules' ) );
-
-               // Avoid PHP 7.1 warning from passing $this by reference
-               $rl = $this;
-               Hooks::run( 'ResourceLoaderRegisterModules', [ &$rl ] );
-
-               if ( $config->get( 'EnableJavaScriptTest' ) === true ) {
-                       $this->registerTestModules();
-               }
+               // Special module that always exists
+               $this->register( 'startup', [ 'class' => ResourceLoaderStartUpModule::class ] );
 
                $this->setMessageBlobStore( new MessageBlobStore( $this, $this->logger ) );
        }
@@ -319,8 +304,6 @@ class ResourceLoader implements LoggerAwareInterface {
         * @throws MWException If a duplicate module registration is attempted
         * @throws MWException If a module name contains illegal characters (pipes or commas)
         * @throws MWException If something other than a ResourceLoaderModule is being registered
-        * @return bool False if there were any errors, in which case one or more modules were
-        *   not registered
         */
        public function register( $name, $info = null ) {
                $moduleSkinStyles = $this->config->get( 'ResourceModuleSkinStyles' );
@@ -397,6 +380,9 @@ class ResourceLoader implements LoggerAwareInterface {
                }
        }
 
+       /**
+        * @internal For use by ServiceWiring only
+        */
        public function registerTestModules() {
                global $IP;
 
@@ -1122,6 +1108,10 @@ MESSAGE;
 
                                if ( !$context->getDebug() ) {
                                        $strContent = self::filter( $filter, $strContent );
+                               } else {
+                                       // In debug mode, separate each response by a new line.
+                                       // For example, between 'mw.loader.implement();' statements.
+                                       $strContent = $this->ensureNewline( $strContent );
                                }
 
                                if ( $context->getOnly() === 'scripts' ) {
@@ -1160,11 +1150,9 @@ MESSAGE;
                                // Use a linebreak between module script and state script (T162719)
                                $out = $this->ensureNewline( $out ) . $stateScript;
                        }
-               } else {
-                       if ( $states ) {
-                               $this->errors[] = 'Problematic modules: '
-                                       . self::encodeJsonForScript( $states );
-                       }
+               } elseif ( $states ) {
+                       $this->errors[] = 'Problematic modules: '
+                               . self::encodeJsonForScript( $states );
                }
 
                return $out;
@@ -1177,7 +1165,7 @@ MESSAGE;
         */
        private function ensureNewline( $str ) {
                $end = substr( $str, -1 );
-               if ( $end === false || $end === "\n" ) {
+               if ( $end === false || $end === '' || $end === "\n" ) {
                        return $str;
                }
                return $str . "\n";
@@ -1449,7 +1437,7 @@ MESSAGE;
                        }
                }
 
-               array_walk( $modules, [ 'self', 'trimArray' ] );
+               array_walk( $modules, [ self::class, 'trimArray' ] );
 
                return Xml::encodeJsCall(
                        'mw.loader.register',
@@ -1491,7 +1479,7 @@ MESSAGE;
         */
        public static function makeLoaderConditionalScript( $script ) {
                // Adds a function to lazy-created RLQ
-               return '(window.RLQ=window.RLQ||[]).push(function(){' .
+               return '(RLQ=window.RLQ||[]).push(function(){' .
                        trim( $script ) . '});';
        }
 
@@ -1505,7 +1493,7 @@ MESSAGE;
         */
        public static function makeInlineCodeWithModule( $modules, $script ) {
                // Adds an array to lazy-created RLQ
-               return '(window.RLQ=window.RLQ||[]).push(['
+               return '(RLQ=window.RLQ||[]).push(['
                        . self::encodeJsonForScript( $modules ) . ','
                        . 'function(){' . trim( $script ) . '}'
                        . ']);';
@@ -1536,7 +1524,7 @@ MESSAGE;
 
                return new WrappedString(
                        Html::inlineScript( $js, $nonce ),
-                       "<script$escNonce>(window.RLQ=window.RLQ||[]).push(function(){",
+                       "<script$escNonce>(RLQ=window.RLQ||[]).push(function(){",
                        '});</script>'
                );
        }
@@ -1572,7 +1560,7 @@ MESSAGE;
         * For example, `[ 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ]`
         * becomes `'foo.bar,baz|bar.baz,quux'`.
         *
-        * This process is reversed by ResourceLoaderContext::expandModuleNames().
+        * This process is reversed by ResourceLoader::expandModuleNames().
         * See also mw.loader#buildModulesString() which is a port of this, used
         * on the client-side.
         *
@@ -1596,6 +1584,44 @@ MESSAGE;
                return implode( '|', $arr );
        }
 
+       /**
+        * Expand a string of the form `jquery.foo,bar|jquery.ui.baz,quux` to
+        * an array of module names like `[ 'jquery.foo', 'jquery.bar',
+        * 'jquery.ui.baz', 'jquery.ui.quux' ]`.
+        *
+        * This process is reversed by ResourceLoader::makePackedModulesString().
+        *
+        * @since 1.33
+        * @param string $modules Packed module name list
+        * @return array Array of module names
+        */
+       public static function expandModuleNames( $modules ) {
+               $retval = [];
+               $exploded = explode( '|', $modules );
+               foreach ( $exploded as $group ) {
+                       if ( strpos( $group, ',' ) === false ) {
+                               // This is not a set of modules in foo.bar,baz notation
+                               // but a single module
+                               $retval[] = $group;
+                       } else {
+                               // This is a set of modules in foo.bar,baz notation
+                               $pos = strrpos( $group, '.' );
+                               if ( $pos === false ) {
+                                       // Prefixless modules, i.e. without dots
+                                       $retval = array_merge( $retval, explode( ',', $group ) );
+                               } else {
+                                       // We have a prefix and a bunch of suffixes
+                                       $prefix = substr( $group, 0, $pos ); // 'foo'
+                                       $suffixes = explode( ',', substr( $group, $pos + 1 ) ); // [ 'bar', 'baz' ]
+                                       foreach ( $suffixes as $suffix ) {
+                                               $retval[] = "$prefix.$suffix";
+                                       }
+                               }
+                       }
+               }
+               return $retval;
+       }
+
        /**
         * Determine whether debug mode was requested
         * Order of priority is 1) request param, 2) cookie, 3) $wg setting
@@ -1681,7 +1707,6 @@ MESSAGE;
         * @param bool $printable
         * @param bool $handheld
         * @param array $extraQuery
-        *
         * @return array
         */
        public static function makeLoaderQuery( $modules, $lang, $skin, $user = null,
@@ -1690,9 +1715,17 @@ MESSAGE;
        ) {
                $query = [
                        'modules' => self::makePackedModulesString( $modules ),
-                       'lang' => $lang,
-                       'skin' => $skin,
                ];
+               // Keep urls short by omitting query parameters that
+               // match the defaults assumed by ResourceLoaderContext.
+               // Note: This relies on the defaults either being insignificant or forever constant,
+               // as otherwise cached urls could change in meaning when the defaults change.
+               if ( $lang !== ResourceLoaderContext::DEFAULT_LANG ) {
+                       $query['lang'] = $lang;
+               }
+               if ( $skin !== ResourceLoaderContext::DEFAULT_SKIN ) {
+                       $query['skin'] = $skin;
+               }
                if ( $debug === true ) {
                        $query['debug'] = 'true';
                }