Daniel Kinzler has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/245484

Change subject: Move singletons of MediaWikiTitleCodec and 
MediaWikiPageLinkRenderer to MediaWikiServices.
......................................................................

Move singletons of MediaWikiTitleCodec and MediaWikiPageLinkRenderer to 
MediaWikiServices.

Change-Id: Icda128d4b03901efdab9c0c6ced142b3a7fe6671
---
M includes/MediaWikiServices.php
M includes/Title.php
M includes/specials/SpecialCategories.php
M includes/specials/SpecialLinkSearch.php
M tests/phpunit/includes/MediaWikiServicesTest.php
5 files changed, 148 insertions(+), 38 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core 
refs/changes/84/245484/4

diff --git a/includes/MediaWikiServices.php b/includes/MediaWikiServices.php
index 3606ea3..c318d2d 100644
--- a/includes/MediaWikiServices.php
+++ b/includes/MediaWikiServices.php
@@ -74,12 +74,27 @@
        }
 
        /**
+        * @return Language
+        */
+       public function getContentLanguage() {
+               return $this->getConfig()->get( 'ContLang' );
+       }
+
+       /**
+        * @return string language code
+        */
+       public function getContentLanguageCode() {
+               return $this->getConfig()->get( 'LanguageCode' );
+       }
+
+       /**
         * @param string $name
+        * @param string $reset if 'reset', creation of a fresh instance is 
forced.
         *
         * @return object
         */
-       private function getService( $name ) {
-               if ( !isset( $this->services[$name] ) ) {
+       private function getService( $name, $reset = '' ) {
+               if ( $reset === 'reset' || !isset( $this->services[$name] ) ) {
                        $this->services[$name] = $this->createService( $name );
                }
 
@@ -120,4 +135,87 @@
                return new CachingSiteStore( $siteStore, $cache );
        }
 
+       private $titleCodecFingerprint = null;
+
+       /**
+        * Checks the global configuration variables that affect the TitleCodec 
have
+        * been modified.
+        *
+        * @note This is a hack around the fact that a) the configuration 
object may depend on mutable
+        * global state and b) the title codec is accessed via static methods 
in Title. Once TitleParser
+        * and TitleFormatter instances are property getting injected in all 
places that need them,
+        * there will no longer be need to purge the default instance when the 
config changes.
+        * Once that is the case, this method should be removed.
+        *
+        * @return bool true if the global configuration variables that affect 
the TitleCodec have
+        * been modified.
+        */
+       private function checkConfigForTitleCodecChanged() {
+               $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
+               $contLang = $this->getConfig()->get( 'ContLang' );
+
+               // $wgContLang and $wgLocalInterwikis may change (especially 
while testing),
+               // make sure we are using the right one. To detect changes over 
the course
+               // of a request, we remember a fingerprint of the config used 
to create the
+               // codec singleton, and re-create it if the fingerprint doesn't 
match.
+               $fingerprint = spl_object_hash( $contLang ) . '|' . join( '+', 
$localInterwikis );
+               $changed = ( $fingerprint !== $this->titleCodecFingerprint );
+
+               $this->titleCodecFingerprint = $fingerprint;
+               return $changed;
+       }
+
+       /**
+        * @return TitleParser
+        */
+       public function getTitleParser() {
+               return $this->getService( 'TitleCodec', 
$this->checkConfigForTitleCodecChanged() ? 'reset' : '' );
+       }
+
+       /**
+        * @return TitleFormatter
+        */
+       public function getTitleFormatter() {
+               // XXX: we may want to manage this per language, or at least 
content language vs user language.
+               return $this->getService( 'TitleCodec', 
$this->checkConfigForTitleCodecChanged() ? 'reset' : '' );
+       }
+
+       /**
+        * @note should be called by createService() only!
+        */
+       private function newTitleCodec() {
+               $localInterwikis = $this->getConfig()->get( 'LocalInterwikis' );
+
+               return new MediaWikiTitleCodec(
+                       $this->getContentLanguage(),
+                       $this->getGenderCache(),
+                       $localInterwikis
+               );
+       }
+
+       /**
+        * @return GenderCache
+        */
+       public function getGenderCache() {
+               // @todo: manage the GenderCache singleton here instead of in 
the GenderCache class.
+               return GenderCache::singleton();
+       }
+
+       /**
+        * @return PageLinkRenderer
+        */
+       public function getPageLinkRenderer() {
+               // XXX: we may want to manage this per language, or at least 
content language vs user language.
+               return $this->getService( 'PageLinkRenderer' );
+       }
+
+       /**
+        * @note should be called by createService() only!
+        */
+       private function newPageLinkRenderer() {
+               return new MediaWikiPageLinkRenderer(
+                       $this->getTitleFormatter()
+               );
+       }
+
 }
