messagecache: check overridable message array in getMsgFromNamespace()
authorAaron Schulz <aschulz@wikimedia.org>
Mon, 15 Oct 2018 15:08:24 +0000 (08:08 -0700)
committerKrinkle <krinklemail@gmail.com>
Tue, 16 Oct 2018 20:39:38 +0000 (20:39 +0000)
Follow up to a3d6c1411dad.

This avoids extra queries for messages that have a software defined value.

Bug: T193271
Change-Id: I25aa0e27200a0b417721cf1fbd34a82095405b89

includes/cache/MessageCache.php
tests/phpunit/includes/cache/MessageCacheTest.php

index 4e0d0a7..869f768 100644 (file)
@@ -52,6 +52,13 @@ class MessageCache {
         */
        protected $cache;
 
+       /**
+        * Map of (lowercase message key => index) for all software defined messages
+        *
+        * @var array
+        */
+       protected $overridable;
+
        /**
         * @var bool[] Map of (language code => boolean)
         */
@@ -258,6 +265,8 @@ class MessageCache {
                        return true;
                }
 
+               $this->overridable = array_flip( Language::getMessageKeysFor( $code ) );
+
                # 8 lines of code just to say (once) that message cache is disabled
                if ( $this->mDisable ) {
                        static $shownDisabled = false;
@@ -1029,14 +1038,18 @@ class MessageCache {
                                $this->cache->getField( $code, 'HASH' )
                        );
                } else {
-                       // Message page does not exist or does not override a software message.
-                       // Load the message page, utilizing the individual message cache.
-                       $entry = $this->loadCachedMessagePageEntry(
-                               $title,
-                               $code,
-                               $this->cache->getField( $code, 'HASH' )
-                       );
-                       if ( substr( $entry, 0, 1 ) !== ' ' ) {
+                       // Message page either does not exist or does not override a software message
+                       if ( !isset( $this->overridable[$this->contLang->lcfirst( $title )] ) ) {
+                               // Message page does not override any software-defined message. A custom
+                               // message might be defined to have content or settings specific to the wiki.
+                               // Load the message page, utilizing the individual message cache as needed.
+                               $entry = $this->loadCachedMessagePageEntry(
+                                       $title,
+                                       $code,
+                                       $this->cache->getField( $code, 'HASH' )
+                               );
+                       }
+                       if ( $entry === null || substr( $entry, 0, 1 ) !== ' ' ) {
                                // Message does not have a MediaWiki page definition; try hook handlers
                                $message = false;
                                Hooks::run( 'MessagesPreLoad', [ $title, &$message, $code ] );
index 661f325..c340c08 100644 (file)
@@ -196,4 +196,21 @@ class MessageCacheTest extends MediaWikiLangTestCase {
                        [ 'ćaB', 'ćaB' ],
                ];
        }
+
+       public function testNoDBAccess() {
+               global $wgContLanguageCode;
+
+               $dbr = wfGetDB( DB_REPLICA );
+
+               MessageCache::singleton()->getMsgFromNamespace( 'allpages', $wgContLanguageCode );
+
+               $this->assertEquals( 0, $dbr->trxLevel() );
+               $dbr->setFlag( DBO_TRX, $dbr::REMEMBER_PRIOR ); // make queries trigger TRX
+
+               MessageCache::singleton()->getMsgFromNamespace( 'go', $wgContLanguageCode );
+
+               $dbr->restoreFlags();
+
+               $this->assertEquals( 0, $dbr->trxLevel(), "No DB read queries" );
+       }
 }