jenkins-bot has submitted this change and it was merged.

Change subject: LanguageWithConversion: Allow lazy language object construction
......................................................................


LanguageWithConversion: Allow lazy language object construction

It seems language object construction is too expensive.

Change-Id: I4ae84a8c2dc40874733d64866db4076ff8f43fd8
---
M lib/includes/LanguageWithConversion.php
M lib/tests/phpunit/LanguageWithConversionTest.php
2 files changed, 161 insertions(+), 40 deletions(-)

Approvals:
  Daniel Kinzler: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/lib/includes/LanguageWithConversion.php 
b/lib/includes/LanguageWithConversion.php
index 5528e75..c8de917 100644
--- a/lib/includes/LanguageWithConversion.php
+++ b/lib/includes/LanguageWithConversion.php
@@ -33,7 +33,9 @@
        static protected $objectCache = array();
 
        protected $language;
+       protected $languageCode;
        protected $sourceLanguage;
+       protected $sourceLanguageCode;
        protected $parentLanguage;
 
        protected $translateCache = array();
@@ -42,50 +44,104 @@
        /**
         * Constructor.
         *
-        * @param $language Language
-        * @param $sourceLanguage null|Language
-        * @param $parentLanguage null|Language
+        * @param null|Language $language
+        * @param string $languageCode
+        * @param null|Language $sourceLanguage
+        * @param null|string $sourceLanguageCode
+        * @param null|Language $parentLanguage
         */
