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