jenkins-bot has submitted this change and it was merged.
Change subject: Include preferred labels / descriptions for entities in JS on
EntityView
......................................................................
Include preferred labels / descriptions for entities in JS on EntityView
EntityView now initializes a fallback chain for current context, and in
experimental mode, wbUsedEntities and wbEntity include data with fallback
using this chain, to have data to be viewed by final user included.
Change-Id: Ic8ad24f49ba7fafe11e3dceb5d36e18d5b9ef19f
---
M lib/includes/LanguageFallbackChainFactory.php
M repo/includes/EntityView.php
M repo/includes/WikibaseRepo.php
M repo/includes/serializers/FetchedEntityContentSerializer.php
M repo/tests/phpunit/includes/EntityViewTest.php
M repo/tests/phpunit/includes/serializers/FetchedEntityContentSerializerTest.php
6 files changed, 158 insertions(+), 11 deletions(-)
Approvals:
Daniel Kinzler: Looks good to me, approved
jenkins-bot: Verified
diff --git a/lib/includes/LanguageFallbackChainFactory.php
b/lib/includes/LanguageFallbackChainFactory.php
index b2106f6..6860e08 100644
--- a/lib/includes/LanguageFallbackChainFactory.php
+++ b/lib/includes/LanguageFallbackChainFactory.php
@@ -62,6 +62,21 @@
public $userLanguageCache;
/**
+ * @var bool
+ */
+ public $anonymousPageViewCached;
+
+ /**
+ * Constructor.
+ *
+ * @param $anonymousPageViewCached bool
+ * Whether full page outputs are cached for anons, so some
fine-grained fallbacks shouldn't be used for them.
+ */
+ public function __construct( $anonymousPageViewCached = false ) {
+ $this->anonymousPageViewCached = $anonymousPageViewCached;
+ }
+
+ /**
* Get the fallback chain based a single language, and specified
fallback level.
*
* @param Language $language
@@ -329,4 +344,22 @@
return $chain;
}
+ /**
+ * Construct the fallback chain based on a context for direct page
views.
+ * Caching mechanisms used are taken into consideration.
+ *
+ * @param IContextSource $context
+ *
+ * @return LanguageFallbackChain
+ */
+ public function newFromContextForPageView( IContextSource $context ) {
+ if ( $this->anonymousPageViewCached &&
$context->getUser()->isAnon() ) {
+ // Anonymous users share the same Squid cache, which is
splitted by URL.
+ // That means we can't do anything except for what
completely depends by URL such as &uselang=.
+ return $this->newFromLanguage( $context->getLanguage()
);
+ } else {
+ return $this->newFromContext( $context );
+ }
+ }
+
}
diff --git a/repo/includes/EntityView.php b/repo/includes/EntityView.php
index 1a6a693..a5b816e 100644
--- a/repo/includes/EntityView.php
+++ b/repo/includes/EntityView.php
@@ -88,6 +88,11 @@
protected $dataTypeLookup;
/**
+ * @var LanguageFallbackChain
+ */
+ protected $languageFallbackChain;
+
+ /**
* Maps entity types to the corresponding entity view.
* FIXME: remove this stuff, big OCP violation
*
@@ -112,6 +117,7 @@
* @param EntityLookup $entityLookup
* @param EntityTitleLookup $entityTitleLookup
* @param Lib\EntityIdFormatter $idFormatter
+ * @param LanguageFallbackChain $languageFallbackChain
*/
public function __construct(
IContextSource $context,
@@ -119,7 +125,8 @@
PropertyDataTypeLookup $dataTypeLookup,
EntityLookup $entityLookup,
EntityTitleLookup $entityTitleLookup,
- EntityIdFormatter $idFormatter
+ EntityIdFormatter $idFormatter,
+ LanguageFallbackChain $languageFallbackChain
) {
$this->setContext( $context );
$this->valueFormatters = $valueFormatters;
@@ -127,6 +134,7 @@
$this->entityLookup = $entityLookup;
$this->entityTitleLookup = $entityTitleLookup;
$this->idFormatter = $idFormatter;
+ $this->languageFallbackChain = $languageFallbackChain;
}
/**
@@ -858,6 +866,7 @@
// TODO: use injected id formatter
$serializationOptions = new EntitySerializationOptions(
WikibaseRepo::getDefaultInstance()->getIdFormatter() );
+ $serializationOptions->setLanguages( Utils::getLanguageCodes()
+ array( $langCode => $this->languageFallbackChain ) );
$serializerFactory = new SerializerFactory();
$serializer = $serializerFactory->newSerializerForObject(
$entity, $serializationOptions );
@@ -897,13 +906,17 @@
$entities = $this->entityLookup->getEntities( $entityIds );
$entityInfo = array();
- $serializer =
FetchedEntityContentSerializer::newForFrontendStore( $langCode );
+ $serializer =
FetchedEntityContentSerializer::newForFrontendStore( $langCode,
$this->languageFallbackChain );
foreach( $entities as $prefixedId => $entity ) {
if( $entity === null ) {
continue;
}
$entityContent = $entityContentFactory->getFromId(
$entity->getId() );
+ if ( !$entityContent ) {
+ // It's missing in the database, but we've
already got an $entity (possibly from a MockRepository).
+ $entityContent =
$entityContentFactory->newFromEntity( $entity );
+ }
$entityInfo[ $prefixedId ] =
$serializer->getSerialized( $entityContent );
}
@@ -921,6 +934,7 @@
* @param Lib\PropertyDataTypeLookup $dataTypeLookup
* @param EntityLookup $entityLookup
* @param IContextSource|null $context
+ * @param LanguageFallbackChain|null $languageFallbackChain Overrides
any language fallback chain created inside, for testing
*
* @throws \MWException
* @return EntityView
@@ -930,7 +944,8 @@
ValueFormatterFactory $valueFormatters,
PropertyDataTypeLookup $dataTypeLookup,
EntityLookup $entityLookup,
- IContextSource $context = null
+ IContextSource $context = null,
+ LanguageFallbackChain $languageFallbackChain = null
) {
$type = $entity->getEntity()->getType();
@@ -945,7 +960,19 @@
$idFormatter =
WikibaseRepo::getDefaultInstance()->getIdFormatter();
$entityTitleLookup = EntityContentFactory::singleton();
- $instance = new self::$typeMap[ $type ]( $context,
$valueFormatters, $dataTypeLookup, $entityLookup, $entityTitleLookup,
$idFormatter );
+ if ( !$languageFallbackChain ) {
+ $factory =
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChainFactory();
+ if ( defined( 'WB_EXPERIMENTAL_FEATURES' ) &&
WB_EXPERIMENTAL_FEATURES ) {
+ $languageFallbackChain =
$factory->newFromContextForPageView( $context );
+ } else {
+ # Effectively disables fallback.
+ $languageFallbackChain =
$factory->newFromLanguage(
+ $context->getLanguage(),
LanguageFallbackChainFactory::FALLBACK_SELF
+ );
+ }
+ }
+
+ $instance = new self::$typeMap[ $type ]( $context,
$valueFormatters, $dataTypeLookup, $entityLookup, $entityTitleLookup,
$idFormatter, $languageFallbackChain );
return $instance;
}
}
diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php
index 40065e1..8a29e87 100644
--- a/repo/includes/WikibaseRepo.php
+++ b/repo/includes/WikibaseRepo.php
@@ -305,7 +305,12 @@
*/
public function getLanguageFallbackChainFactory() {
if ( $this->languageFallbackChainFactory === null ) {
- $this->languageFallbackChainFactory = new
LanguageFallbackChainFactory();
+ global $wgUseSquid;
+ // The argument is about whether full page output
(OutputPage, specifically JS vars in it currently)
+ // is cached for anons, where the only caching
mechanism in use now is Squid.
+ $this->languageFallbackChainFactory = new
LanguageFallbackChainFactory(
+ /* $anonymousPageViewCached = */ $wgUseSquid
+ );
}
return $this->languageFallbackChainFactory;
diff --git a/repo/includes/serializers/FetchedEntityContentSerializer.php
b/repo/includes/serializers/FetchedEntityContentSerializer.php
index 36dcb9e..45804d0 100644
--- a/repo/includes/serializers/FetchedEntityContentSerializer.php
+++ b/repo/includes/serializers/FetchedEntityContentSerializer.php
@@ -9,6 +9,8 @@
use Wikibase\Entity;
use Wikibase\Repo\WikibaseRepo;
use Wikibase\EntityContent;
+use Wikibase\LanguageFallbackChain;
+use Wikibase\LanguageFallbackChainFactory;
use Wikibase\Lib\Serializers\SerializerObject;
use Wikibase\Lib\Serializers\EntitySerializationOptions;
use Wikibase\Lib\Serializers\SerializerFactory;
@@ -89,13 +91,20 @@
* @since 0.5
*
* @param string $primaryLanguage
+ * @param LanguageFallbackChain|null $languageFallbackChain
* @return FetchedEntityContentSerializer
*/
- public static function newForFrontendStore( $primaryLanguage ) {
+ public static function newForFrontendStore( $primaryLanguage,
LanguageFallbackChain $languageFallbackChain ) {
$entitySerializationOptions =
new EntitySerializationOptions(
WikibaseRepo::getDefaultInstance()->getIdFormatter() );
$entitySerializationOptions->setProps( array( 'labels',
'descriptions', 'datatype' ) );
- $entitySerializationOptions->setLanguages( array(
$primaryLanguage ) );
+ if ( !$languageFallbackChain ) {
+ $languageFallbackChainFactory =
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChain();
+ $languageFallbackChain =
$languageFallbackChainFactory->newFromLanguageCode(
+ $primaryLanguage,
LanguageFallbackChainFactory::FALLBACK_SELF
+ );
+ }
+ $entitySerializationOptions->setLanguages( array(
$primaryLanguage => $languageFallbackChain ) );
$fetchedEntityContentSerializationOptions =
new FetchedEntityContentSerializationOptions(
$entitySerializationOptions );
diff --git a/repo/tests/phpunit/includes/EntityViewTest.php
b/repo/tests/phpunit/includes/EntityViewTest.php
index 24fe2e8..239e9bf 100644
--- a/repo/tests/phpunit/includes/EntityViewTest.php
+++ b/repo/tests/phpunit/includes/EntityViewTest.php
@@ -11,9 +11,12 @@
use Wikibase\DataModel\Entity\PropertyId;
use Wikibase\EntityContent;
use Wikibase\EntityContentFactory;
+use Wikibase\EntityLookup;
use Wikibase\EntityView;
use Wikibase\Item;
use Wikibase\ItemContent;
+use Wikibase\LanguageFallbackChain;
+use Wikibase\LanguageFallbackChainFactory;
use Wikibase\Lib\InMemoryDataTypeLookup;
use Wikibase\Property;
use Wikibase\PropertyContent;
@@ -40,9 +43,13 @@
*/
class EntityViewTest extends \PHPUnit_Framework_TestCase {
- protected function newEntityView( EntityContent $entityContent ) {
+ protected function newEntityView( EntityContent $entityContent,
EntityLookup $entityLoader = null,
+ \IContextSource $context = null, LanguageFallbackChain
$languageFallbackChain = null
+ ) {
$valueFormatters = new ValueFormatterFactory( array() );
- $entityLoader = new MockRepository();
+ if ( !$entityLoader ) {
+ $entityLoader = new MockRepository();
+ }
$p11 = new PropertyId( 'p11' );
$p23 = new PropertyId( 'p23' );
@@ -60,7 +67,9 @@
$entityContent,
$valueFormatters,
$dataTypeLookup,
- $entityLoader
+ $entityLoader,
+ $context,
+ $languageFallbackChain
);
return $entityView;
@@ -269,4 +278,64 @@
array( PropertyContent::newEmpty() )
);
}
+
+ /**
+ * @dataProvider provideRegisterJsConfigVars
+ */
+ public function testRegisterJsConfigVars( EntityContent $entityContent,
EntityLookup $entityLoader,
+ $context, LanguageFallbackChain $languageFallbackChain,
$langCode, $editableView, $expected
+ ) {
+ $entityView = $this->newEntityView( $entityContent,
$entityLoader, $context, $languageFallbackChain );
+ $out = new \OutputPage( new \RequestContext() );
+ $entityView->registerJsConfigVars( $out, $entityContent,
$langCode, $editableView );
+ $actual = array_intersect_key( $out->mJsConfigVars, $expected );
+ ksort( $expected );
+ ksort( $actual );
+ $this->assertEquals( $expected, $actual );
+ }
+
+ public function provideRegisterJsConfigVars() {
+ $entityContentFactory = EntityContentFactory::singleton();
+ $languageFallbackChainFactory = new
LanguageFallbackChainFactory();
+
+ $argLists = array();
+
+ $entity = Item::newEmpty();
+ $entity->setLabel( 'de', 'foo' );
+ $entity->setId( 49 );
+ $content = $entityContentFactory->newFromEntity( $entity );
+ $q98 = new ItemId( 'Q98' );
+ $entityQ98 = Item::newEmpty();
+ $entityQ98->setLabel( 'de', 'bar' );
+ $entityQ98->setId( $q98 );
+ $entityLoader = new MockRepository();
+ $entityLoader->putEntity( $entityQ98 );
+ $p11 = new PropertyId( 'p11' );
+ $entity->addClaim( new Claim( new PropertyValueSnak( $p11, new
EntityIdValue( $q98 ) ) ) );
+ $languageFallbackChain =
$languageFallbackChainFactory->newFromLanguageCode(
+ 'de-formal', LanguageFallbackChainFactory::FALLBACK_ALL
+ ); // with fallback to German
+ $argLists[] = array( $content, $entityLoader, null,
$languageFallbackChain, 'fr', true, array(
+ 'wbEntityType' => 'item',
+ 'wbDataLangName' => 'français',
+ 'wbEntityId' => 'Q49',
+ 'wbEntity' =>
'{"id":"Q49","type":"item","labels":{"de":{"language":"de","value":"foo"},"fr":{"language":"de","value":"foo"}},"claims":{"P11":[{"id":null,"mainsnak":{"snaktype":"value","property":"P11","datavalue":{"value":{"entity-type":"item","numeric-id":98},"type":"wikibase-entityid"}},"type":"claim"}]}}',
+ 'wbUsedEntities' =>
'{"Q98":{"content":{"id":"Q98","type":"item","labels":{"fr":{"language":"de","value":"bar"}}},"title":"Item:Q98","revision":""}}',
+ ) );
+
+ $languageFallbackChain =
$languageFallbackChainFactory->newFromLanguageCode(
+ 'de-formal', LanguageFallbackChainFactory::FALLBACK_SELF
+ ); // with no fallback
+ $argLists[] = array( $content, $entityLoader, null,
$languageFallbackChain, 'nl', true, array(
+ 'wbEntityType' => 'item',
+ 'wbDataLangName' => 'Nederlands',
+ 'wbEntityId' => 'Q49',
+ 'wbEntity' =>
'{"id":"Q49","type":"item","labels":{"de":{"language":"de","value":"foo"}},"claims":{"P11":[{"id":null,"mainsnak":{"snaktype":"value","property":"P11","datavalue":{"value":{"entity-type":"item","numeric-id":98},"type":"wikibase-entityid"}},"type":"claim"}]}}',
+ 'wbUsedEntities' =>
'{"Q98":{"content":{"id":"Q98","type":"item"},"title":"Item:Q98","revision":""}}',
+ ) );
+
+ // TODO: add more tests for other JS vars
+
+ return $argLists;
+ }
}
diff --git
a/repo/tests/phpunit/includes/serializers/FetchedEntityContentSerializerTest.php
b/repo/tests/phpunit/includes/serializers/FetchedEntityContentSerializerTest.php
index 2c32dcb..880fa62 100644
---
a/repo/tests/phpunit/includes/serializers/FetchedEntityContentSerializerTest.php
+++
b/repo/tests/phpunit/includes/serializers/FetchedEntityContentSerializerTest.php
@@ -10,6 +10,7 @@
use Wikibase\PropertyContent;
use Wikibase\PropertyHandler;
use Wikibase\Repo\WikibaseRepo;
+use Wikibase\LanguageFallbackChainFactory;
use Title;
/**
@@ -78,7 +79,10 @@
* @since 0.5
*/
public function testNewForFrontendStore() {
- $serializer =
FetchedEntityContentSerializer::newForFrontendStore( 'en' );
+ $serializer =
FetchedEntityContentSerializer::newForFrontendStore( 'en',
+
WikibaseRepo::getDefaultInstance()->getLanguageFallbackChainFactory()
+ ->newFromLanguageCode( 'en',
LanguageFallbackChainFactory::FALLBACK_SELF )
+ );
$this->assertInstanceOf( $this->getClass(), $serializer );
}
}
--
To view, visit https://gerrit.wikimedia.org/r/72226
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Ic8ad24f49ba7fafe11e3dceb5d36e18d5b9ef19f
Gerrit-PatchSet: 52
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: Hashar <[email protected]>
Gerrit-Reviewer: Jeroen De Dauw <[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