Merge "ChangesListSpecialPage: Use Html instead of Xml in makeLegend()"
[lhc/web/wiklou.git] / includes / resourceloader / ResourceLoaderStartUpModule.php
index 5ee6bd2..f9c5057 100644 (file)
@@ -44,8 +44,8 @@ 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,
@@ -85,6 +85,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,
@@ -117,10 +118,79 @@ 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.
         *
-        * @param ResourceLoaderContext $context object
+        * @param ResourceLoaderContext $context
         * @return string JavaScript code for registering all modules with the client loader
         */
        public static function getModuleRegistrations( ResourceLoaderContext $context ) {
@@ -157,6 +227,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        );
                }
 
+               self::compileUnresolvedDependencies( $registryData );
+
                // Register sources
                $out .= ResourceLoader::makeLoaderSourcesScript( $resourceLoader->getSources() );
 
@@ -176,7 +248,11 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                continue;
                        }
 
-                       if ( !count( $data['dependencies'] ) && $data['group'] === null && $data['source'] === 'local' ) {
+                       if (
+                               !count( $data['dependencies'] ) &&
+                               $data['group'] === null &&
+                               $data['source'] === 'local'
+                       ) {
                                // Modules without dependencies, a group or a foreign source;
                                // call mw.loader.register(name, timestamp)
                                $registrations[] = array( $name, $data['version'] );
@@ -234,7 +310,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
        public static function getStartupModulesUrl( ResourceLoaderContext $context ) {
                // The core modules:
                $moduleNames = array( 'jquery', 'mediawiki' );
-               wfRunHooks( 'ResourceLoaderGetStartupModules', array( &$moduleNames ) );
+               wfRunHooks( 'ResourceLoaderGetStartupModules', array( &$moduleNames ), '1.23' );
 
                // Get the latest version
                $loader = $context->getResourceLoader();
@@ -265,7 +341,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
        public function getScript( ResourceLoaderContext $context ) {
                global $IP, $wgLegacyJavaScriptGlobals;
 
-               $out = file_get_contents( "$IP/resources/startup.js" );
+               $out = file_get_contents( "$IP/resources/src/startup.js" );
                if ( $context->getOnly() === 'scripts' ) {
 
                        // Startup function
@@ -274,7 +350,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                        // Fix indentation
                        $registrations = str_replace( "\n", "\n\t", trim( $registrations ) );
                        $out .= "var startUp = function () {\n" .
-                               "\tmw.config = new " . Xml::encodeJsCall( 'mw.Map', array( $wgLegacyJavaScriptGlobals ) ) . "\n" .
+                               "\tmw.config = new " .
+                               Xml::encodeJsCall( 'mw.Map', array( $wgLegacyJavaScriptGlobals ) ) . "\n" .
                                "\t$registrations\n" .
                                "\t" . Xml::encodeJsCall( 'mw.config.set', array( $configuration ) ) .
                                "};\n";
@@ -315,7 +392,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
 
                $time = max(
                        wfTimestamp( TS_UNIX, $wgCacheEpoch ),
-                       filemtime( "$IP/resources/startup.js" ),
+                       filemtime( "$IP/resources/src/startup.js" ),
                        $this->getHashMtime( $context )
                );
 
@@ -340,8 +417,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         *
         * Detect changes to mw.config settings embedded in #getScript (bug 28899).
         *
-        * @param $context ResourceLoaderContext
-        * @return string: Hash
+        * @param ResourceLoaderContext $context
+        * @return string Hash
         */
        public function getModifiedHash( ResourceLoaderContext $context ) {
                global $wgLegacyJavaScriptGlobals;