From: Roan Kattouw Date: Wed, 27 Oct 2010 22:22:10 +0000 (+0000) Subject: (bug 25339) Allow specifying separate base paths for local and remote paths in Resour... X-Git-Tag: 1.31.0-rc.0~34248 X-Git-Url: http://git.cyclocoop.org/data/%7B%24admin_url%7Dconfig?a=commitdiff_plain;h=6d4d8641f6d93b54b5e68b840512ebcc1ad24d03;p=lhc%2Fweb%2Fwiklou.git (bug 25339) Allow specifying separate base paths for local and remote paths in ResourceLoaderFileModule::__construct(). Extensions can use this to properly point the resource loader to their resources in a way that doesn't depend on the extensions/ directory being a subdirectory of phase3/ on the filesystem and that respects $wgExtensionAssetsPath. Also converted all extensions using ResourceLoader to use this approach, except MWEmbed which uses way more indirection building its module registrations than I can deal with after midnight. 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 --- diff --git a/includes/resourceloader/ResourceLoaderFileModule.php b/includes/resourceloader/ResourceLoaderFileModule.php index 803133d91f..c3d53a8656 100644 --- a/includes/resourceloader/ResourceLoaderFileModule.php +++ b/includes/resourceloader/ResourceLoaderFileModule.php @@ -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"; - } }