X-Git-Url: http://git.cyclocoop.org/?a=blobdiff_plain;f=includes%2Fcache%2FMessageBlobStore.php;h=624bbc9456fc54e207174ddd870adea2ffbeb417;hb=4020bf947bba198728c37f1c40532add6a46b909;hp=6290eaea01b92760ab9d7a05605957fed8dd9999;hpb=f84ebddc133361ca023d1c9305fcc5bbb785e2d8;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/cache/MessageBlobStore.php b/includes/cache/MessageBlobStore.php index 6290eaea01..624bbc9456 100644 --- a/includes/cache/MessageBlobStore.php +++ b/includes/cache/MessageBlobStore.php @@ -23,13 +23,12 @@ */ /** - * This class provides access to the resource message blobs storage used - * by ResourceLoader. + * This class provides access to the message blobs used by ResourceLoader modules. * * A message blob is a JSON object containing the interface messages for a - * certain resource in a certain language. These message blobs are cached - * in the msg_resource table and automatically invalidated when one of their - * constituent messages or the resource itself is changed. + * certain module in a certain language. These message blobs are cached + * in the automatically invalidated when one of their constituent messages, + * or the module definition, is changed. */ class MessageBlobStore { /** @@ -41,16 +40,14 @@ class MessageBlobStore { */ protected $blobCache = array(); + /* @var ResourceLoader */ + protected $resourceloader; + /** - * Get the singleton instance - * - * @since 1.24 - * @deprecated since 1.25 - * @return MessageBlobStore + * @param ResourceLoader $resourceloader */ - public static function getInstance() { - wfDeprecated( __METHOD__, '1.25' ); - return new self; + public function __construct( ResourceLoader $resourceloader = null ) { + $this->resourceloader = $resourceloader; } /** @@ -74,13 +71,13 @@ class MessageBlobStore { if ( isset( $this->blobCache[$lang][$name] ) ) { $blobs[$name] = $this->blobCache[$lang][$name]; } else { - $missingFromCache[] = $name; + $missingFromCache[$name] = $module; } } // Try DB cache if ( $missingFromCache ) { - $blobs += $this->getFromDB( $resourceLoader, $missingFromCache, $lang ); + $blobs += $this->getFromDB( $missingFromCache, $lang ); } // Generate new blobs for any remaining modules and store in DB @@ -110,7 +107,7 @@ class MessageBlobStore { * @param string $name Module name * @param ResourceLoaderModule $module * @param string $lang Language code - * @return mixed Message blob or false if the module has no messages + * @return string JSON blob */ public function insertMessageBlob( $name, ResourceLoaderModule $module, $lang ) { $blob = $this->generateMessageBlob( $module, $lang ); @@ -131,29 +128,14 @@ class MessageBlobStore { 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" ); @@ -180,8 +162,6 @@ class MessageBlobStore { return null; } - // Save the old and new blobs for later - $oldBlob = $row->mr_blob; $newBlob = $this->generateMessageBlob( $module, $lang ); try { @@ -196,36 +176,6 @@ class MessageBlobStore { 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" ); } @@ -273,26 +223,36 @@ class MessageBlobStore { } } 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() * @@ -304,11 +264,15 @@ class MessageBlobStore { $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 { @@ -344,6 +308,19 @@ class MessageBlobStore { return $updates; } + /** + * @param string $key Message key + * @param string $lang Language code + * @return string + */ + private function fetchMessage( $key, $lang ) { + $message = wfMessage( $key )->inLanguage( $lang ); + if ( !$message->exists() ) { + wfDebugLog( 'resourceloader', __METHOD__ . " failed to find: '$key' ($lang)" ); + } + return $message->plain(); + } + /** * Reencode a message blob with the updated value for a message * @@ -354,8 +331,7 @@ class MessageBlobStore { */ private function reencodeBlob( $blob, $key, $lang ) { $decoded = FormatJson::decode( $blob, true ); - $decoded[$key] = wfMessage( $key )->inLanguage( $lang )->plain(); - + $decoded[$key] = $this->fetchMessage( $key, $lang ); return FormatJson::encode( (object)$decoded ); } @@ -363,13 +339,12 @@ class MessageBlobStore { * Get the message blobs for a set of modules from the database. * Modules whose blobs are not in the database are silently dropped. * - * @param ResourceLoader $resourceLoader - * @param array $modules Array of module names + * @param array $modules Array of module objects by name * @param string $lang Language code * @throws MWException * @return array Array mapping module names to blobs */ - private function getFromDB( ResourceLoader $resourceLoader, $modules, $lang ) { + private function getFromDB( $modules, $lang ) { if ( !count( $modules ) ) { return array(); } @@ -378,16 +353,16 @@ class MessageBlobStore { $dbr = wfGetDB( DB_SLAVE ); $res = $dbr->select( 'msg_resource', array( 'mr_blob', 'mr_resource', 'mr_timestamp' ), - array( 'mr_resource' => $modules, 'mr_lang' => $lang ), + array( 'mr_resource' => array_keys( $modules ), 'mr_lang' => $lang ), __METHOD__ ); foreach ( $res as $row ) { - $module = $resourceLoader->getModule( $row->mr_resource ); - if ( !$module ) { + if ( !isset( $modules[ $row->mr_resource ] ) ) { // This shouldn't be possible throw new MWException( __METHOD__ . ' passed an invalid module name' ); } + $module = $modules[ $row->mr_resource ]; // Update the module's blob if the list of messages changed $blobKeys = array_keys( FormatJson::decode( $row->mr_blob, true ) ); @@ -407,13 +382,13 @@ class MessageBlobStore { * * @param ResourceLoaderModule $module * @param string $lang Language code - * @return string JSON object + * @return string JSON blob */ private function generateMessageBlob( ResourceLoaderModule $module, $lang ) { $messages = array(); foreach ( $module->getMessages() as $key ) { - $messages[$key] = wfMessage( $key )->inLanguage( $lang )->plain(); + $messages[$key] = $this->fetchMessage( $key, $lang ); } return FormatJson::encode( (object)$messages );