-       protected function __construct( Language $language, $sourceLanguage, 
$parentLanguage ) {
+       protected function __construct( $language, $languageCode, 
$sourceLanguage, $sourceLanguageCode, $parentLanguage ) {
                $this->language = $language;
+               $this->languageCode = $languageCode;
                $this->sourceLanguage = $sourceLanguage;
+               $this->sourceLanguageCode = $sourceLanguageCode;
                $this->parentLanguage = $parentLanguage;
+       }
+
+       /**
+        * Validate a language code. Logic taken from class Language.
+        *
+        * @param string $code Language code
+        *
+        * @return string Validated and normalized code.
+        *
+        * @throw MWException on invalid code
+        */
+       public static function validateLanguageCode( $code ) {
+               global $wgDummyLanguageCodes;
+
+               if ( isset( $wgDummyLanguageCodes[$code] ) ) {
+                       $code = $wgDummyLanguageCodes[$code];
+               }
+
+               if ( !Language::isValidCode( $code )
+                       || strcspn( $code, ":/\\\000" ) !== strlen( $code )
+               ) {
+                       throw new MWException( __METHOD__ . ': invalid language 
code ' . $code );
+               }
+
+               return $code;
        }
 
        /**
         * Get a LanguageWithConversion object.
         *
-        * @param $language Language: Language for this object
-        * @param $sourceLanguage null|Language:
-        *          Source language if this is a converted language, or null
+        * @param $language Language|string: Language (code) for this object
+        * @param $sourceLanguage null|Language|string:
+        *          Source language (code) if this is a converted language, or 
null
         * @return LanguageWithConversion
         */
-       public static function factory( Language $language, $sourceLanguage = 
null ) {
-               $sourceCode = $sourceLanguage ? $sourceLanguage->getCode() : '';
-               if ( isset( 
self::$objectCache[$language->getCode()][$sourceCode] ) ) {
-                       return 
self::$objectCache[$language->getCode()][$sourceCode];
+       public static function factory( $language, $sourceLanguage = null ) {
+               if ( is_string( $language ) ) {
+                       $languageCode = self::validateLanguageCode( $language );
+                       $language = null;
+               } else {
+                       $languageCode = $language->getCode();
                }
 
-               if ( $sourceLanguage ) {
-                       $parentLanguage = $language->getParentLanguage();
-                       $sourceParentLanguage = 
$sourceLanguage->getParentLanguage();
-                       if ( !$parentLanguage || !$sourceParentLanguage ) {
-                               throw new MWException( __METHOD__ .
-                                       ': either $language or $sourceLanguage 
does not support conversion.'
-                               );
+               if ( is_string( $sourceLanguage ) ) {
+                       $sourceLanguageCode = self::validateLanguageCode( 
$sourceLanguage );
+                       $sourceLanguage = null;
+               } elseif ( $sourceLanguage === null ) {
+                       $sourceLanguageCode = null;
+               } else {
+                       $sourceLanguageCode = $sourceLanguage->getCode();
+               }
+
+               $sourceLanguageKey = $sourceLanguageCode === null ? '' : 
$sourceLanguageCode;
+               if ( isset( 
self::$objectCache[$languageCode][$sourceLanguageKey] ) ) {
+                       return 
self::$objectCache[$languageCode][$sourceLanguageKey];
+               }
+
+               if ( $sourceLanguageCode !== null ) {
+                       if ( !$language ) {
+                               $language = Language::factory( $languageCode );
                        }
-                       if ( $parentLanguage->getCode() !== 
$sourceParentLanguage->getCode() ) {
-                               throw new MWException( __METHOD__ .
-                                       ': $language and $sourceLanguage do not 
share the same parent language'
-                               );
+                       $parentLanguage = $language->getParentLanguage();
+
+                       if ( !$parentLanguage ) {
+                               throw new MWException( __METHOD__ . ': 
$language does not support conversion' );
+                       }
+
+                       if ( !$parentLanguage->hasVariant( $sourceLanguageCode 
) ) {
+                               throw new MWException( __METHOD__ . ': given 
languages do not have the same parent language' );
                        }
                } else {
                        $parentLanguage = null;
                }
 
-               $object = new self( $language, $sourceLanguage, $parentLanguage 
);
-               self::$objectCache[$language->getCode()][$sourceCode] = $object;
+               $object = new self( $language, $languageCode, $sourceLanguage, 
$sourceLanguageCode, $parentLanguage );
+               self::$objectCache[$languageCode][$sourceLanguageKey] = $object;
                return $object;
+       }
+
+       /**
+        * Get the code of the language this object wraps.
+        *
+        * @return string
+        */
+       public function getLanguageCode() {
+               return $this->languageCode;
        }
 
        /**
@@ -94,28 +150,58 @@
         * @return Language
         */
        public function getLanguage() {
+               if ( !$this->language ) {
+                       $this->language = Language::factory( 
$this->languageCode );
+               }
+
                return $this->language;
        }
 
        /**
-        * Get the source language defined. Semi-private for unit testing etc.
+        * Get the code of the source language defined.
+        *
+        * @return string
+        */
+       public function getSourceLanguageCode() {
+               return $this->sourceLanguageCode;
+       }
+
+       /**
+        * Get the source language defined.
         *
         * @return Language
         */
        public function getSourceLanguage() {
+               if ( $this->sourceLanguageCode !== null && 
!$this->sourceLanguage ) {
+                       $this->sourceLanguage = Language::factory( 
$this->sourceLanguageCode );
+               }
+
                return $this->sourceLanguage;
        }
 
        /**
-        * Get the language where data should be fetched.
+        * Get the code of the language where data should be fetched.
+        *
+        * @return string
+        */
+       public function getFetchLanguageCode() {
+               if ( $this->sourceLanguageCode !== null ) {
+                       return $this->sourceLanguageCode;
+               } else {
+                       return $this->languageCode;
+               }
+       }
+
+       /**
+        * Get the language where data should be fetched. Generally this 
doesn't need to be used.
         *
         * @return Language
         */
        public function getFetchLanguage() {
-               if ( $this->sourceLanguage ) {
-                       return $this->sourceLanguage;
+               if ( $this->sourceLanguageCode !== null ) {
+                       return $this->getSourceLanguage();
                } else {
-                       return $this->language;
+                       return $this->getLanguage();
                }
        }
 
diff --git a/lib/tests/phpunit/LanguageWithConversionTest.php 
b/lib/tests/phpunit/LanguageWithConversionTest.php
index 2fe6fd1..c13a6ac 100644
--- a/lib/tests/phpunit/LanguageWithConversionTest.php
+++ b/lib/tests/phpunit/LanguageWithConversionTest.php
@@ -18,6 +18,34 @@
  */
 class LanguageWithConversionTest extends \MediaWikiTestCase {
 
+       private function assertLanguageWithConversion( $obj,
+               $expectedLangCode, $expectedSourceLangCode, 
$expectedFetchLangCode
+       ) {
+               $this->assertEquals( $expectedLangCode, 
$obj->getLanguage()->getCode() );
+               $this->assertEquals( $expectedLangCode, $obj->getLanguageCode() 
);
+               if ( $expectedSourceLangCode === null ) {
+                       $this->assertNull( $obj->getSourceLanguage() );
+                       $this->assertNull( $obj->getSourceLanguageCode() );
+               } else {
+                       $this->assertEquals( $expectedSourceLangCode, 
$obj->getSourceLanguage()->getCode() );
+                       $this->assertEquals( $expectedSourceLangCode, 
$obj->getSourceLanguageCode() );
+               }
+               $this->assertEquals( $expectedFetchLangCode, 
$obj->getFetchLanguage()->getCode() );
+               $this->assertEquals( $expectedFetchLangCode, 
$obj->getFetchLanguageCode() );
+       }
+
+       /**
+        * @dataProvider provideFactory
+        */
+       public function testFactoryCode( $langCode, $sourceLangCode,
+               $expectedLangCode, $expectedSourceLangCode, 
$expectedFetchLangCode
+       ) {
+               $obj = LanguageWithConversion::factory( $langCode, 
$sourceLangCode );
+               $this->assertLanguageWithConversion( $obj,
+                       $expectedLangCode, $expectedSourceLangCode, 
$expectedFetchLangCode
+               );
+       }
+
        /**
         * @dataProvider provideFactory
         */
@@ -26,24 +54,29 @@
        ) {
                $obj = LanguageWithConversion::factory( Language::factory( 
$langCode ),
                        $sourceLangCode === null ? null : Language::factory( 
$sourceLangCode ) );
-               $this->assertEquals( $obj->getLanguage()->getCode(), 
$expectedLangCode );
-               if ( $expectedSourceLangCode === null ) {
-                       $this->assertNull( $obj->getSourceLanguage() );
-               } else {
-                       $this->assertEquals( 
$obj->getSourceLanguage()->getCode(), $expectedSourceLangCode );
-               }
-               $this->assertEquals( $obj->getFetchLanguage()->getCode(), 
$expectedFetchLangCode );
+               $this->assertLanguageWithConversion( $obj,
+                       $expectedLangCode, $expectedSourceLangCode, 
$expectedFetchLangCode
+               );
        }
 
        public function provideFactory() {
                return array(
                        array( 'en', null, 'en', null, 'en' ),
                        array( 'zh', null, 'zh', null, 'zh' ),
+                       array( 'zh-classical', null, 'lzh', null, 'lzh' ),
                        array( 'zh-cn', null, 'zh-cn', null, 'zh-cn' ),
                        array( 'zh', 'zh-cn', 'zh', 'zh-cn', 'zh-cn' ),
                        array( 'zh-cn', 'zh', 'zh-cn', 'zh', 'zh' ),
                        array( 'zh-cn', 'zh-tw', 'zh-cn', 'zh-tw', 'zh-tw' ),
                );
+       }
+
+       /**
+        * @dataProvider provideFactoryException
+        * @expectedException MWException
+        */
+       public function testFactoryCodeException( $langCode, $sourceLangCode ) {
+               LanguageWithConversion::factory( $langCode, $sourceLangCode );
        }
 
        /**
@@ -57,6 +90,10 @@
 
        public function provideFactoryException() {
                return array(
+                       array( ':', null ),
+                       array( '/', null ),
+                       array( '/', ':' ),
+                       array( 'en', '/' ),
                        array( 'en', 'de' ),
                        array( 'en', 'en-gb' ),
                        array( 'en-gb', 'en' ),
@@ -73,8 +110,7 @@
         * @dataProvider provideTranslate
         */
        public function testTranslate( $langCode, $sourceLangCode, 
$translations ) {
-               $obj = LanguageWithConversion::factory( Language::factory( 
$langCode ),
-                       $sourceLangCode === null ? null : Language::factory( 
$sourceLangCode ) );
+               $obj = LanguageWithConversion::factory( $langCode, 
$sourceLangCode );
                foreach ( $translations as $text => $translatedText ) {
                        $this->assertEquals( $obj->translate( $text ), 
$translatedText );
                }
@@ -84,8 +120,7 @@
         * @dataProvider provideTranslate
         */
        public function testTranslateBatched( $langCode, $sourceLangCode, 
$translations ) {
-               $obj = LanguageWithConversion::factory( Language::factory( 
$langCode ),
-                       $sourceLangCode === null ? null : Language::factory( 
$sourceLangCode ) );
+               $obj = LanguageWithConversion::factory( $langCode, 
$sourceLangCode );
                foreach ( $translations as $text => $translatedText ) {
                        $obj->prepareForTranslate( $text );
                }

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I4ae84a8c2dc40874733d64866db4076ff8f43fd8
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Liangent <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Denny Vrandecic <[email protected]>
Gerrit-Reviewer: jenkins-bot

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

Reply via email to