Merge "EditPage::newSectionSummary should return a value in all code paths"
[lhc/web/wiklou.git] / includes / resourceloader / ResourceLoaderModule.php
index 429bcec..ba37f42 100644 (file)
@@ -26,7 +26,6 @@
  * Abstraction for resource loader modules, with name registration and maxage functionality.
  */
 abstract class ResourceLoaderModule {
-
        # Type of resource
        const TYPE_SCRIPTS = 'scripts';
        const TYPE_STYLES = 'styles';
@@ -65,13 +64,18 @@ abstract class ResourceLoaderModule {
        // In-object cache for message blob mtime
        protected $msgBlobMtime = array();
 
+       /**
+        * @var Config
+        */
+       protected $config;
+
        /* Methods */
 
        /**
         * Get this module's name. This is set when the module is registered
         * with ResourceLoader::register()
         *
-        * @return mixed: Name (string) or null if no name was set
+        * @return string|null Name (string) or null if no name was set
         */
        public function getName() {
                return $this->name;
@@ -91,7 +95,7 @@ abstract class ResourceLoaderModule {
         * Get this module's origin. This is set when the module is registered
         * with ResourceLoader::register()
         *
-        * @return int: ResourceLoaderModule class constant, the subclass default
+        * @return int ResourceLoaderModule class constant, the subclass default
         *     if not set manually
         */
        public function getOrigin() {
@@ -102,7 +106,7 @@ abstract class ResourceLoaderModule {
         * Set this module's origin. This is called by ResourceLoader::register()
         * when registering the module. Other code should not call this.
         *
-        * @param int $origin origin
+        * @param int $origin Origin
         */
        public function setOrigin( $origin ) {
                $this->origin = $origin;
@@ -123,13 +127,34 @@ abstract class ResourceLoaderModule {
         * Includes all relevant JS except loader scripts.
         *
         * @param ResourceLoaderContext $context
-        * @return string: JavaScript code
+        * @return string JavaScript code
         */
        public function getScript( ResourceLoaderContext $context ) {
                // Stub, override expected
                return '';
        }
 
+       /**
+        * @return Config
+        * @since 1.24
+        */
+       public function getConfig() {
+               if ( $this->config === null ) {
+                       // Ugh, fall back to default
+                       $this->config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
+               }
+
+               return $this->config;
+       }
+
+       /**
+        * @param Config $config
+        * @since 1.24
+        */
+       public function setConfig( Config $config ) {
+               $this->config = $config;
+       }
+
        /**
         * Get the URL or URLs to load for this module's JS in debug mode.
         * The default behavior is to return a load.php?only=scripts URL for
@@ -142,20 +167,20 @@ abstract class ResourceLoaderModule {
         * MUST return either an only= URL or a non-load.php URL.
         *
         * @param ResourceLoaderContext $context
-        * @return array: Array of URLs
+        * @return array Array of URLs
         */
        public function getScriptURLsForDebug( ResourceLoaderContext $context ) {
-               $url = ResourceLoader::makeLoaderURL(
-                       array( $this->getName() ),
-                       $context->getLanguage(),
-                       $context->getSkin(),
-                       $context->getUser(),
-                       $context->getVersion(),
-                       true, // debug
-                       'scripts', // only
-                       $context->getRequest()->getBool( 'printable' ),
-                       $context->getRequest()->getBool( 'handheld' )
+               $resourceLoader = $context->getResourceLoader();
+               $derivative = new DerivativeResourceLoaderContext( $context );
+               $derivative->setModules( array( $this->getName() ) );
+               $derivative->setOnly( 'scripts' );
+               $derivative->setDebug( true );
+
+               $url = $resourceLoader->createLoaderURL(
+                       $this->getSource(),
+                       $derivative
                );
+
                return array( $url );
        }
 
@@ -173,7 +198,7 @@ abstract class ResourceLoaderModule {
         * Get all CSS for this module for a given skin.
         *
         * @param ResourceLoaderContext $context
-        * @return array: List of CSS strings or array of CSS strings keyed by media type.
+        * @return array List of CSS strings or array of CSS strings keyed by media type.
         *  like array( 'screen' => '.foo { width: 0 }' );
         *  or array( 'screen' => array( '.foo { width: 0 }' ) );
         */
@@ -189,20 +214,20 @@ abstract class ResourceLoaderModule {
         * load the files directly. See also getScriptURLsForDebug()
         *
         * @param ResourceLoaderContext $context
-        * @return array: array( mediaType => array( URL1, URL2, ... ), ... )
+        * @return array Array( mediaType => array( URL1, URL2, ... ), ... )
         */
        public function getStyleURLsForDebug( ResourceLoaderContext $context ) {
-               $url = ResourceLoader::makeLoaderURL(
-                       array( $this->getName() ),
-                       $context->getLanguage(),
-                       $context->getSkin(),
-                       $context->getUser(),
-                       $context->getVersion(),
-                       true, // debug
-                       'styles', // only
-                       $context->getRequest()->getBool( 'printable' ),
-                       $context->getRequest()->getBool( 'handheld' )
+               $resourceLoader = $context->getResourceLoader();
+               $derivative = new DerivativeResourceLoaderContext( $context );
+               $derivative->setModules( array( $this->getName() ) );
+               $derivative->setOnly( 'styles' );
+               $derivative->setDebug( true );
+
+               $url = $resourceLoader->createLoaderURL(
+                       $this->getSource(),
+                       $derivative
                );
+
                return array( 'all' => array( $url ) );
        }
 
@@ -211,7 +236,7 @@ abstract class ResourceLoaderModule {
         *
         * To get a JSON blob with messages, use MessageBlobStore::get()
         *
-        * @return array: List of message keys. Keys may occur more than once
+        * @return array List of message keys. Keys may occur more than once
         */
        public function getMessages() {
                // Stub, override expected
@@ -221,7 +246,7 @@ abstract class ResourceLoaderModule {
        /**
         * Get the group this module is in.
         *
-        * @return string: Group name
+        * @return string Group name
         */
        public function getGroup() {
                // Stub, override expected
@@ -231,7 +256,7 @@ abstract class ResourceLoaderModule {
        /**
         * Get the origin of this module. Should only be overridden for foreign modules.
         *
-        * @return string: Origin name, 'local' for local modules
+        * @return string Origin name, 'local' for local modules
         */
        public function getSource() {
                // Stub, override expected
@@ -263,7 +288,7 @@ abstract class ResourceLoaderModule {
        /**
         * Get the loader JS for this module, if set.
         *
-        * @return mixed: JavaScript loader code as a string or boolean false if no custom loader set
+        * @return mixed JavaScript loader code as a string or boolean false if no custom loader set
         */
        public function getLoaderScript() {
                // Stub, override expected
@@ -278,7 +303,7 @@ abstract class ResourceLoaderModule {
         *
         * To add dependencies dynamically on the client side, use a custom
         * loader script, see getLoaderScript()
-        * @return array: List of module names as strings
+        * @return array List of module names as strings
         */
        public function getDependencies() {
                // Stub, override expected
@@ -288,18 +313,36 @@ abstract class ResourceLoaderModule {
        /**
         * Get target(s) for the module, eg ['desktop'] or ['desktop', 'mobile']
         *
-        * @return array: Array of strings
+        * @return array Array of strings
         */
        public function getTargets() {
                return $this->targets;
        }
 
+       /**
+        * Get the skip function.
+        *
+        * Modules that provide fallback functionality can provide a "skip function". This
+        * function, if provided, will be passed along to the module registry on the client.
+        * When this module is loaded (either directly or as a dependency of another module),
+        * then this function is executed first. If the function returns true, the module will
+        * instantly be considered "ready" without requesting the associated module resources.
+        *
+        * The value returned here must be valid javascript for execution in a private function.
+        * It must not contain the "function () {" and "}" wrapper though.
+        *
+        * @return string|null A JavaScript function body returning a boolean value, or null
+        */
+       public function getSkipFunction() {
+               return null;
+       }
+
        /**
         * Get the files this module depends on indirectly for a given skin.
         * Currently these are only image files referenced by the module's CSS.
         *
         * @param string $skin Skin name
-        * @return array: List of files
+        * @return array List of files
         */
        public function getFileDependencies( $skin ) {
                // Try in-object cache first
@@ -335,7 +378,7 @@ abstract class ResourceLoaderModule {
         * Get the last modification timestamp of the message blob for this
         * module in a given language.
         * @param string $lang Language code
-        * @return int: UNIX timestamp, or 0 if the module doesn't have messages
+        * @return int UNIX timestamp, or 0 if the module doesn't have messages
         */
        public function getMsgBlobMtime( $lang ) {
                if ( !isset( $this->msgBlobMtime[$lang] ) ) {
@@ -363,7 +406,7 @@ abstract class ResourceLoaderModule {
         * Set a preloaded message blob last modification timestamp. Used so we
         * can load this information for all modules at once.
         * @param string $lang Language code
-        * @param $mtime Integer: UNIX timestamp or 0 if there is no such blob
+        * @param int $mtime UNIX timestamp or 0 if there is no such blob
         */
        public function setMsgBlobMtime( $lang, $mtime ) {
                $this->msgBlobMtime[$lang] = $mtime;
@@ -387,7 +430,7 @@ abstract class ResourceLoaderModule {
         * yourself and take its result into consideration.
         *
         * @param ResourceLoaderContext $context Context object
-        * @return integer UNIX timestamp
+        * @return int UNIX timestamp
         */
        public function getModifiedTime( ResourceLoaderContext $context ) {
                // 0 would mean now
@@ -398,7 +441,7 @@ abstract class ResourceLoaderModule {
         * Helper method for calculating when the module's hash (if it has one) changed.
         *
         * @param ResourceLoaderContext $context
-        * @return integer: UNIX timestamp or 0 if no hash was provided
+        * @return int UNIX timestamp or 0 if no hash was provided
         *  by getModifiedHash()
         */
        public function getHashMtime( ResourceLoaderContext $context ) {
@@ -432,7 +475,7 @@ abstract class ResourceLoaderModule {
         * use of getHashMTime() inside getModifiedTime().
         *
         * @param ResourceLoaderContext $context
-        * @return string|null: Hash
+        * @return string|null Hash
         */
        public function getModifiedHash( ResourceLoaderContext $context ) {
                return null;
@@ -441,7 +484,9 @@ abstract class ResourceLoaderModule {
        /**
         * Helper method for calculating when this module's definition summary was last changed.
         *
-        * @return integer: UNIX timestamp or 0 if no definition summary was provided
+        * @since 1.23
+        *
+        * @return int UNIX timestamp or 0 if no definition summary was provided
         *  by getDefinitionSummary()
         */
        public function getDefinitionMtime( ResourceLoaderContext $context ) {
@@ -474,7 +519,8 @@ abstract class ResourceLoaderModule {
                        return $data;
                }
 
-               wfDebugLog( 'resourceloader', __METHOD__ . ": New definition hash for module {$this->getName()} in context {$context->getHash()}: $hash." );
+               wfDebugLog( 'resourceloader', __METHOD__ . ": New definition hash for module "
+                       . "{$this->getName()} in context {$context->getHash()}: $hash." );
 
                $timestamp = time();
                $cache->set( $key, $timestamp );
@@ -505,7 +551,9 @@ abstract class ResourceLoaderModule {
         * contain arrays and scalars as values (avoid object instances) which means
         * it requires abstraction.
         *
-        * @return Array|null
+        * @since 1.23
+        *
+        * @return array|null
         */
        public function getDefinitionSummary( ResourceLoaderContext $context ) {
                return array(
@@ -526,7 +574,7 @@ abstract class ResourceLoaderModule {
                return false;
        }
 
-       /** @var JSParser lazy-initialized; use self::javaScriptParser() */
+       /** @var JSParser Lazy-initialized; use self::javaScriptParser() */
        private static $jsParser;
        private static $parseCacheVersion = 1;
 
@@ -536,11 +584,10 @@ abstract class ResourceLoaderModule {
         *
         * @param string $fileName
         * @param string $contents
-        * @return string: JS with the original, or a replacement error
+        * @return string JS with the original, or a replacement error
         */
        protected function validateScriptFile( $fileName, $contents ) {
-               global $wgResourceLoaderValidateJS;
-               if ( $wgResourceLoaderValidateJS ) {
+               if ( $this->getConfig()->get( 'ResourceLoaderValidateJS' ) ) {
                        // Try for cache hit
                        // Use CACHE_ANYTHING since filtering is very slow compared to DB queries
                        $key = wfMemcKey( 'resourceloader', 'jsparse', self::$parseCacheVersion, md5( $contents ) );