Merge "Fix RequestContextTest screwing up $wgUser"
[lhc/web/wiklou.git] / includes / resourceloader / ResourceLoaderStartUpModule.php
index 8dc5946..8a936c6 100644 (file)
@@ -44,11 +44,12 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                }
 
                global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension,
-                       $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang,
-                       $wgVariantArticlePath, $wgActionPaths, $wgVersion,
+                       $wgArticlePath, $wgScriptPath, $wgServer, $wgServerName,
+                       $wgContLang, $wgVariantArticlePath, $wgActionPaths, $wgVersion,
                        $wgEnableAPI, $wgEnableWriteAPI, $wgDBname,
                        $wgSitename, $wgFileExtensions, $wgExtensionAssetsPath,
-                       $wgCookiePrefix, $wgResourceLoaderMaxQueryLength,
+                       $wgCookiePrefix, $wgCookieDomain, $wgCookiePath,
+                       $wgCookieExpiration, $wgResourceLoaderMaxQueryLength,
                        $wgResourceLoaderStorageEnabled, $wgResourceLoaderStorageVersion,
                        $wgSearchType;
 
@@ -85,6 +86,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        // becoming [] instead of {} in JS (bug 34604)
                        'wgActionPaths' => (object)$wgActionPaths,
                        'wgServer' => $wgServer,
+                       'wgServerName' => $wgServerName,
                        'wgUserLanguage' => $context->getLanguage(),
                        'wgContentLanguage' => $wgContLang->getCode(),
                        'wgVersion' => $wgVersion,
@@ -104,6 +106,9 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        'wgExtensionAssetsPath' => $wgExtensionAssetsPath,
                        // MediaWiki sets cookies to have this prefix by default
                        'wgCookiePrefix' => $wgCookiePrefix,
+                       'wgCookieDomain' => $wgCookieDomain,
+                       'wgCookiePath' => $wgCookiePath,
+                       'wgCookieExpiration' => $wgCookieExpiration,
                        'wgResourceLoaderMaxQueryLength' => $wgResourceLoaderMaxQueryLength,
                        'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces,
                        'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass( Title::legalChars() ),
@@ -117,6 +122,75 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                return $this->configVars[$hash];
        }
 
+       /**
+        * Recursively get all explicit and implicit dependencies for to the given module.
+        *
+        * @param array $registryData
+        * @param string $moduleName
+        * @return array
+        */
+       protected static function getImplicitDependencies( Array $registryData, $moduleName ) {
+               static $dependencyCache = array();
+
+               // The list of implicit dependencies won't be altered, so we can
+               // cache them without having to worry.
+               if ( !isset( $dependencyCache[$moduleName] ) ) {
+
+                       if ( !isset( $registryData[$moduleName] ) ) {
+                               // Dependencies may not exist
+                               $dependencyCache[$moduleName] = array();
+                       } else {
+                               $data = $registryData[$moduleName];
+                               $dependencyCache[$moduleName] = $data['dependencies'];
+
+                               foreach ( $data['dependencies'] as $dependency ) {
+                                       // Recursively get the dependencies of the dependencies
+                                       $dependencyCache[$moduleName] = array_merge(
+                                               $dependencyCache[$moduleName],
+                                               self::getImplicitDependencies( $registryData, $dependency )
+                                       );
+                               }
+                       }
+               }
+
+               return $dependencyCache[$moduleName];
+       }
+
+       /**
+        * Optimize the dependency tree in $this->modules and return it.
+        *
+        * The optimization basically works like this:
+        *      Given we have module A with the dependencies B and C
+        *              and module B with the dependency C.
+        *      Now we don't have to tell the client to explicitly fetch module
+        *              C as that's already included in module B.
+        *
+        * This way we can reasonably reduce the amout of module registration
+        * data send to the client.
+        *
+        * @param Array &$registryData Modules keyed by name with properties:
+        *  - string 'version'
+        *  - array 'dependencies'
+        *  - string|null 'group'
+        *  - string 'source'
+        *  - string|false 'loader'
+        */
+       public static function compileUnresolvedDependencies( Array &$registryData ) {
+               foreach ( $registryData as $name => &$data ) {
+                       if ( $data['loader'] !== false ) {
+                               continue;
+                       }
+                       $dependencies = $data['dependencies'];
+                       foreach ( $data['dependencies'] as $dependency ) {
+                               $implicitDependencies = self::getImplicitDependencies( $registryData, $dependency );
+                               $dependencies = array_diff( $dependencies, $implicitDependencies );
+                       }
+                       // Rebuild keys
+                       $data['dependencies'] = array_values( $dependencies );
+               }
+       }
+
+
        /**
         * Get registration code for all modules.
         *
@@ -148,15 +222,29 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
 
                        // FIXME: Convert to numbers, wfTimestamp always gives us stings, even for TS_UNIX
 
+                       $skipFunction = $module->getSkipFunction();
+                       if ( $skipFunction !== null && !ResourceLoader::inDebugMode() ) {
+                               $skipFunction = $resourceLoader->filter( 'minify-js',
+                                       $skipFunction,
+                                       // There will potentially be lots of these little string in the registrations
+                                       // manifest, we don't want to blow up the startup module with
+                                       // "/* cache key: ... */" all over it in non-debug mode.
+                                       /* cacheReport = */ false
+                               );
+                       }
+
                        $registryData[ $name ] = array(
                                'version' => $mtime,
                                'dependencies' => $module->getDependencies(),
                                'group' => $module->getGroup(),
                                'source' => $module->getSource(),
                                'loader' => $module->getLoaderScript(),
+                               'skip' => $skipFunction,
                        );
                }
 
