(bug 25339) Allow specifying separate base paths for local and remote paths in Resour...
authorRoan Kattouw <catrope@users.mediawiki.org>
Wed, 27 Oct 2010 22:22:10 +0000 (22:22 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Wed, 27 Oct 2010 22:22:10 +0000 (22:22 +0000)
What actually happens here
* Add $localBasePath, $remoteBasePath params to the FileModule constructor, defaulting to $IP and $wgScriptPath respectively
* Add getLocalPath() and getRemotePath(), which use this information to build a proper FS or URL path for a file
* Make readScriptFiles() non-static so it can use these functions
* Run every single file path we use through either getLocalPath() or getRemotePath() as appropriate
** Except file dependencies, these are already prefixed. Our inability to give them special treatment caused bugs earlier
* Kill prefixFilePathList() and resolveFilePath(), no longer needed

includes/resourceloader/ResourceLoaderFileModule.php

index 803133d..c3d53a8 100644 (file)
@@ -29,6 +29,10 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
 
        /* Protected Members */
 
+       /** @var {string} Local base path, see __construct() */
+       protected $localBasePath = '';
+       /** @var {string} Remote base path, see __construct() */
+       protected $remoteBasePath = '';
        /**
         * @var {array} List of paths to JavaScript files to always include
         * @format array( [file-path], [file-path], ... )
@@ -95,7 +99,8 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * Constructs a new module from an options array.
         * 
         * @param {array} $options Options array. If not given or empty, an empty module will be constructed
-        * @param {string} $basePath base path to prepend to all paths in $options
+        * @param {string} $localBasePath base path to prepend to all local paths in $options. Defaults to $IP
+        * @param {string} $remoteBasePath base path to prepend to all remote paths in $options. Defaults to $wgScriptPath
         * 
         * @format $options
         *      array(
@@ -127,7 +132,10 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         *              'group' => [group name string],
         *      )
         */
-       public function __construct( $options = array(), $basePath = null ) {
+       public function __construct( $options = array(), $localBasePath = null, $remoteBasePath = null ) {
+               global $IP, $wgScriptPath;
+               $this->localBasePath = $localBasePath === null ? $IP : $localBasePath;
+               $this->remoteBasePath = $remoteBasePath === null ? $wgScriptPath : $remoteBasePath;
                foreach ( $options as $member => $option ) {
                        switch ( $member ) {
                                // Lists of file paths
@@ -135,7 +143,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                case 'debugScripts':
                                case 'loaderScripts':
                                case 'styles':
-                                       $this->{$member} = self::prefixFilePathList( (array) $option, $basePath );
+                                       $this->{$member} = (array) $option;
                                        break;
                                // Collated lists of file paths
                                case 'languageScripts':
@@ -152,7 +160,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                                                                "Invalid collated file path list key error. '$key' given, string expected."
                                                        );
                                                }
-                                               $this->{$member}[$key] = self::prefixFilePathList( (array) $value, $basePath );
+                                               $this->{$member}[$key] = (array) $value;
                                        }
                                        break;
                                // Lists of strings
@@ -191,13 +199,13 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        if ( $this->debugRaw ) {
                                $script = '';
                                foreach ( $files as $file ) {
-                                       $path = FormatJson::encode( "$wgServer$wgScriptPath/$file" );
+                                       $path = FormatJson::encode( $wgServer . $this->getRemotePath( $file ) );
                                        $script .= "\n\tmediaWiki.loader.load( $path );";
                                }
                                return $script;
                        }
                }
-               return self::readScriptFiles( $files );
+               return $this->readScriptFiles( $files );
        }
 
        /**
@@ -209,7 +217,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                if ( count( $this->loaderScripts ) == 0 ) {
                        return false;
                }
-               return self::readScriptFiles( $this->loaderScripts );
+               return $this->readScriptFiles( $this->loaderScripts );
        }
 
        /**
@@ -311,9 +319,11 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        $context->getDebug() ? $this->debugScripts : array(),
                        self::tryForKey( $this->languageScripts, $context->getLanguage() ),
                        self::tryForKey( $this->skinScripts, $context->getSkin(), 'default' ),
-                       $this->loaderScripts,
-                       $this->getFileDependencies( $context->getSkin() )
+                       $this->loaderScripts
                );
+               $files = array_map( array( $this, 'getLocalPath' ), $files );
+               // File deps need to be treated separately because they're already prefixed
+               $files = array_merge( $files, $this->getFileDependencies( $context->getSkin() ) );
                
                // If a module is nothing but a list of dependencies, we need to avoid giving max() an empty array
                if ( count( $files ) === 0 ) {
@@ -321,7 +331,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                }
                
                wfProfileIn( __METHOD__.'-filemtime' );
-               $filesMtime = max( array_map( 'filemtime', array_map( array( __CLASS__, 'resolveFilePath' ), $files ) ) );
+               $filesMtime = max( array_map( 'filemtime', $files ) );
                wfProfileOut( __METHOD__.'-filemtime' );
                $this->modifiedTime[$context->getHash()] = max( $filesMtime, $this->getMsgBlobMtime( $context->getLanguage() ) );
                wfProfileOut( __METHOD__ );
@@ -330,27 +340,12 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
 
        /* Protected Members */
 
