/**
* Whether the position returned by getPosition() is a default value or comes from the module
- * definition. This method is meant to be short-lived, and is only useful until classes added via
- * addModuleStyles with a default value define an explicit position. See getModuleStyles() in
- * OutputPage for the related migration warning.
+ * definition. This method is meant to be short-lived, and is only useful until classes added
+ * via addModuleStyles with a default value define an explicit position. See getModuleStyles()
+ * in OutputPage for the related migration warning.
*
* @return bool
* @since 1.26
}
$dbr = wfGetDB( DB_SLAVE );
- $deps = $dbr->selectField( 'module_deps', 'md_deps', array(
+ $deps = $dbr->selectField( 'module_deps',
+ 'md_deps',
+ array(
'md_module' => $this->getName(),
'md_skin' => $skin,
- ), __METHOD__
+ ),
+ __METHOD__
);
+
if ( !is_null( $deps ) ) {
$this->fileDeps[$skin] = (array)FormatJson::decode( $deps, true );
} else {
$this->fileDeps[$skin] = array();
}
+
return $this->fileDeps[$skin];
}
}
$dbr = wfGetDB( DB_SLAVE );
- $msgBlobMtime = $dbr->selectField( 'msg_resource', 'mr_timestamp', array(
+ $msgBlobMtime = $dbr->selectField( 'msg_resource',
+ 'mr_timestamp',
+ array(
'mr_resource' => $this->getName(),
'mr_lang' => $lang
- ), __METHOD__
+ ),
+ __METHOD__
);
// If no blob was found, but the module does have messages, that means we need
// to regenerate it. Return NOW
*/
final protected function buildContent( ResourceLoaderContext $context ) {
$rl = $context->getResourceLoader();
+ $stats = RequestContext::getMain()->getStats();
+ $statStart = microtime( true );
// Only include properties that are relevant to this context (e.g. only=scripts)
// and that are non-empty (e.g. don't include "templates" for modules without
$stylePairs[$media] = array();
foreach ( $style as $cssText ) {
if ( is_string( $cssText ) ) {
- $stylePairs[$media][] = $rl->filter( 'minify-css', $cssText );
+ $stylePairs[$media][] =
+ $rl->filter( 'minify-css', $cssText );
}
}
} elseif ( is_string( $style ) ) {
$content['templates'] = $templates;
}
+ $statTiming = microtime( true ) - $statStart;
+ $statName = strtr( $this->getName(), '.', '_' );
+ $stats->timing( "resourceloader_build.all", $statTiming );
+ $stats->timing( "resourceloader_build.$statName", $statTiming );
+
return $content;
}
$contextHash = $context->getHash();
if ( !array_key_exists( $contextHash, $this->versionHash ) ) {
- $summary = $this->getDefinitionSummary( $context );
- if ( !isset( $summary['_cacheEpoch'] ) ) {
- throw new Exception( 'getDefinitionSummary must call parent method' );
- }
- $str = json_encode( $summary );
+ if ( $this->enableModuleContentVersion() ) {
+ // Detect changes directly
+ $str = json_encode( $this->getModuleContent( $context ) );
+ } else {
+ // Infer changes based on definition and other metrics
+ $summary = $this->getDefinitionSummary( $context );
+ if ( !isset( $summary['_cacheEpoch'] ) ) {
+ throw new LogicException( 'getDefinitionSummary must call parent method' );
+ }
+ $str = json_encode( $summary );
- $mtime = $this->getModifiedTime( $context );
- if ( $mtime !== null ) {
- // Support: MediaWiki 1.25 and earlier
- $str .= strval( $mtime );
- }
+ $mtime = $this->getModifiedTime( $context );
+ if ( $mtime !== null ) {
+ // Support: MediaWiki 1.25 and earlier
+ $str .= strval( $mtime );
+ }
- $mhash = $this->getModifiedHash( $context );
- if ( $mhash !== null ) {
- // Support: MediaWiki 1.25 and earlier
- $str .= strval( $mhash );
+ $mhash = $this->getModifiedHash( $context );
+ if ( $mhash !== null ) {
+ // Support: MediaWiki 1.25 and earlier
+ $str .= strval( $mhash );
+ }
}
$this->versionHash[$contextHash] = ResourceLoader::makeHash( $str );
return $this->versionHash[$contextHash];
}
+ /**
+ * Whether to generate version hash based on module content.
+ *
+ * If a module requires database or file system access to build the module
+ * content, consider disabling this in favour of manually tracking relevant
+ * aspects in getDefinitionSummary(). See getVersionHash() for how this is used.
+ *
+ * @return bool
+ */
+ public function enableModuleContentVersion() {
+ return false;
+ }
+
/**
* Get the definition summary for this module.
*
protected function validateScriptFile( $fileName, $contents ) {
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 ) );
+ // Use CACHE_ANYTHING since parsing JS is much slower than a DB query
+ $key = wfMemcKey(
+ 'resourceloader',
+ 'jsparse',
+ self::$parseCacheVersion,
+ md5( $contents )
+ );
$cache = wfGetCache( CACHE_ANYTHING );
$cacheEntry = $cache->get( $key );
if ( is_string( $cacheEntry ) ) {
} catch ( Exception $e ) {
// We'll save this to cache to avoid having to validate broken JS over and over...
$err = $e->getMessage();
- $result = "mw.log.error(" . Xml::encodeJsVar( "JavaScript parse error: $err" ) . ");";
+ $result = "mw.log.error(" .
+ Xml::encodeJsVar( "JavaScript parse error: $err" ) . ");";
}
$cache->set( $key, $result );