diff --git a/includes/Title.php b/includes/Title.php
index 9ada4f3..16b7d7c 100644
--- a/includes/Title.php
+++ b/includes/Title.php
@@ -170,31 +170,7 @@
         * @return TitleParser
         */
        private static function getTitleParser() {
-               global $wgContLang, $wgLocalInterwikis;
-
-               static $titleCodec = null;
-               static $titleCodecFingerprint = null;
-
-               // $wgContLang and $wgLocalInterwikis may change (especially 
while testing),
-               // make sure we are using the right one. To detect changes over 
the course
-               // of a request, we remember a fingerprint of the config used 
to create the
-               // codec singleton, and re-create it if the fingerprint doesn't 
match.
-               $fingerprint = spl_object_hash( $wgContLang ) . '|' . join( 
'+', $wgLocalInterwikis );
-
-               if ( $fingerprint !== $titleCodecFingerprint ) {
-                       $titleCodec = null;
-               }
-
-               if ( !$titleCodec ) {
-                       $titleCodec = new MediaWikiTitleCodec(
-                               $wgContLang,
-                               GenderCache::singleton(),
-                               $wgLocalInterwikis
-                       );
-                       $titleCodecFingerprint = $fingerprint;
-               }
-
-               return $titleCodec;
+               return MediaWikiServices::getInstance()->getTitleParser();
        }
 
        /**
@@ -206,9 +182,7 @@
         * @return TitleFormatter
         */
        private static function getTitleFormatter() {
-               // NOTE: we know that getTitleParser() returns a 
MediaWikiTitleCodec,
-               //      which implements TitleFormatter.
-               return self::getTitleParser();
+               return MediaWikiServices::getInstance()->getTitleFormatter();
        }
 
        function __construct() {
diff --git a/includes/specials/SpecialCategories.php 
b/includes/specials/SpecialCategories.php
index cea6ceb..257c490 100644
--- a/includes/specials/SpecialCategories.php
+++ b/includes/specials/SpecialCategories.php
@@ -59,9 +59,7 @@
         */
        private function initServices() {
                if ( !$this->linkRenderer ) {
-                       $lang = $this->getContext()->getLanguage();
-                       $titleFormatter = new MediaWikiTitleCodec( $lang, 
GenderCache::singleton() );
-                       $this->linkRenderer = new MediaWikiPageLinkRenderer( 
$titleFormatter );
+                       $this->linkRenderer = 
MediaWikiServices::getInstance()->getPageLinkRenderer();
                }
        }
 
diff --git a/includes/specials/SpecialLinkSearch.php 
b/includes/specials/SpecialLinkSearch.php
index f474867..eb5ed78 100644
--- a/includes/specials/SpecialLinkSearch.php
+++ b/includes/specials/SpecialLinkSearch.php
@@ -68,11 +68,9 @@
         * This allows for dependency injection even though we don't control 
object creation.
         */
        private function initServices() {
-               global $wgLanguageCode;
                if ( !$this->linkRenderer ) {
-                       $lang = Language::factory( $wgLanguageCode );
-                       $titleFormatter = new MediaWikiTitleCodec( $lang, 
GenderCache::singleton() );
-                       $this->linkRenderer = new MediaWikiPageLinkRenderer( 
$titleFormatter );
+                       $this->linkRenderer = $this->linkRenderer =
+                               
MediaWikiServices::getInstance()->getPageLinkRenderer();
                }
        }
 
diff --git a/tests/phpunit/includes/MediaWikiServicesTest.php 
b/tests/phpunit/includes/MediaWikiServicesTest.php
index a776920..60810a7 100644
--- a/tests/phpunit/includes/MediaWikiServicesTest.php
+++ b/tests/phpunit/includes/MediaWikiServicesTest.php
@@ -5,7 +5,7 @@
  *
  * @group MediaWiki
  */
-class MediaWikiServicesTest extends PHPUnit_Framework_TestCase {
+class MediaWikiServicesTest extends MediaWikiTestCase {
 
        /**
         * @param string $expectedType expected class
@@ -34,4 +34,46 @@
                $this->assertGetterReturnType( 'SiteLookup', 'getSiteLookup' );
        }
 
+       public function testGetGenderCache() {
+               $this->assertGetterReturnType( 'GenderCache', 'getGenderCache' 
);
+       }
+
+       public function testGetTitleFormatter() {
+               $this->assertGetterReturnType( 'TitleFormatter', 
'getTitleFormatter' );
+       }
+
+       /**
+        * Test that the TitleFormatter instance gets automatically reset when 
affected by
+        * config changes, but is re-used otherwise.
+        */
+       public function testGetTitleFormatter_reset() {
+               global $wgContLang;
+               $this->stashMwGlobals( 'wgContLang' );
+
+               $locator = MediaWikiServices::getInstance();
+               $originalFormatter = $locator->getTitleFormatter();
+
+               $this->assertSame(
+                       $originalFormatter,
+                       $locator->getTitleFormatter(),
+                       'service instance should be cached'
+               );
+
+               $wgContLang = Language::factory( 'qqxyz' );
+
+               $this->assertNotSame(
+                       $originalFormatter,
+                       $locator->getTitleFormatter(),
+                       'service instance should be reset when $wgLanguageCode 
changes'
+               );
+       }
+
+       public function testGetTitleParser() {
+               $this->assertGetterReturnType( 'TitleParser', 'getTitleParser' 
);
+       }
+
+       public function testGetPageLinkRenderer() {
+               $this->assertGetterReturnType( 'PageLinkRenderer', 
'getPageLinkRenderer' );
+       }
+
 }

-- 
To view, visit https://gerrit.wikimedia.org/r/245484
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Icda128d4b03901efdab9c0c6ced142b3a7fe6671
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to