$skin = $context->getSkin();
$lang = $context->getLanguage();
- // Get file dependency information
+ // Batched version of ResourceLoaderModule::getFileDependencies
+ $vary = "$skin|$lang";
$res = $dbr->select( 'module_deps', array( 'md_module', 'md_deps' ), array(
'md_module' => $modules,
- 'md_skin' => $skin
+ 'md_skin' => $vary,
), __METHOD__
);
-
- // Set modules' dependencies
+ // Prime in-object cache values for each module
$modulesWithDeps = array();
foreach ( $res as $row ) {
$module = $this->getModule( $row->md_module );
if ( $module ) {
- $module->setFileDependencies( $skin, FormatJson::decode( $row->md_deps, true ) );
+ $module->setFileDependencies( $context, FormatJson::decode( $row->md_deps, true ) );
$modulesWithDeps[] = $row->md_module;
}
}
-
// Register the absence of a dependency row too
foreach ( array_diff( $modules, $modulesWithDeps ) as $name ) {
$module = $this->getModule( $name );
if ( $module ) {
- $this->getModule( $name )->setFileDependencies( $skin, array() );
+ $this->getModule( $name )->setFileDependencies( $context, array() );
}
}
if ( !$options['cache'] ) {
$result = self::applyFilter( $filter, $data, $this->config );
} else {
- $key = wfGlobalCacheKey( 'resourceloader', 'filter', $filter, self::$filterCacheVersion, md5( $data ) );
+ $key = wfGlobalCacheKey(
+ 'resourceloader',
+ 'filter',
+ $filter,
+ self::$filterCacheVersion, md5( $data )
+ );
$cache = wfGetCache( wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING );
$cacheEntry = $cache->get( $key );
if ( is_string( $cacheEntry ) ) {
private static function applyFilter( $filter, $data, Config $config ) {
switch ( $filter ) {
case 'minify-js':
- return JavaScriptMinifier::minify( $data,
- $config->get( 'ResourceLoaderMinifierStatementsOnOwnLine' ),
- $config->get( 'ResourceLoaderMinifierMaxLineLength' )
- );
+ return JavaScriptMinifier::minify( $data );
case 'minify-css':
return CSSMin::minify( $data );
}
* Generate code for a response.
*
* @param ResourceLoaderContext $context Context in which to generate a response
- * @param array $modules List of module objects keyed by module name
- * @param array $missing List of requested module names that are unregistered (optional)
+ * @param ResourceLoaderModule[] $modules List of module objects keyed by module name
+ * @param string[] $missing List of requested module names that are unregistered (optional)
* @return string Response data
*/
public function makeModuleResponse( ResourceLoaderContext $context,
// Generate output
$isRaw = false;
+
+ $filter = $context->getOnly() === 'styles' ? 'minify-css' : 'minify-js';
+
foreach ( $modules as $name => $module ) {
try {
$content = $module->getModuleContent( $context );
+ $strContent = '';
// Append output
switch ( $context->getOnly() ) {
$scripts = $content['scripts'];
if ( is_string( $scripts ) ) {
// Load scripts raw...
- $out .= $scripts;
+ $strContent = $scripts;
} elseif ( is_array( $scripts ) ) {
// ...except when $scripts is an array of URLs
- $out .= self::makeLoaderImplementScript( $name, $scripts, array(), array(), array() );
+ $strContent = self::makeLoaderImplementScript( $name, $scripts, array(), array(), array() );
}
break;
case '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'] ) : '';
+ $strContent = isset( $styles['css'] ) ? implode( '', $styles['css'] ) : '';
break;
default:
- $out .= self::makeLoaderImplementScript(
+ $strContent = self::makeLoaderImplementScript(
$name,
isset( $content['scripts'] ) ? $content['scripts'] : '',
isset( $content['styles'] ) ? $content['styles'] : array(),
);
break;
}
+
+ if ( !$context->getDebug() ) {
+ // Don't cache private modules. This is especially important in the case
+ // of modules which change every time they are built, like the embedded
+ // user.tokens module (bug T84960).
+ $filterOptions = array( 'cache' => ( $module->getGroup() !== 'private' ) );
+ $strContent = $this->filter( $filter, $strContent, $filterOptions );
+ }
+
+ $out .= $strContent;
+
} catch ( Exception $e ) {
MWExceptionHandler::logException( $e );
$this->logger->warning( 'Generating module package failed: {exception}', array(
// Set the state of modules we didn't respond to with mw.loader.implement
if ( count( $states ) ) {
- $out .= self::makeLoaderStateScript( $states );
+ $stateScript = self::makeLoaderStateScript( $states );
+ if ( !$context->getDebug() ) {
+ $stateScript = $this->filter( 'minify-js', $stateScript );
+ }
+ $out .= $stateScript;
}
} else {
if ( count( $states ) ) {
}
}
- $enableFilterCache = true;
- if ( count( $modules ) === 1 && reset( $modules ) instanceof ResourceLoaderUserTokensModule ) {
- // If we're building the embedded user.tokens, don't cache (T84960)
- $enableFilterCache = false;
- }
-
- if ( !$context->getDebug() ) {
- if ( $context->getOnly() === 'styles' ) {
- $out = $this->filter( 'minify-css', $out );
- } else {
- $out = $this->filter( 'minify-js', $out, array(
- 'cache' => $enableFilterCache
- ) );
- }
- }
-
return $out;
}
}
private static function isEmptyObject( stdClass $obj ) {
- foreach ( $obj as $key => &$value ) {
+ foreach ( $obj as $key => $value ) {
return false;
}
return true;
* @return string
*/
public static function makeLoaderConditionalScript( $script ) {
- return "window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n" . trim( $script ) . "\n} );";
+ return "window.RLQ = window.RLQ || []; window.RLQ.push( function () {\n" .
+ trim( $script ) . "\n} );";
}
/**
/**
* Returns LESS compiler set up for use with MediaWiki
*
+ * @since 1.22
+ * @since 1.26 added $extraVars parameter
* @param Config $config
+ * @param array $extraVars Associative array of extra (i.e., other than the
+ * globally-configured ones) that should be used for compilation.
* @throws MWException
- * @since 1.22
* @return Less_Parser
*/
- public static function getLessCompiler( Config $config ) {
+ public static function getLessCompiler( Config $config, $extraVars = array() ) {
// When called from the installer, it is possible that a required PHP extension
// is missing (at least for now; see bug 47564). If this is the case, throw an
// exception (caught by the installer) to prevent a fatal error later on.
}
$parser = new Less_Parser;
- $parser->ModifyVars( self::getLessVars( $config ) );
+ $parser->ModifyVars( array_merge( self::getLessVars( $config ), $extraVars ) );
$parser->SetImportDirs( array_fill_keys( $config->get( 'ResourceLoaderLESSImportPaths' ), '' ) );
$parser->SetOption( 'relativeUrls', false );
$parser->SetCacheDir( $config->get( 'CacheDirectory' ) ?: wfTempDir() );
if ( !self::$lessVars ) {
$lessVars = $config->get( 'ResourceLoaderLESSVars' );
Hooks::run( 'ResourceLoaderGetLessVars', array( &$lessVars ) );
- // Sort by key to ensure consistent hashing for cache lookups.
- ksort( $lessVars );
self::$lessVars = $lessVars;
}
return self::$lessVars;