<?php
/**
- * Resource message blobs storage used by the resource loader.
+ * Resource message blobs storage used by ResourceLoader.
*
* 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
*/
/**
- * This class provides access to the resource message blobs storage used by
- * the ResourceLoader.
+ * This class provides access to the resource message blobs storage used
+ * by ResourceLoader.
*
* A message blob is a JSON object containing the interface messages for a
* certain resource in a certain language. These message blobs are cached
*/
protected $blobCache = array();
+ /* @var ResourceLoader */
+ protected $resourceloader;
+
+ /**
+ * @param ResourceLoader $resourceloader
+ */
+ public function __construct( ResourceLoader $resourceloader = null ) {
+ $this->resourceloader = $resourceloader;
+ }
+
/**
* Get the singleton instance
*
array( 'IGNORE' )
);
- if ( $success ) {
- if ( $dbw->affectedRows() == 0 ) {
- // Blob was already present, fetch it
- $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array(
- 'mr_resource' => $name,
- 'mr_lang' => $lang,
- ),
- __METHOD__
- );
- } else {
- // Update msg_resource_links
- $rows = array();
-
- foreach ( $module->getMessages() as $key ) {
- $rows[] = array(
- 'mrl_resource' => $name,
- 'mrl_message' => $key
- );
- }
- $dbw->insert( 'msg_resource_links', $rows,
- __METHOD__, array( 'IGNORE' )
- );
- }
+ if ( $success && $dbw->affectedRows() == 0 ) {
+ // Blob was already present, fetch it
+ $blob = $dbw->selectField( 'msg_resource', 'mr_blob', array(
+ 'mr_resource' => $name,
+ 'mr_lang' => $lang,
+ ),
+ __METHOD__
+ );
}
} catch ( DBError $e ) {
wfDebug( __METHOD__ . " failed to update DB: $e\n" );
* @param string $name Module name
* @param ResourceLoaderModule $module
* @param string $lang Language code
- * @return string Regenerated message blob, or null if there was no blob for
+ * @return string|null Regenerated message blob, or null if there was no blob for
* the given module/language pair.
*/
public function updateModule( $name, ResourceLoaderModule $module, $lang ) {
return null;
}
- // Save the old and new blobs for later
- $oldBlob = $row->mr_blob;
$newBlob = $this->generateMessageBlob( $module, $lang );
try {
array( array( 'mr_resource', 'mr_lang' ) ),
$newRow, __METHOD__
);
-
- // Figure out which messages were added and removed
- $oldMessages = array_keys( FormatJson::decode( $oldBlob, true ) );
- $newMessages = array_keys( FormatJson::decode( $newBlob, true ) );
- $added = array_diff( $newMessages, $oldMessages );
- $removed = array_diff( $oldMessages, $newMessages );
-
- // Delete removed messages, insert added ones
- if ( $removed ) {
- $dbw->delete( 'msg_resource_links', array(
- 'mrl_resource' => $name,
- 'mrl_message' => $removed
- ), __METHOD__
- );
- }
-
- $newLinksRows = array();
-
- foreach ( $added as $message ) {
- $newLinksRows[] = array(
- 'mrl_resource' => $name,
- 'mrl_message' => $message
- );
- }
-
- if ( $newLinksRows ) {
- $dbw->insert( 'msg_resource_links', $newLinksRows, __METHOD__,
- array( 'IGNORE' ) // just in case
- );
- }
} catch ( Exception $e ) {
wfDebug( __METHOD__ . " failed to update DB: $e\n" );
}
}
} while ( count( $updates ) );
- // No need to update msg_resource_links because we didn't add
- // or remove any messages, we just changed their contents.
} catch ( Exception $e ) {
wfDebug( __METHOD__ . " failed to update DB: $e\n" );
}
}
public function clear() {
- // TODO: Give this some more thought
try {
// Not using TRUNCATE, because that needs extra permissions,
// which maybe not granted to the database user.
$dbw = wfGetDB( DB_MASTER );
$dbw->delete( 'msg_resource', '*', __METHOD__ );
- $dbw->delete( 'msg_resource_links', '*', __METHOD__ );
} catch ( Exception $e ) {
wfDebug( __METHOD__ . " failed to update DB: $e\n" );
}
}
+ /**
+ * @return ResourceLoader
+ */
+ protected function getResourceLoader() {
+ // For back-compat this class supports instantiation without passing ResourceLoader
+ // Lazy-initialise this property because most callers don't need it.
+ if ( $this->resourceloader === null ) {
+ wfDebug( __CLASS__ . ' created without a ResourceLoader instance' );
+ $this->resourceloader = new ResourceLoader();
+ }
+
+ return $this->resourceloader;
+ }
+
/**
* Create an update queue for updateMessage()
*
$dbw = wfGetDB( DB_MASTER );
if ( is_null( $prevUpdates ) ) {
+ $rl = $this->getResourceLoader();
+ $moduleNames = $rl->getModulesByMessage( $key );
// Fetch all blobs referencing $key
$res = $dbw->select(
- array( 'msg_resource', 'msg_resource_links' ),
+ array( 'msg_resource' ),
array( 'mr_resource', 'mr_lang', 'mr_blob', 'mr_timestamp' ),
- array( 'mrl_message' => $key, 'mr_resource=mrl_resource' ),
+ array(
+ 'mr_resource' => $moduleNames,
+ ),
__METHOD__
);
} else {
return array();
}
- $config = $resourceLoader->getConfig();
$retval = array();
$dbr = wfGetDB( DB_SLAVE );
$res = $dbr->select( 'msg_resource',
throw new MWException( __METHOD__ . ' passed an invalid module name' );
}
- // Update the module's blobs if the set of messages changed or if the blob is
- // older than the CacheEpoch setting
- $keys = array_keys( FormatJson::decode( $row->mr_blob, true ) );
- $values = array_values( array_unique( $module->getMessages() ) );
- if ( $keys !== $values
- || wfTimestamp( TS_MW, $row->mr_timestamp ) <= $config->get( 'CacheEpoch' )
- ) {
+ // Update the module's blob if the list of messages changed
+ $blobKeys = array_keys( FormatJson::decode( $row->mr_blob, true ) );
+ $moduleMsgs = array_values( array_unique( $module->getMessages() ) );
+ if ( $blobKeys !== $moduleMsgs ) {
$retval[$row->mr_resource] = $this->updateModule( $row->mr_resource, $module, $lang );
} else {
$retval[$row->mr_resource] = $row->mr_blob;