diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2013-01-18 16:46:04 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2013-01-18 16:46:04 +0100 |
commit | 63601400e476c6cf43d985f3e7b9864681695ed4 (patch) | |
tree | f7846203a952e38aaf66989d0a4702779f549962 /includes/resourceloader/ResourceLoader.php | |
parent | 8ff01378c9e0207f9169b81966a51def645b6a51 (diff) |
Update to MediaWiki 1.20.2
this update includes:
* adjusted Arch Linux skin
* updated FluxBBAuthPlugin
* patch for https://bugzilla.wikimedia.org/show_bug.cgi?id=44024
Diffstat (limited to 'includes/resourceloader/ResourceLoader.php')
-rw-r--r-- | includes/resourceloader/ResourceLoader.php | 166 |
1 files changed, 110 insertions, 56 deletions
diff --git a/includes/resourceloader/ResourceLoader.php b/includes/resourceloader/ResourceLoader.php index 9175b10d..3b48a266 100644 --- a/includes/resourceloader/ResourceLoader.php +++ b/includes/resourceloader/ResourceLoader.php @@ -1,5 +1,7 @@ <?php /** + * Base class for resource loading system. + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -161,11 +163,11 @@ class ResourceLoader { $wgResourceLoaderMinifierStatementsOnOwnLine, $wgResourceLoaderMinifierMaxLineLength ); - $result .= "\n\n/* cache key: $key */\n"; + $result .= "\n/* cache key: $key */"; break; case 'minify-css': $result = CSSMin::minify( $data ); - $result .= "\n\n/* cache key: $key */\n"; + $result .= "\n/* cache key: $key */"; break; } @@ -215,7 +217,7 @@ class ResourceLoader { * Registers a module with the ResourceLoader system. * * @param $name Mixed: Name of module as a string or List of name/object pairs as an array - * @param $info Module info array. For backwards compatibility with 1.17alpha, + * @param $info array Module info array. For backwards compatibility with 1.17alpha, * this may also be a ResourceLoaderModule object. Optional when using * multiple-registration calling style. * @throws MWException: If a duplicate module registration is attempted @@ -239,9 +241,9 @@ class ResourceLoader { ); } - // Check $name for illegal characters - if ( preg_match( '/[|,!]/', $name ) ) { - throw new MWException( "ResourceLoader module name '$name' is invalid. Names may not contain pipes (|), commas (,) or exclamation marks (!)" ); + // Check $name for validity + if ( !self::isValidModuleName( $name ) ) { + throw new MWException( "ResourceLoader module name '$name' is invalid, see ResourceLoader::isValidModuleName()" ); } // Attach module @@ -354,6 +356,7 @@ class ResourceLoader { * @return Array */ public function getTestModuleNames( $framework = 'all' ) { + /// @TODO: api siteinfo prop testmodulenames modulenames if ( $framework == 'all' ) { return $this->testModuleNames; } elseif ( isset( $this->testModuleNames[$framework] ) && is_array( $this->testModuleNames[$framework] ) ) { @@ -499,10 +502,6 @@ class ResourceLoader { $response = $this->makeComment( $warnings ) . $response; } - // Remove the output buffer and output the response - ob_end_clean(); - echo $response; - // Save response to file cache unless there are errors if ( isset( $fileCache ) && !$errors && !$missing ) { // Cache single modules...and other requests if there are enough hits @@ -515,6 +514,10 @@ class ResourceLoader { } } + // Remove the output buffer and output the response + ob_end_clean(); + echo $response; + wfProfileOut( __METHOD__ ); } @@ -598,7 +601,7 @@ class ResourceLoader { /** * Send out code for a response from file cache if possible * - * @param $fileCache ObjectFileCache: Cache object for this request URL + * @param $fileCache ResourceFileCache: Cache object for this request URL * @param $context ResourceLoaderContext: Context in which to generate a response * @return bool If this found a cache file and handled the response */ @@ -682,6 +685,7 @@ class ResourceLoader { } // Generate output + $isRaw = false; foreach ( $modules as $name => $module ) { /** * @var $module ResourceLoaderModule @@ -699,7 +703,7 @@ class ResourceLoader { $scripts = $module->getScriptURLsForDebug( $context ); } else { $scripts = $module->getScript( $context ); - if ( is_string( $scripts ) ) { + if ( is_string( $scripts ) && strlen( $scripts ) && substr( $scripts, -1 ) !== ';' ) { // bug 27054: Append semicolon to prevent weird bugs // caused by files not terminating their statements right $scripts .= ";\n"; @@ -709,12 +713,39 @@ class ResourceLoader { // Styles $styles = array(); if ( $context->shouldIncludeStyles() ) { - // If we are in debug mode, we'll want to return an array of URLs - // See comment near shouldIncludeScripts() for more details - if ( $context->getDebug() && !$context->getOnly() && $module->supportsURLLoading() ) { - $styles = $module->getStyleURLsForDebug( $context ); - } else { - $styles = $module->getStyles( $context ); + // Don't create empty stylesheets like array( '' => '' ) for modules + // that don't *have* any stylesheets (bug 38024). + $stylePairs = $module->getStyles( $context ); + if ( count ( $stylePairs ) ) { + // If we are in debug mode without &only= set, we'll want to return an array of URLs + // See comment near shouldIncludeScripts() for more details + if ( $context->getDebug() && !$context->getOnly() && $module->supportsURLLoading() ) { + $styles = array( + 'url' => $module->getStyleURLsForDebug( $context ) + ); + } else { + // Minify CSS before embedding in mw.loader.implement call + // (unless in debug mode) + if ( !$context->getDebug() ) { + foreach ( $stylePairs as $media => $style ) { + // Can be either a string or an array of strings. + if ( is_array( $style ) ) { + $stylePairs[$media] = array(); + foreach ( $style as $cssText ) { + if ( is_string( $cssText ) ) { + $stylePairs[$media][] = $this->filter( 'minify-css', $cssText ); + } + } + } elseif ( is_string( $style ) ) { + $stylePairs[$media] = $this->filter( 'minify-css', $style ); + } + } + } + // Wrap styles into @media groups as needed and flatten into a numerical array + $styles = array( + 'css' => self::makeCombinedStyles( $stylePairs ) + ); + } } } @@ -733,23 +764,21 @@ class ResourceLoader { } break; case 'styles': - $out .= self::makeCombinedStyles( $styles ); + // We no longer seperate into media, they are all combined now with + // custom media type groups into @media .. {} sections as part of the css string. + // Module returns either an empty array or a numerical array with css strings. + $out .= isset( $styles['css'] ) ? implode( '', $styles['css'] ) : ''; break; case 'messages': $out .= self::makeMessageSetScript( new XmlJsCode( $messagesBlob ) ); break; default: - // Minify CSS before embedding in mw.loader.implement call - // (unless in debug mode) - if ( !$context->getDebug() ) { - foreach ( $styles as $media => $style ) { - if ( is_string( $style ) ) { - $styles[$media] = $this->filter( 'minify-css', $style ); - } - } - } - $out .= self::makeLoaderImplementScript( $name, $scripts, $styles, - new XmlJsCode( $messagesBlob ) ); + $out .= self::makeLoaderImplementScript( + $name, + $scripts, + $styles, + new XmlJsCode( $messagesBlob ) + ); break; } } catch ( Exception $e ) { @@ -760,15 +789,14 @@ class ResourceLoader { $missing[] = $name; unset( $modules[$name] ); } + $isRaw |= $module->isRaw(); wfProfileOut( __METHOD__ . '-' . $name ); } // Update module states - if ( $context->shouldIncludeScripts() ) { + if ( $context->shouldIncludeScripts() && !$context->getRaw() && !$isRaw ) { // Set the state of modules loaded as only scripts to ready - if ( count( $modules ) && $context->getOnly() === 'scripts' - && !isset( $modules['startup'] ) ) - { + if ( count( $modules ) && $context->getOnly() === 'scripts' ) { $out .= self::makeLoaderStateScript( array_fill_keys( array_keys( $modules ), 'ready' ) ); } @@ -796,9 +824,9 @@ class ResourceLoader { * Returns JS code to call to mw.loader.implement for a module with * given properties. * - * @param $name Module name + * @param $name string Module name * @param $scripts Mixed: List of URLs to JavaScript files or String of JavaScript code - * @param $styles Mixed: List of CSS strings keyed by media type, or list of lists of URLs to + * @param $styles Mixed: Array of CSS strings keyed by media type, or an array of lists of URLs to * CSS files keyed by media type * @param $messages Mixed: List of messages associated with this module. May either be an * associative array mapping message key to value, or a JSON-encoded message blob containing @@ -808,7 +836,7 @@ class ResourceLoader { */ public static function makeLoaderImplementScript( $name, $scripts, $styles, $messages ) { if ( is_string( $scripts ) ) { - $scripts = new XmlJsCode( "function( $ ) {{$scripts}}" ); + $scripts = new XmlJsCode( "function () {\n{$scripts}\n}" ); } elseif ( !is_array( $scripts ) ) { throw new MWException( 'Invalid scripts error. Array of URLs or string of code expected.' ); } @@ -817,6 +845,11 @@ class ResourceLoader { array( $name, $scripts, + // Force objects. mw.loader.implement requires them to be javascript objects. + // Although these variables are associative arrays, which become javascript + // objects through json_encode. In many cases they will be empty arrays, and + // PHP/json_encode() consider empty arrays to be numerical arrays and + // output javascript "[]" instead of "{}". This fixes that. (object)$styles, (object)$messages ) ); @@ -836,26 +869,34 @@ class ResourceLoader { /** * Combines an associative array mapping media type to CSS into a - * single stylesheet with @media blocks. + * single stylesheet with "@media" blocks. * - * @param $styles Array: List of CSS strings keyed by media type + * @param $styles Array: Array keyed by media type containing (arrays of) CSS strings. * - * @return string + * @return Array */ - public static function makeCombinedStyles( array $styles ) { - $out = ''; - foreach ( $styles as $media => $style ) { - // Transform the media type based on request params and config - // The way that this relies on $wgRequest to propagate request params is slightly evil - $media = OutputPage::transformCssMedia( $media ); - - if ( $media === null ) { - // Skip - } elseif ( $media === '' || $media == 'all' ) { - // Don't output invalid or frivolous @media statements - $out .= "$style\n"; - } else { - $out .= "@media $media {\n" . str_replace( "\n", "\n\t", "\t" . $style ) . "\n}\n"; + private static function makeCombinedStyles( array $stylePairs ) { + $out = array(); + foreach ( $stylePairs as $media => $styles ) { + // ResourceLoaderFileModule::getStyle can return the styles + // as a string or an array of strings. This is to allow separation in + // the front-end. + $styles = (array) $styles; + foreach ( $styles as $style ) { + $style = trim( $style ); + // Don't output an empty "@media print { }" block (bug 40498) + if ( $style !== '' ) { + // Transform the media type based on request params and config + // The way that this relies on $wgRequest to propagate request params is slightly evil + $media = OutputPage::transformCssMedia( $media ); + + if ( $media === '' || $media == 'all' ) { + $out[] = $style; + } else if ( is_string( $media ) ) { + $out[] = "@media $media {\n" . str_replace( "\n", "\n\t", "\t" . $style ) . "}"; + } + // else: skip + } } } return $out; @@ -902,7 +943,7 @@ class ResourceLoader { public static function makeCustomLoaderScript( $name, $version, $dependencies, $group, $source, $script ) { $script = str_replace( "\n", "\n\t", trim( $script ) ); return Xml::encodeJsCall( - "( function( name, version, dependencies, group, source ) {\n\t$script\n} )", + "( function ( name, version, dependencies, group, source ) {\n\t$script\n} )", array( $name, $version, $dependencies, $group, $source ) ); } @@ -975,7 +1016,7 @@ class ResourceLoader { * @return string */ public static function makeLoaderConditionalScript( $script ) { - return "if(window.mw){\n".trim( $script )."\n}"; + return "if(window.mw){\n" . trim( $script ) . "\n}"; } /** @@ -1091,4 +1132,17 @@ class ResourceLoader { ksort( $query ); return $query; } + + /** + * Check a module name for validity. + * + * Module names may not contain pipes (|), commas (,) or exclamation marks (!) and can be + * at most 255 bytes. + * + * @param $moduleName string Module name to check + * @return bool Whether $moduleName is a valid module name + */ + public static function isValidModuleName( $moduleName ) { + return !preg_match( '/[|,!]/', $moduleName ) && strlen( $moduleName ) <= 255; + } } |