* requests its own information. This sacrifice of modularity yields a substantial
* performance improvement.
*
- * @param array $modules List of module names to preload information for
+ * @param array $moduleNames List of module names to preload information for
* @param ResourceLoaderContext $context Context to load the information within
*/
- public function preloadModuleInfo( array $modules, ResourceLoaderContext $context ) {
- if ( !count( $modules ) ) {
+ public function preloadModuleInfo( array $moduleNames, ResourceLoaderContext $context ) {
+ if ( !$moduleNames ) {
// Or else Database*::select() will explode, plus it's cheaper!
return;
}
// Batched version of ResourceLoaderModule::getFileDependencies
$vary = "$skin|$lang";
$res = $dbr->select( 'module_deps', array( 'md_module', 'md_deps' ), array(
- 'md_module' => $modules,
+ 'md_module' => $moduleNames,
'md_skin' => $vary,
), __METHOD__
);
- // Prime in-object cache values for each module
+
+ // Prime in-object cache for file dependencies
$modulesWithDeps = array();
foreach ( $res as $row ) {
$module = $this->getModule( $row->md_module );
}
}
// Register the absence of a dependency row too
- foreach ( array_diff( $modules, $modulesWithDeps ) as $name ) {
+ foreach ( array_diff( $moduleNames, $modulesWithDeps ) as $name ) {
$module = $this->getModule( $name );
if ( $module ) {
$this->getModule( $name )->setFileDependencies( $context, array() );
}
}
- // Get message blob mtimes. Only do this for modules with messages
- $modulesWithMessages = array();
- foreach ( $modules as $name ) {
+ // Prime in-object cache for message blobs for modules with messages
+ $modules = array();
+ foreach ( $moduleNames as $name ) {
$module = $this->getModule( $name );
- if ( $module && count( $module->getMessages() ) ) {
- $modulesWithMessages[] = $name;
- }
- }
- $modulesWithoutMessages = array_flip( $modules ); // Will be trimmed down by the loop below
- if ( count( $modulesWithMessages ) ) {
- $res = $dbr->select( 'msg_resource', array( 'mr_resource', 'mr_timestamp' ), array(
- 'mr_resource' => $modulesWithMessages,
- 'mr_lang' => $lang
- ), __METHOD__
- );
- foreach ( $res as $row ) {
- $module = $this->getModule( $row->mr_resource );
- if ( $module ) {
- $module->setMsgBlobMtime( $lang, wfTimestamp( TS_UNIX, $row->mr_timestamp ) );
- unset( $modulesWithoutMessages[$row->mr_resource] );
- }
+ if ( $module && $module->getMessages() ) {
+ $modules[$name] = $module;
}
}
- foreach ( array_keys( $modulesWithoutMessages ) as $name ) {
- $module = $this->getModule( $name );
- if ( $module ) {
- $module->setMsgBlobMtime( $lang, 1 );
- }
+ $store = $this->getMessageBlobStore();
+ $blobs = $store->getBlobs( $modules, $lang );
+ foreach ( $blobs as $name => $blob ) {
+ $modules[$name]->setMessageBlob( $blob, $lang );
}
}
}
$stats = RequestContext::getMain()->getStats();
- $cache = ObjectCache::newAccelerator( CACHE_ANYTHING );
+ $cache = ObjectCache::getLocalServerInstance( CACHE_ANYTHING );
$key = $cache->makeGlobalKey(
'resourceloader',
/**
* Register core modules and runs registration hooks.
- * @param Config|null $config
+ * @param Config $config [optional]
+ * @param LoggerInterface $logger [optional]
*/
public function __construct( Config $config = null, LoggerInterface $logger = null ) {
global $IP;
- if ( !$logger ) {
- $logger = new NullLogger();
- }
- $this->setLogger( $logger );
+ $this->logger = $logger ?: new NullLogger();
if ( !$config ) {
$this->logger->debug( __METHOD__ . ' was called without providing a Config instance' );
$this->registerTestModules();
}
- $this->setMessageBlobStore( new MessageBlobStore() );
+ $this->setMessageBlobStore( new MessageBlobStore( $this, $this->logger ) );
}
/**
return $this->config;
}
+ /**
+ * @since 1.26
+ * @param LoggerInterface $logger
+ */
public function setLogger( LoggerInterface $logger ) {
$this->logger = $logger;
}
+ /**
+ * @since 1.27
+ * @return LoggerInterface
+ */
+ public function getLogger() {
+ return $this->logger;
+ }
+
/**
* @since 1.26
* @return MessageBlobStore
/**
* Add a foreign source of modules.
*
+ * Source IDs are typically the same as the Wiki ID or database name (e.g. lowercase a-z).
+ *
* @param array|string $id Source ID (string), or array( id1 => loadUrl, id2 => loadUrl, ... )
* @param string|array $loadUrl load.php url (string), or array with loadUrl key for
* backwards-compatibility.
/** @var ResourceLoaderModule $object */
$object = new $class( $info );
$object->setConfig( $this->getConfig() );
+ $object->setLogger( $this->logger );
}
$object->setName( $name );
$this->modules[$name] = $object;
}
try {
- // Preload for getCombinedVersion()
+ // Preload for getCombinedVersion() and for batch makeModuleResponse()
$this->preloadModuleInfo( array_keys( $modules ), $context );
} catch ( Exception $e ) {
MWExceptionHandler::logException( $e );
return $data;
}
- // Pre-fetch blobs
- if ( $context->shouldIncludeMessages() ) {
- try {
- $this->blobStore->get( $this, $modules, $context->getLanguage() );
- } catch ( Exception $e ) {
- MWExceptionHandler::logException( $e );
- $this->logger->warning( 'Prefetching MessageBlobStore failed: {exception}', array(
- 'exception' => $e
- ) );
- $this->errors[] = self::formatExceptionNoComment( $e );
- }
- }
-
foreach ( $missing as $name ) {
$states[$name] = 'missing';
}
return $out;
}
+ /**
+ * Get names of modules that use a certain message.
+ *
+ * @param string $messageKey
+ * @return array List of module names
+ */
+ public function getModulesByMessage( $messageKey ) {
+ $moduleNames = array();
+ foreach ( $this->getModuleNames() as $moduleName ) {
+ $module = $this->getModule( $moduleName );
+ if ( in_array( $messageKey, $module->getMessages() ) ) {
+ $moduleNames[] = $moduleName;
+ }
+ }
+ return $moduleNames;
+ }
+
/* Static Methods */
/**