-       /**
-        * Prefixes each file path in a list.
-        * 
-        * @param {array} $list List of file paths in any combination of index/path or path/options pairs
-        * @param {string} $prefix String to prepend to each file path in $list
-        * @return {array} List of prefixed file paths
-        */
-       protected static function prefixFilePathList( array $list, $prefix ) {
-               $prefixed = array();
-               foreach ( $list as $key => $value ) {
-                       if ( is_string( $key ) && is_array( $value ) ) {
-                               // array( [path] => array( [options] ) )
-                               $prefixed[$prefix . $key] = $value;
-                       } else if ( is_int( $key ) && is_string( $value ) ) {
-                               // array( [path] )
-                               $prefixed[$key] = $prefix . $value;
-                       } else {
-                               throw new MWException( "Invalid file path list error. '$key' => '$value' given." );
-                       }
-               }
-               return $prefixed;
+       protected function getLocalPath( $path ) {
+               return "{$this->localBasePath}/$path";
+       }
+       
+       protected function getRemotePath( $path ) {
+               return "{$this->remoteBasePath}/$path";
        }
 
        /**
@@ -403,11 +398,11 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @param {array} $scripts List of file paths to scripts to read, remap and concetenate
         * @return {string} Concatenated and remapped JavaScript data from $scripts
         */
-       protected static function readScriptFiles( array $scripts ) {
+       protected function readScriptFiles( array $scripts ) {
                if ( empty( $scripts ) ) {
                        return '';
                }
-               return implode( "\n", array_map( array( __CLASS__, 'readScriptFile' ), array_unique( $scripts ) ) );
+               return implode( "\n", array_map( 'file_get_contents', array_map( array( $this, 'getLocalPath' ), array_unique( $scripts ) ) ) );
        }
 
        /**
@@ -429,20 +424,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                return $styles;
        }
 
-       /**
-        * Reads a script file.
-        * 
-        * This method can be used as a callback for array_map()
-        * 
-        * @param {string} $path File path of script file to read
-        * @return {string} JavaScript data in script file
-        */
-       protected static function readScriptFile( $path ) {
-               global $IP;
-               
-               return file_get_contents( "$IP/$path" );
-       }
-
        /**
         * Reads a style file.
         * 
@@ -452,28 +433,15 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @return {string} CSS data in script file
         */
        protected function readStyleFile( $path ) {
-               global $wgScriptPath, $IP;
+               global $wgScriptPath;
                
-               $style = file_get_contents( "$IP/$path" );
-               $dir = dirname( "$IP/$path" );
+               $style = file_get_contents( $this->getLocalPath( $path ) );
+               $dir = $this->getLocalPath( dirname( $path ) );
+               $remoteDir = $this->getRemotePath( dirname( $path ) );
                // Get and register local file references
                $this->localFileRefs = array_merge( $this->localFileRefs, CSSMin::getLocalFileReferences( $style, $dir ) );
                return CSSMin::remap(
-                       $style, $dir, $wgScriptPath . '/' . dirname( $path ), true
+                       $style, $dir, $remoteDir, true
                );
        }
-
-       /**
-        * Resolves a file name.
-        * 
-        * This method can be used as a callback for array_map()
-        * 
-        * @param {string} $path File path to resolve
-        * @return {string} Absolute file path
-        */
-       protected static function resolveFilePath( $path ) {
-               global $IP;
-               
-               return "$IP/$path";
-       }
 }