+               self::compileUnresolvedDependencies( $registryData );
+
                // Register sources
                $out .= ResourceLoader::makeLoaderSourcesScript( $resourceLoader->getSources() );
 
@@ -179,17 +267,25 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        if (
                                !count( $data['dependencies'] ) &&
                                $data['group'] === null &&
-                               $data['source'] === 'local'
+                               $data['source'] === 'local' &&
+                               $data['skip'] === null
                        ) {
-                               // Modules without dependencies, a group or a foreign source;
+                               // Modules with no dependencies, group, foreign source or skip function;
                                // call mw.loader.register(name, timestamp)
                                $registrations[] = array( $name, $data['version'] );
-                       } elseif ( $data['group'] === null && $data['source'] === 'local' ) {
-                               // Modules with dependencies but no group or foreign source;
+                       } elseif (
+                               $data['group'] === null &&
+                               $data['source'] === 'local' &&
+                               $data['skip'] === null
+                       ) {
+                               // Modules with dependencies but no group, foreign source or skip function;
                                // call mw.loader.register(name, timestamp, dependencies)
                                $registrations[] = array( $name, $data['version'], $data['dependencies'] );
-                       } elseif ( $data['source'] === 'local' ) {
-                               // Modules with a group but no foreign source;
+                       } elseif (
+                               $data['source'] === 'local' &&
+                               $data['skip'] === null
+                       ) {
+                               // Modules with a group but no foreign source or skip function;
                                // call mw.loader.register(name, timestamp, dependencies, group)
                                $registrations[] = array(
                                        $name,
@@ -197,8 +293,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                        $data['dependencies'],
                                        $data['group']
                                );
-                       } else {
-                               // Modules with a foreign source;
+                       } elseif ( $data['skip'] === null ) {
+                               // Modules with a foreign source but no skip function;
                                // call mw.loader.register(name, timestamp, dependencies, group, source)
                                $registrations[] = array(
                                        $name,
@@ -207,6 +303,17 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                        $data['group'],
                                        $data['source']
                                );
+                       } else {
+                               // Modules with a skip function;
+                               // call mw.loader.register(name, timestamp, dependencies, group, source, skip)
+                               $registrations[] = array(
+                                       $name,
+                                       $data['version'],
+                                       $data['dependencies'],
+                                       $data['group'],
+                                       $data['source'],
+                                       $data['skip']
+                               );
                        }
                }