WMDE-leszek has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/377266 )
Change subject: Make a difference between entity serializers used to serialize data for storage, and to serialize it tu output to outside world ...................................................................... Make a difference between entity serializers used to serialize data for storage, and to serialize it tu output to outside world This change does not matter much for current way items and properties are serialized (the same format stored in the DB and presetned e.g. in API results), although there are already places which state in comment there is not guarantees given. This might matter for extensions adding custom entity types that contain data that must be stored but should not visible to data user. And in general, consumers of data provided by Wikibase should not be make any assumption on correspondence between what user get e.g. from API and what is persisted in the internal storage. Change-Id: Ifaeb8048cf4120744b85bcf325379157da6a01a6 --- M data-access/src/GenericServices.php M data-access/src/MultipleRepositoryAwareWikibaseServices.php M data-access/src/PerRepositoryServiceWiring.php M data-access/src/WikibaseServices.php M data-access/tests/phpunit/GenericServicesTest.php M data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php M lib/includes/EntityTypeDefinitions.php M lib/tests/phpunit/EntityTypeDefinitionsTest.php M repo/includes/WikibaseRepo.php M repo/tests/phpunit/includes/Api/EditPageTest.php M repo/tests/phpunit/includes/Content/DeferredDecodingEntityHolderTest.php M repo/tests/phpunit/includes/Content/EntityHandlerTest.php M repo/tests/phpunit/includes/WikibaseRepoTest.php 13 files changed, 115 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Wikibase refs/changes/66/377266/1 diff --git a/data-access/src/GenericServices.php b/data-access/src/GenericServices.php index 1cc8b82..702a60e 100644 --- a/data-access/src/GenericServices.php +++ b/data-access/src/GenericServices.php @@ -44,6 +44,11 @@ private $compactEntitySerializer; /** + * @var Serializer|null + */ + private $storageEntitySerializer; + + /** * @var LanguageFallbackChainFactory */ private $languageFallbackChainFactory; @@ -115,6 +120,27 @@ } /** + * Returns the entity serializer that generates serialization that is used in the storage layer. + * + * @return Serializer + */ + public function getStorageEntitySerializer() { + if ( !isset( $this->storageEntitySerializer ) ) { + $serializerFactoryCallbacks = $this->entityTypeDefinitions->getStorageSerializerFactoryCallbacks(); + $baseSerializerFactory = $this->getBaseDataModelSerializerFactory(); + $serializers = []; + + foreach ( $serializerFactoryCallbacks as $callback ) { + $serializers[] = call_user_func( $callback, $baseSerializerFactory ); + } + + $this->storageEntitySerializer = new DispatchingSerializer( $serializers ); + } + + return $this->storageEntitySerializer; + } + + /** * @return SerializerFactory Factory creating serializers that generate the full (expanded) serialization. * The factory returned has the knowledge about items, properties, and the elements they are made of, * but not about other entity types. diff --git a/data-access/src/MultipleRepositoryAwareWikibaseServices.php b/data-access/src/MultipleRepositoryAwareWikibaseServices.php index a4f2c6e..04d5c1d 100644 --- a/data-access/src/MultipleRepositoryAwareWikibaseServices.php +++ b/data-access/src/MultipleRepositoryAwareWikibaseServices.php @@ -150,6 +150,9 @@ 'CompactEntitySerializer' => function() use ( $genericServices ) { return $genericServices->getCompactEntitySerializer(); }, + 'StorageEntitySerializer' => function() use ( $genericServices ) { + return $genericServices->getStorageEntitySerializer(); + }, 'EntityStoreWatcher' => function() use ( $multiRepositoryServices ) { return $multiRepositoryServices; }, @@ -224,6 +227,15 @@ } /** + * Returns the entity serializer that generates serialization that is used in the storage layer. + * + * @return Serializer + */ + public function getStorageEntitySerializer() { + return $this->getService( 'StorageEntitySerializer' ); + } + + /** * @return EntityStoreWatcher */ public function getEntityStoreWatcher() { diff --git a/data-access/src/PerRepositoryServiceWiring.php b/data-access/src/PerRepositoryServiceWiring.php index 3a48db2..b7215c2 100644 --- a/data-access/src/PerRepositoryServiceWiring.php +++ b/data-access/src/PerRepositoryServiceWiring.php @@ -68,7 +68,7 @@ } elseif ( $services->getRepositoryName() !== '' ) { $serializer = new ForbiddenSerializer( 'Serialization of foreign entities is not supported!' ); } else { - $serializer = $genericServices->getFullEntitySerializer(); + $serializer = $genericServices->getStorageEntitySerializer(); } $codec = new EntityContentDataCodec( diff --git a/data-access/src/WikibaseServices.php b/data-access/src/WikibaseServices.php index 6044cab..c664dfe 100644 --- a/data-access/src/WikibaseServices.php +++ b/data-access/src/WikibaseServices.php @@ -59,6 +59,13 @@ public function getCompactEntitySerializer(); /** + * Returns the entity serializer that generates serialization that is used in the storage layer. + * + * @return Serializer + */ + public function getStorageEntitySerializer(); + + /** * Returns a service that can be registered as a watcher to changes to entity data. * Such watcher gets notified when entity is updated or deleted, or when the entity * redirect is updated. diff --git a/data-access/tests/phpunit/GenericServicesTest.php b/data-access/tests/phpunit/GenericServicesTest.php index 0813174..5a9a867 100644 --- a/data-access/tests/phpunit/GenericServicesTest.php +++ b/data-access/tests/phpunit/GenericServicesTest.php @@ -52,6 +52,20 @@ $this->assertSame( $serializerOne, $serializerTwo ); } + public function testGetStorageEntitySerializer() { + $services = $this->newGenericServices(); + $this->assertInstanceOf( Serializer::class, $services->getStorageEntitySerializer() ); + } + + public function testGetStorageEntitySerializerReusesTheInstanceForMultipleCalls() { + $services = $this->newGenericServices(); + + $serializerOne = $services->getStorageEntitySerializer(); + $serializerTwo = $services->getStorageEntitySerializer(); + + $this->assertSame( $serializerOne, $serializerTwo ); + } + public function testGetLanguageFallbackChainFactory() { $services = $this->newGenericServices(); diff --git a/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php b/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php index 9b4261a..c855d40 100644 --- a/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php +++ b/data-access/tests/phpunit/MultipleRepositoryAwareWikibaseServicesTest.php @@ -118,6 +118,12 @@ $this->assertInstanceOf( Serializer::class, $wikibaseServices->getCompactEntitySerializer() ); } + public function testGetStorageEntitySerializer() { + $wikibaseServices = $this->newMultipleRepositoryAwareWikibaseServices(); + + $this->assertInstanceOf( Serializer::class, $wikibaseServices->getStorageEntitySerializer() ); + } + public function testGetEntityStoreWatcher() { $wikibaseServices = $this->newMultipleRepositoryAwareWikibaseServices(); @@ -182,6 +188,7 @@ 'EntityRevisionLookup', 'FullEntitySerializer', 'CompactEntitySerializer', + 'StorageEntitySerializer', 'EntityStoreWatcher', 'LanguageFallbackChainFactory', 'PropertyInfoLookup', diff --git a/lib/includes/EntityTypeDefinitions.php b/lib/includes/EntityTypeDefinitions.php index 25422d8..0ee720f 100644 --- a/lib/includes/EntityTypeDefinitions.php +++ b/lib/includes/EntityTypeDefinitions.php @@ -76,6 +76,22 @@ /** * @return callable[] */ + public function getStorageSerializerFactoryCallbacks() { + $storageSerializerInstantiators = $this->getMapForDefinitionField( 'storage-serializer-factory-callback' ); + $fallbackSerializerInstantiators = $this->getMapForDefinitionField( 'serializer-factory-callback' ); + + foreach ( $fallbackSerializerInstantiators as $type => $instantiator ) { + if ( !array_key_exists( $type, $storageSerializerInstantiators ) ) { + $storageSerializerInstantiators[$type] = $fallbackSerializerInstantiators[$type]; + } + } + + return $storageSerializerInstantiators; + } + + /** + * @return callable[] + */ public function getDeserializerFactoryCallbacks() { return $this->getMapForDefinitionField( 'deserializer-factory-callback' ); } diff --git a/lib/tests/phpunit/EntityTypeDefinitionsTest.php b/lib/tests/phpunit/EntityTypeDefinitionsTest.php index 13d88e6..c741d74 100644 --- a/lib/tests/phpunit/EntityTypeDefinitionsTest.php +++ b/lib/tests/phpunit/EntityTypeDefinitionsTest.php @@ -36,6 +36,7 @@ ], 'bar' => [ 'serializer-factory-callback' => 'bar-serializer', + 'storage-serializer-factory-callback' => 'bar-storage-serializer', 'deserializer-factory-callback' => 'bar-deserializer', 'view-factory-callback' => 'bar-view', 'content-model-id' => 'bar-model', @@ -58,6 +59,18 @@ ); } + public function testGetStorageSerializerFactoryCallbacks() { + $definitions = new EntityTypeDefinitions( $this->getDefinitions() ); + + $this->assertEquals( + [ + 'foo' => 'foo-serializer', + 'bar' => 'bar-storage-serializer' + ], + $definitions->getStorageSerializerFactoryCallbacks() + ); + } + public function testGetDeserializerFactoryCallbacks() { $definitions = new EntityTypeDefinitions( $this->getDefinitions() ); diff --git a/repo/includes/WikibaseRepo.php b/repo/includes/WikibaseRepo.php index 23a2486..3e3e090 100644 --- a/repo/includes/WikibaseRepo.php +++ b/repo/includes/WikibaseRepo.php @@ -1276,7 +1276,7 @@ public function getEntityContentDataCodec() { return new EntityContentDataCodec( $this->getEntityIdParser(), - $this->getAllTypesEntitySerializer(), + $this->getStorageEntitySerializer(), $this->getInternalFormatEntityDeserializer(), $this->settings->getSetting( 'maxSerializedEntitySize' ) * 1024 ); @@ -1367,6 +1367,15 @@ } /** + * Returns the entity serializer that generates serialization that is used in the storage layer. + * + * @return Serializer + */ + public function getStorageEntitySerializer() { + return $this->getWikibaseServices()->getStorageEntitySerializer(); + } + + /** * Returns a deserializer to deserialize statements in both current and legacy serialization. * * @return Deserializer diff --git a/repo/tests/phpunit/includes/Api/EditPageTest.php b/repo/tests/phpunit/includes/Api/EditPageTest.php index 52c8ba5..310bfe2 100644 --- a/repo/tests/phpunit/includes/Api/EditPageTest.php +++ b/repo/tests/phpunit/includes/Api/EditPageTest.php @@ -38,7 +38,7 @@ $item->setLabel( "de", "EditPageTest" ); - $data = $wikibaseRepo->getAllTypesEntitySerializer()->serialize( $item ); + $data = $wikibaseRepo->getStorageEntitySerializer()->serialize( $item ); $text = json_encode( $data ); $title = $wikibaseRepo->getEntityTitleLookup()->getTitleForId( $item->getId() ); diff --git a/repo/tests/phpunit/includes/Content/DeferredDecodingEntityHolderTest.php b/repo/tests/phpunit/includes/Content/DeferredDecodingEntityHolderTest.php index 42c65f2..1c27f28 100644 --- a/repo/tests/phpunit/includes/Content/DeferredDecodingEntityHolderTest.php +++ b/repo/tests/phpunit/includes/Content/DeferredDecodingEntityHolderTest.php @@ -47,7 +47,7 @@ $wikibaseRepo = WikibaseRepo::getDefaultInstance(); $codec = new EntityContentDataCodec( new ItemIdParser(), - $wikibaseRepo->getAllTypesEntitySerializer(), + $wikibaseRepo->getStorageEntitySerializer(), $wikibaseRepo->getInternalFormatEntityDeserializer() ); $blob = $codec->encodeEntity( $entity, CONTENT_FORMAT_JSON ); diff --git a/repo/tests/phpunit/includes/Content/EntityHandlerTest.php b/repo/tests/phpunit/includes/Content/EntityHandlerTest.php index dd92b84..e8c8edc 100644 --- a/repo/tests/phpunit/includes/Content/EntityHandlerTest.php +++ b/repo/tests/phpunit/includes/Content/EntityHandlerTest.php @@ -367,7 +367,7 @@ public function exportTransformProvider() { $entity = $this->newEntity(); - $internalSerializer = WikibaseRepo::getDefaultInstance()->getAllTypesEntitySerializer(); + $internalSerializer = WikibaseRepo::getDefaultInstance()->getStorageEntitySerializer(); $oldBlob = json_encode( $internalSerializer->serialize( $entity ) ); // fake several old formats @@ -422,7 +422,7 @@ $settings->setSetting( 'transformLegacyFormatOnExport', true ); $entity = $this->newEntity(); - $entitySerializer = $this->getWikibaseRepo( $settings )->getAllTypesEntitySerializer(); + $entitySerializer = $this->getWikibaseRepo( $settings )->getStorageEntitySerializer(); $expected = json_encode( $entitySerializer->serialize( $entity ) ); $handler = $this->getHandler( $settings ); diff --git a/repo/tests/phpunit/includes/WikibaseRepoTest.php b/repo/tests/phpunit/includes/WikibaseRepoTest.php index f52b83f..645e25a 100644 --- a/repo/tests/phpunit/includes/WikibaseRepoTest.php +++ b/repo/tests/phpunit/includes/WikibaseRepoTest.php @@ -465,6 +465,11 @@ $this->assertInstanceOf( Serializer::class, $serializer ); } + public function testGetStorageEntitySerializer() { + $serializer = $this->getWikibaseRepo()->getStorageEntitySerializer(); + $this->assertInstanceOf( Serializer::class, $serializer ); + } + public function testGetExternalFormatStatementDeserializer() { $deserializer = $this->getWikibaseRepo()->getExternalFormatStatementDeserializer(); $this->assertInstanceOf( Deserializer::class, $deserializer ); -- To view, visit https://gerrit.wikimedia.org/r/377266 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ifaeb8048cf4120744b85bcf325379157da6a01a6 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Wikibase Gerrit-Branch: master Gerrit-Owner: WMDE-leszek <leszek.mani...@wikimedia.de> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits