jenkins-bot has submitted this change and it was merged.
Change subject: Remove Utils::lookup[User]MultilangText() and related functions
......................................................................
Remove Utils::lookup[User]MultilangText() and related functions
Replaced by language fallback chain.
Utils::languageChain(), which has no usage in Wikibase, is removed too.
Other removed functions include those lookup* functions' dependency,
Utils::filterMultilangText() and Utils::reorderArray().
Change-Id: I40ad9647ba489a7950773f21a2ec04273ef1fe9e
---
M lib/includes/LanguageFallbackChain.php
M lib/includes/Utils.php
M lib/tests/phpunit/LanguageFallbackChainTest.php
M repo/Wikibase.hooks.php
M repo/includes/actions/EditEntityAction.php
M repo/includes/actions/ViewEntityAction.php
6 files changed, 164 insertions(+), 250 deletions(-)
Approvals:
Daniel Kinzler: Looks good to me, approved
jenkins-bot: Verified
diff --git a/lib/includes/LanguageFallbackChain.php
b/lib/includes/LanguageFallbackChain.php
index ee91987..5802287 100644
--- a/lib/includes/LanguageFallbackChain.php
+++ b/lib/includes/LanguageFallbackChain.php
@@ -1,6 +1,7 @@
<?php
namespace Wikibase;
+use \Language;
/**
* Object representing a language fallback chain used in Wikibase.
@@ -61,7 +62,7 @@
* 'value' => finally fetched and translated value
* 'language' => language code of the language which final value
is in
* 'source' => language code of the language where the value is
fetched
- * ), or null when no data can be found.
+ * ), or null when no "acceptable" data can be found.
*/
public function extractPreferredValue( $data ) {
@@ -80,4 +81,36 @@
return null;
}
+
+ /**
+ * Try to fetch the best value in a multilingual data array first.
+ * If no "acceptable" value exists, return any value known.
+ *
+ * @param string[] $data Multilingual data with language codes as keys
+ *
+ * @return null|array of three items: array(
+ * 'value' => finally fetched and translated value
+ * 'language' => language code of the language which final value
is in
+ * 'source' => language code of the language where the value is
fetched
+ * ), or null when no data with a valid language code can be found.
+ */
+ public function extractPreferredValueOrAny( $data ) {
+
+ $preferred = $this->extractPreferredValue( $data );
+ if ( $preferred ) {
+ return $preferred;
+ }
+
+ foreach ( $data as $code => $value ) {
+ if ( Language::isValidCode( $code ) ) {
+ return array(
+ 'value' => $value,
+ 'language' => $code,
+ 'source' => $code,
+ );
+ }
+ }
+
+ return null;
+ }
}
diff --git a/lib/includes/Utils.php b/lib/includes/Utils.php
index c6ce523..e12dc70 100644
--- a/lib/includes/Utils.php
+++ b/lib/includes/Utils.php
@@ -232,200 +232,6 @@
}
/**
- * Reorder an array with keys with the order given by a second array.
- *
- * Note that this function will do an intersection and then organize
- * the resulting array in the order given by the array in the second
- * argument. The sorting is not by the keys, but by the order the
- * entries are inserted into the resulting array. Another way to
- * describe this is to change the insertion order of the first array
- * according to the sequence of values in the second array.
- *
- * @since 0.1
- *
- * @param array $array
- * @param array $sequence
- *
- * @return array
- */
- static public function reorderArray( array $array, array $sequence ) {
-
- // First create an intersection with our wanted entries as keys
- $common = array_intersect_key( array_flip( $sequence ), $array
);
-
- // Then do a merge with our previous array, and with a new
intersection
- return array_merge( $common, array_intersect_key( $array,
$common ) );
- }
-
- /**
- * Find the multilingual texts that has keys in the the sequence.
- *
- * The final result will be in the order given by the sequence.
- *
- * @since 0.1
- *
- * @param array $texts the key-value pairs to check for existence
- * @param array $sequence the list of keys that should exist
- *
- * @return array
- */
- static public function filterMultilangText( array $texts = null, array
$sequence = null ) {
-
- // Prerequisites for further processing
- if ( is_null( $texts ) || is_null( $sequence ) ) {
- return array(); // makes the simplest use case
- }
-
- // Do a reordering to get the language strings in correct order
- $texts = \Wikibase\Utils::reorderArray(
- $texts,
- $sequence
- );
-
- // Extract the valid codes
- $validCodes = array_filter(
- array_keys( $texts ),
- function( $langCode ) { return is_string( $langCode )
&& Language::isValidCode( $langCode ); }
- );
-
- // If the valid codes are empty we don't need to process it
further
- if ( empty( $validCodes ) ) {
- return array();
- }
-
- // Filter out everything that matches with a key before we
return the result
- return array_intersect_key( $texts, array_flip( $validCodes ) );
- }
-
- /**
- * Find the first multilingual string that can be used for constructing
a language object. The
- * global chain is always used.
- *
- * Note that a multilingual string from the global chain will always be
globally cachable.
- *
- * @since 0.1
- *
- * @param array $texts the key-value pairs to check for existence
- * @param array $sequence the list of keys that should exist
- * @param array $fallback an array of values that are used as a
replacement if nothing is found
- * The fallback is in the form array( code, text, language
)
- * @return array|null triplet with the initial language code, the text,
and the language object
- */
- static public function lookupMultilangText( array $texts = null, array
$sequence = null, array $fallback = null ) {
-
- // Prerequisites for further processing
- if ( is_null( $texts ) || is_null( $sequence ) ) {
- return $fallback; // makes the simplest use case
- }
-
- // Filter down the result
- $texts = \Wikibase\Utils::filterMultilangText( $texts,
$sequence );
- if ( is_null( $texts ) || empty( $texts ) ) {
- return $fallback;
- }
-
- // Find the first language code we can turn into a language
object
- // Note that the factory call do a pretty dumb cleaning up that
can make this vejjy slow
- foreach ( $texts as $code => $text ) {
- $lang = Language::factory( $code );
- if ( !is_null( $lang ) ) {
- return array( $code, $text, $lang );
- }
- }
-
- // Use the fallback if the previous fails
- return $fallback;
- }
-
- /**
- * Find the first multilingual string that can be used for constructing
a language object
- * for the current user. If a preferred language can't be identified
the global chain is
- * used.
- *
- * Note that a user specific multilingual string is not globally
cachable.
- *
- * FIXME: duplication with @see lookupMultilangText, needs refactor
- *
- * @since 0.1
- *
- * @param array $texts the key-value pairs to check for existence
- * @param array $sequence the list of keys that should exist
- * @param array $fallback an array of values that are used as a
replacement if nothing is found
- * The fallback is in the form array( code, text, language
)
- * @return array|null triplet with the initial language code, the text,
and the language object
- */
- static public function lookupUserMultilangText( array $texts = null,
array $sequence = null, array $fallback = null ) {
- // FIXME: deprecated globals!
- global $wgUser, $wgLang;
-
- // Prerequisites for further processing
- if ( is_null( $texts ) || is_null( $sequence ) ) {
- return $fallback; // makes the simplest use case
- }
-
- // Filter down the result
- $texts = \Wikibase\Utils::filterMultilangText( $texts,
$sequence );
- if ( is_null( $texts ) || empty( $texts ) ) {
- return $fallback;
- }
-
- // Check if we can use the ordinary language
- // This should always be used if possible because this will
match
- // with the user set language
- reset($texts);
- list( $code, $text ) = each( $texts );
- if ( $wgLang->getCode() === $code ) {
- $lang = Language::factory( $code );
- if ( !is_null( $lang ) ) {
- return array( $code, $text, $lang );
- }
- }
-
- // Find the first preferred language code we can turn into a
language object
- // Note that the factory call do a pretty dumb cleaning up that
can make this vejjy slow
- foreach ( $texts as $code => $text ) {
- if ( $wgUser->getOption( "sttl-languages-$code" ) ) {
- $lang = Language::factory( $code );
- if ( !is_null( $lang ) ) {
- return array( $code, $text, $lang );
- }
- }
- }
-
- // Find the first ordinary language code we can turn into a
language object
- // Note that the factory call do a pretty dumb cleaning up that
can make this vejjy slow
- foreach ( $texts as $code => $text ) {
- $lang = Language::factory( $code );
- if ( !is_null( $lang ) ) {
- return array( $code, $text, $lang );
- }
- }
-
- // Use the fallback if the previous fails
- return $fallback;
- }
-
- /**
- * Get the fallback languages prepended with the source language itself.
- *
- * A language chain in this respect is the language itself and all
fallback
- * languagese. Because English is prepended to all languages it is not
a real
- * language group, its only a language group for the purpose of
figuring out
- * the best guess if language attributes are missing.
- *
- * Note that a language chain is globally unique, there will not be any
- * language with two different chains.
- *
- * @since 0.1
- *
- * @param string $langCode the language code for the source language
itself
- * @return array of language codes
- */
- static public function languageChain( $langCode ) {
- return array_merge( array( $langCode ),
Language::getFallbacksFor( $langCode ) );
- }
-
- /**
* Check the given PID to see if it is alive
*
* @since 0.3
diff --git a/lib/tests/phpunit/LanguageFallbackChainTest.php
b/lib/tests/phpunit/LanguageFallbackChainTest.php
index 455c981..839dba8 100644
--- a/lib/tests/phpunit/LanguageFallbackChainTest.php
+++ b/lib/tests/phpunit/LanguageFallbackChainTest.php
@@ -105,4 +105,61 @@
);
}
+ /**
+ * @group WikibaseLib
+ * @dataProvider provideExtractPreferredValueOrAny
+ */
+ public function testExtractPreferredValueOrAny( $lang, $mode, $data,
$expected ) {
+ $factory = new LanguageFallbackChainFactory();
+ $chain = $factory->newFromLanguage( \Language::factory( $lang
), $mode );
+
+ $resolved = $chain->extractPreferredValueOrAny( $data );
+
+ $this->assertEquals( $expected, $resolved );
+ }
+
+ public function provideExtractPreferredValueOrAny() {
+ $data = array(
+ 'en' => 'foo',
+ 'nl' => 'bar',
+ 'zh-cn' => '测试',
+ );
+
+ return array(
+ array( 'en',
LanguageFallbackChainFactory::FALLBACK_ALL, $data, array(
+ 'value' => 'foo',
+ 'language' => 'en',
+ 'source' => 'en',
+ ) ),
+ array( 'nl',
LanguageFallbackChainFactory::FALLBACK_ALL, $data, array(
+ 'value' => 'bar',
+ 'language' => 'nl',
+ 'source' => 'nl',
+ ) ),
+ array( 'de',
LanguageFallbackChainFactory::FALLBACK_SELF, $data, array(
+ 'value' => 'foo',
+ 'language' => 'en',
+ 'source' => 'en',
+ ) ),
+ array( 'fr',
LanguageFallbackChainFactory::FALLBACK_SELF, array(
+ 'kk' => 'baz',
+ ), array(
+ 'value' => 'baz',
+ 'language' => 'kk',
+ 'source' => 'kk',
+ ) ),
+ array( 'it',
LanguageFallbackChainFactory::FALLBACK_SELF, array(
+ ':' => 'qux',
+ 'kk' => 'baz',
+ ), array(
+ 'value' => 'baz',
+ 'language' => 'kk',
+ 'source' => 'kk',
+ ) ),
+ array( 'sr',
LanguageFallbackChainFactory::FALLBACK_SELF, array(
+ ':' => 'qux',
+ ), null ),
+ array( 'ar',
LanguageFallbackChainFactory::FALLBACK_SELF, array(), null ),
+ );
+ }
}
diff --git a/repo/Wikibase.hooks.php b/repo/Wikibase.hooks.php
index 86a9131..212e740 100644
--- a/repo/Wikibase.hooks.php
+++ b/repo/Wikibase.hooks.php
@@ -1,8 +1,8 @@
<?php
namespace Wikibase;
-use Title, Language, User, Revision, WikiPage, EditPage, ContentHandler, Html,
MWException;
-
+use Title, Language, User, Revision, WikiPage, EditPage, ContentHandler, Html,
MWException, RequestContext;
+use Wikibase\Repo\WikibaseRepo;
/**
* File defining the hook handlers for the Wikibase extension.
@@ -782,8 +782,6 @@
return true;
}
- global $wgLang, $wgOut;
-
// The following three vars should all exist, unless there is a
failurre
// somewhere, and then it will fail hard. Better test it now!
$page = new WikiPage( $target );
@@ -820,39 +818,36 @@
return true;
}
- // If this fails we will not find labels and descriptions later,
- // but we will try to get a list of alternate languages. The
following
- // uses the user language as a starting point for the fallback
chain.
- // It could be argued that the fallbacks should be limited to
the user
- // selected languages.
- $lang = $wgLang->getCode();
- static $langStore = array();
- if ( !isset( $langStore[$lang] ) ) {
- $langStore[$lang] = array_merge( array( $lang ),
Language::getFallbacksFor( $lang ) );
+ // Try to find the most preferred available language to display
data in current context.
+ $languageFallbackChainFactory =
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChainFactory();
+ $context = RequestContext::getMain();
+ $languageFallbackChain =
$languageFallbackChainFactory->newFromContext( $context );
+
+ $labelData =
$languageFallbackChain->extractPreferredValueOrAny( $entity->getLabels() );
+ $descriptionData =
$languageFallbackChain->extractPreferredValueOrAny( $entity->getDescriptions()
);
+
+ if ( $labelData ) {
+ $labelText = $labelData['value'];
+ $labelLang = Language::factory( $labelData['language']
);
+ } else {
+ $labelText = '';
+ $labelLang = $context->getLanguage();
}
- // Get the label and description for the first languages on the
chain
- // that doesn't fail, use a fallback if everything fails. This
could
- // use the user supplied list of acceptable languages as a
filter.
- list( , $labelText, $labelLang) = $labelTriplet =
- Utils::lookupMultilangText(
- $entity->getLabels( $langStore[$lang] ),
- $langStore[$lang],
- array( $wgLang->getCode(), null, $wgLang )
- );
- list( , $descriptionText, $descriptionLang) =
$descriptionTriplet =
- Utils::lookupMultilangText(
- $entity->getDescriptions( $langStore[$lang] ),
- $langStore[$lang],
- array( $wgLang->getCode(), null, $wgLang )
- );
+ if ( $descriptionData ) {
+ $descriptionText = $descriptionData['value'];
+ $descriptionLang = Language::factory(
$descriptionData['language'] );
+ } else {
+ $descriptionText = '';
+ $descriptionLang = $context->getLanguage();
+ }
// Go on and construct the link
$idHtml = Html::openElement( 'span', array( 'class' =>
'wb-itemlink-id' ) )
. wfMessage( 'wikibase-itemlink-id-wrapper',
$target->getText() )->inContentLanguage()->escaped()
. Html::closeElement( 'span' );
- $labelHtml = Html::openElement( 'span', array( 'class' =>
'wb-itemlink-label', 'lang' => $labelLang->getCode(), 'dir' =>
$labelLang->getDir() ) )
+ $labelHtml = Html::openElement( 'span', array( 'class' =>
'wb-itemlink-label', 'lang' => $labelLang->getHtmlCode(), 'dir' =>
$labelLang->getDir() ) )
. htmlspecialchars( $labelText )
. Html::closeElement( 'span' );
@@ -861,19 +856,19 @@
. Html::closeElement( 'span' );
// Set title attribute for constructed link, and make tricks
with the directionality to get it right
- $titleText = ( $labelText !== null )
- ? $labelLang->getDirMark() . $labelText .
$wgLang->getDirMark()
+ $titleText = ( $labelText !== '' )
+ ? $labelLang->getDirMark() . $labelText .
$context->getLanguage()->getDirMark()
: $target->getPrefixedText();
- $customAttribs[ 'title' ] = ( $descriptionText !== null ) ?
+ $customAttribs[ 'title' ] = ( $descriptionText !== '' ) ?
wfMessage(
'wikibase-itemlink-title',
$titleText,
- $descriptionLang->getDirMark() .
$descriptionText . $wgLang->getDirMark()
+ $descriptionLang->getDirMark() .
$descriptionText . $context->getLanguage()->getDirMark()
)->inContentLanguage()->text() :
$titleText; // no description, just display the title
then
// add wikibase styles in all cases, so we can format the link
properly:
- $wgOut->addModuleStyles( array( 'wikibase.common' ) );
+ $context->getOutput()->addModuleStyles( array(
'wikibase.common' ) );
wfProfileOut( __METHOD__ );
return true;
diff --git a/repo/includes/actions/EditEntityAction.php
b/repo/includes/actions/EditEntityAction.php
index 21b4832..2db7579 100644
--- a/repo/includes/actions/EditEntityAction.php
+++ b/repo/includes/actions/EditEntityAction.php
@@ -288,15 +288,14 @@
*/
public function getLabelText( EntityContent $content ) {
- $langCode = $this->getContext()->getLanguage()->getCode();
- list( , $labelText, ) =
- Utils::lookupUserMultilangText(
- $content->getEntity()->getLabels(),
- Utils::languageChain( $langCode ),
- array( $langCode, $this->getPageTitle(),
$this->getContext()->getLanguage() )
- );
+ $languageFallbackChain = $this->getLanguageFallbackChain();
+ $labelData =
$languageFallbackChain->extractPreferredValueOrAny(
$content->getEntity()->getLabels() );
- return $labelText;
+ if ( $labelData ) {
+ return $labelData['value'];
+ } else {
+ return $this->getPageTitle();
+ }
}
/**
diff --git a/repo/includes/actions/ViewEntityAction.php
b/repo/includes/actions/ViewEntityAction.php
index 7482534..e50e765 100644
--- a/repo/includes/actions/ViewEntityAction.php
+++ b/repo/includes/actions/ViewEntityAction.php
@@ -20,6 +20,38 @@
abstract class ViewEntityAction extends \ViewAction {
/**
+ * @var LanguageFallbackChain
+ */
+ protected $languageFallbackChain;
+
+ /**
+ * Get the language fallback chain for current context.
+ *
+ * @since 0.4
+ *
+ * @return LanguageFallbackChain
+ */
+ public function getLanguageFallbackChain() {
+ if ( $this->languageFallbackChain === null ) {
+ $this->languageFallbackChain =
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChainFactory()
+ ->newFromContext( $this->getContext() );
+ }
+
+ return $this->languageFallbackChain;
+ }
+
+ /**
+ * Set language fallback chain.
+ *
+ * @since 0.4
+ *
+ * @param LanguageFallbackChain $chain
+ */
+ public function setLanguageFallbackChain( LanguageFallbackChain $chain
) {
+ $this->languageFallbackChain = $chain;
+ }
+
+ /**
* @see Action::getName()
*
* @since 0.1
@@ -194,20 +226,12 @@
$this->getArticle()->view();
// Figure out which label to use for title.
- $langCode = $this->getContext()->getLanguage()->getCode();
- // FIXME: Removed as a quickfix
- /*
- list( $labelCode, $labelText, $labelLang) =
- Utils::lookupUserMultilangText(
- $content->getEntity()->getLabels(),
- Utils::languageChain( $langCode ),
- array( $langCode, $this->getPageTitle(),
$this->getContext()->getLanguage() )
- );
-*/
- // FIXME: this replaces the stuff above
- $labelText = $content->getEntity()->getLabel( $langCode );
+ $languageFallbackChain = $this->getLanguageFallbackChain();
+ $labelData =
$languageFallbackChain->extractPreferredValueOrAny(
$content->getEntity()->getLabels() );
- if ( $labelText === false ) {
+ if ( $labelData ) {
+ $labelText = $labelData['value'];
+ } else {
$idPrefixer =
WikibaseRepo::getDefaultInstance()->getIdFormatter();
$labelText = strtoupper( $idPrefixer->format(
$content->getEntity()->getId() ) );
}
--
To view, visit https://gerrit.wikimedia.org/r/71845
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I40ad9647ba489a7950773f21a2ec04273ef1fe9e
Gerrit-PatchSet: 11
Gerrit-Project: mediawiki/extensions/Wikibase
Gerrit-Branch: master
Gerrit-Owner: Liangent <[email protected]>
Gerrit-Reviewer: Addshore <[email protected]>
Gerrit-Reviewer: Aude <[email protected]>
Gerrit-Reviewer: Daniel Kinzler <[email protected]>
Gerrit-Reviewer: Denny Vrandecic <[email protected]>
Gerrit-Reviewer: Liangent <[email protected]>
Gerrit-Reviewer: jenkins-bot
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits