Merge "Revert "merged master"" into Wikidata
[lhc/web/wiklou.git] / includes / MessageBlobStore.php
index 9d1cdda..23955ae 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 /**
+ * Resource message blobs storage used by the resource loader.
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
@@ -15,6 +17,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  * http://www.gnu.org/copyleft/gpl.html
  *
+ * @file
  * @author Roan Kattouw
  * @author Trevor Parscal
  */
  * consistuent messages or the resource itself is changed.
  */
 class MessageBlobStore {
+
        /**
         * Get the message blobs for a set of modules
+        *
+        * @param $resourceLoader ResourceLoader object
         * @param $modules array Array of module objects keyed by module name
         * @param $lang string Language code
         * @return array An array mapping module names to message blobs
@@ -61,8 +67,10 @@ class MessageBlobStore {
         * Generate and insert a new message blob. If the blob was already
         * present, it is not regenerated; instead, the preexisting blob
         * is fetched and returned.
-        * @param $module string Module name
-        * @param $lang string Language code
+        *
+        * @param $name String: module name
+        * @param $module ResourceLoaderModule object
+        * @param $lang String: language code
         * @return mixed Message blob or false if the module has no messages
         */
        public static function insertMessageBlob( $name, ResourceLoaderModule $module, $lang ) {
@@ -112,47 +120,37 @@ class MessageBlobStore {
        }
 
        /**
-        * Update all message blobs for a given module.
-        * @param $module string Module name
-        * @param $lang string Language code (optional)
-        * @return mixed If $lang is set, the new message blob for that language is 
-        *    returned if present. Otherwise, null is returned.
+        * Update the message blob for a given module in a given language
+        *
+        * @param $name String: module name
+        * @param $module ResourceLoaderModule object
+        * @param $lang String: language code
+        * @return String Regenerated message blob, or null if there was no blob for the given module/language pair
         */
-       public static function updateModule( $name, ResourceLoaderModule $module, $lang = null ) {
-               $retval = null;
-
-               // Find all existing blobs for this module
+       public static function updateModule( $name, ResourceLoaderModule $module, $lang ) {
                $dbw = wfGetDB( DB_MASTER );
-               $res = $dbw->select( 'msg_resource',
-                       array( 'mr_lang', 'mr_blob' ),
-                       array( 'mr_resource' => $name ),
+               $row = $dbw->selectRow( 'msg_resource', 'mr_blob',
+                       array( 'mr_resource' => $name, 'mr_lang' => $lang ),
                        __METHOD__
                );
-
-               // Build the new msg_resource rows
-               $newRows = array();
-               $now = $dbw->timestamp();
-               // Save the last-processed old and new blobs for later
-               $oldBlob = $newBlob = null;
-
-               foreach ( $res as $row ) {
-                       $oldBlob = $row->mr_blob;
-                       $newBlob = self::generateMessageBlob( $module, $row->mr_lang );
-
-                       if ( $row->mr_lang === $lang ) {
-                               $retval = $newBlob;
-                       }
-                       $newRows[] = array(
-                               'mr_resource' => $name,
-                               'mr_lang' => $row->mr_lang,
-                               'mr_blob' => $newBlob,
-                               'mr_timestamp' => $now
-                       );
+               if ( !$row ) {
+                       return null;
                }
 
+               // Save the old and new blobs for later
+               $oldBlob = $row->mr_blob;
+               $newBlob = self::generateMessageBlob( $module, $lang );
+               
+               $newRow = array(
+                       'mr_resource' => $name,
+                       'mr_lang' => $lang,
+                       'mr_blob' => $newBlob,
+                       'mr_timestamp' => $dbw->timestamp()
+               );
+
                $dbw->replace( 'msg_resource',
                        array( array( 'mr_resource', 'mr_lang' ) ),
-                       $newRows, __METHOD__
+                       $newRow, __METHOD__
                );
 
                // Figure out which messages were added and removed
@@ -185,12 +183,13 @@ class MessageBlobStore {
                        );
                }
 
-               return $retval;
+               return $newBlob;
        }
 
        /**
         * Update a single message in all message blobs it occurs in.
-        * @param $key string Message key
+        *
+        * @param $key String: message key
         */
        public static function updateMessage( $key ) {
                $dbw = wfGetDB( DB_MASTER );
@@ -202,7 +201,7 @@ class MessageBlobStore {
                do {
                        $updates = self::getUpdatesForMessage( $key, $updates );
 
-                       foreach ( $updates as $key => $update ) {
+                       foreach ( $updates as $k => $update ) {
                                // Update the row on the condition that it
                                // didn't change since we fetched it by putting
                                // the timestamp in the WHERE clause.
@@ -222,7 +221,7 @@ class MessageBlobStore {
                                // fear of getting into an infinite loop
                                if ( !( $success && $dbw->affectedRows() == 0 ) ) {
                                        // Not conflicted
-                                       unset( $updates[$key] );
+                                       unset( $updates[$k] );
                                }
                        }
                } while ( count( $updates ) );
@@ -241,9 +240,10 @@ class MessageBlobStore {
 
        /**
         * Create an update queue for updateMessage()
-        * @param $key string Message key
-        * @param $prevUpdates array Updates queue to refresh or null to build a fresh update queue
-        * @return array Updates queue
+        *
+        * @param $key String: message key
+        * @param $prevUpdates Array: updates queue to refresh or null to build a fresh update queue
+        * @return Array: updates queue
         */
        private static function getUpdatesForMessage( $key, $prevUpdates = null ) {
                $dbw = wfGetDB( DB_MASTER );
@@ -291,23 +291,26 @@ class MessageBlobStore {
 
        /**
         * Reencode a message blob with the updated value for a message
-        * @param $blob string Message blob (JSON object)
-        * @param $key string Message key
-        * @param $lang string Language code
+        *
+        * @param $blob String: message blob (JSON object)
+        * @param $key String: message key
+        * @param $lang String: language code
         * @return Message blob with $key replaced with its new value
         */
        private static function reencodeBlob( $blob, $key, $lang ) {
                $decoded = FormatJson::decode( $blob, true );
                $decoded[$key] = wfMsgExt( $key, array( 'language' => $lang ) );
 
-               return FormatJson::encode( $decoded );
+               return FormatJson::encode( (object)$decoded );
        }
 
        /**
         * Get the message blobs for a set of modules from the database.
         * Modules whose blobs are not in the database are silently dropped.
-        * @param $modules array Array of module names
-        * @param $lang string Language code
+        *
+        * @param $resourceLoader ResourceLoader object
+        * @param $modules Array of module names
+        * @param $lang String: language code
         * @return array Array mapping module names to blobs
         */
        private static function getFromDB( ResourceLoader $resourceLoader, $modules, $lang ) {
@@ -328,9 +331,9 @@ class MessageBlobStore {
                        }
                        // Update the module's blobs if the set of messages changed or if the blob is
                        // older than $wgCacheEpoch
-                       if ( array_keys( FormatJson::decode( $row->mr_blob, true ) ) !== $module->getMessages() ||
+                       if ( array_keys( FormatJson::decode( $row->mr_blob, true ) ) !== array_values( array_unique( $module->getMessages() ) ) ||
                                        wfTimestamp( TS_MW, $row->mr_timestamp ) <= $wgCacheEpoch ) {
-                               $retval[$row->mr_resource] = self::updateModule( $module, $lang );
+                               $retval[$row->mr_resource] = self::updateModule( $row->mr_resource, $module, $lang );
                        } else {
                                $retval[$row->mr_resource] = $row->mr_blob;
                        }
@@ -341,9 +344,10 @@ class MessageBlobStore {
 
        /**
         * Generate the message blob for a given module in a given language.
-        * @param $module string Module name
-        * @param $lang string Language code
-        * @return string JSON object
+        *
+        * @param $module ResourceLoaderModule object
+        * @param $lang String: language code
+        * @return String: JSON object
         */
        private static function generateMessageBlob( ResourceLoaderModule $module, $lang ) {
                $messages = array();
@@ -352,6 +356,6 @@ class MessageBlobStore {
                        $messages[$key] = wfMsgExt( $key, array( 'language' => $lang ) );
                }
 
-               return FormatJson::encode( $messages );
+               return FormatJson::encode( (object)$messages );
        }
 }