forked from JeroenDeDauw/Wikibase
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ForeignEntityRevisionLookupFactory providing a WikiPageEntityMeta…
…DataLookup for the given foreign repository Bug: T150330 Change-Id: Iac2de8d73fbc7e49ad2de358d69cc29456da25a5
- Loading branch information
Showing
3 changed files
with
284 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
145 changes: 145 additions & 0 deletions
145
lib/includes/Store/ForeignEntityRevisionLookupFactory.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
<?php | ||
|
||
namespace Wikibase\Lib\Store; | ||
|
||
use DataValues\Deserializers\DataValueDeserializer; | ||
use Serializers\Serializer; | ||
use Wikibase\DataModel\Assert\RepositoryNameAssert; | ||
use Wikibase\DataModel\Entity\EntityIdParser; | ||
use Wikibase\DataModel\Services\EntityId\PrefixMappingEntityIdParserFactory; | ||
use Wikibase\DataModel\Services\Lookup\UnknownForeignRepositoryException; | ||
use Wikibase\InternalSerialization\DeserializerFactory; | ||
use Wikibase\Lib\Store\Sql\PrefetchingWikiPageEntityMetaDataAccessor; | ||
use Wikibase\Lib\Store\Sql\WikiPageEntityMetaDataLookup; | ||
use Wikimedia\Assert\Assert; | ||
use Wikimedia\Assert\ParameterAssertionException; | ||
|
||
/** | ||
* A factory providing the WikiPageEntityMetaDataLookup instance configured for the given foreign repository. | ||
* | ||
* @license GPL-2.0+ | ||
*/ | ||
class ForeignEntityRevisionLookupFactory { | ||
|
||
/** | ||
* @var PrefixMappingEntityIdParserFactory | ||
*/ | ||
private $parserFactory; | ||
|
||
/** | ||
* @var Serializer | ||
*/ | ||
private $entitySerializer; | ||
|
||
/** | ||
* @var DataValueDeserializer | ||
*/ | ||
private $dataValueDeserializer; | ||
|
||
/** | ||
* @var EntityNamespaceLookup | ||
*/ | ||
private $entityNamespaceLookup; | ||
|
||
/** | ||
* @var int | ||
*/ | ||
private $maxBlobSize; | ||
|
||
/** | ||
* @var string[] | ||
*/ | ||
private $databaseNames; | ||
|
||
/** | ||
* @var WikiPageEntityRevisionLookup[] | ||
*/ | ||
private $lookups = []; | ||
|
||
/** | ||
* @param PrefixMappingEntityIdParserFactory $parserFactory | ||
* @param DataValueDeserializer $dataValueDeserializer | ||
* @param EntityIdParser $idParser Parser used to create an EntityId with a foreign repository prefix stripped | ||
* @param EntityNamespaceLookup $entityNamespaceLookup | ||
* @param int $maxBlobSize The maximum size of a blob allowed in serialization/deserialization, | ||
* @see EntityContentDataCodec | ||
* @param string[] $databaseNames Associative array mapping repository names (prefixes) to database names | ||
* | ||
* @throws ParameterAssertionException | ||
*/ | ||
public function __construct( | ||
PrefixMappingEntityIdParserFactory $parserFactory, | ||
Serializer $entitySerializer, | ||
DataValueDeserializer $dataValueDeserializer, | ||
EntityNamespaceLookup $entityNamespaceLookup, | ||
$maxBlobSize, | ||
array $databaseNames | ||
) { | ||
RepositoryNameAssert::assertParameterKeysAreValidRepositoryNames( $databaseNames, '$databaseNames' ); | ||
Assert::parameterElementType( 'string', $databaseNames, '$databaseNames' ); | ||
Assert::parameter( !array_key_exists( '', $databaseNames ), '$databaseNames', 'must not contain an empty string key' ); | ||
|
||
$this->parserFactory = $parserFactory; | ||
$this->entitySerializer = $entitySerializer; | ||
$this->dataValueDeserializer = $dataValueDeserializer; | ||
$this->entityNamespaceLookup = $entityNamespaceLookup; | ||
$this->maxBlobSize = $maxBlobSize; | ||
$this->databaseNames = $databaseNames; | ||
} | ||
|
||
/** | ||
* @param string $repositoryName | ||
* | ||
* @return WikiPageEntityRevisionLookup | ||
* | ||
* @throws UnknownForeignRepositoryException | ||
*/ | ||
public function getLookup( $repositoryName ) { | ||
if ( !isset( $this->lookups[$repositoryName] ) ) { | ||
$this->lookups[$repositoryName] = $this->newLookupForRepository( $repositoryName ); | ||
|
||
} | ||
return $this->lookups[$repositoryName]; | ||
} | ||
|
||
/** | ||
* @param string $repositoryName | ||
* | ||
* @return WikiPageEntityRevisionLookup | ||
* | ||
* @throws UnknownForeignRepositoryException | ||
*/ | ||
private function newLookupForRepository( $repositoryName ) { | ||
if ( !array_key_exists( $repositoryName, $this->databaseNames ) ) { | ||
throw new UnknownForeignRepositoryException( 'No database configured for repository: ' . $repositoryName ); | ||
} | ||
|
||
$prefixMappingIdParser = $this->parserFactory->getIdParser( $repositoryName ); | ||
$entityDeserializerFactory = new DeserializerFactory( | ||
$this->dataValueDeserializer, | ||
$prefixMappingIdParser, | ||
null | ||
); | ||
$codec = new EntityContentDataCodec( | ||
$prefixMappingIdParser, | ||
$this->entitySerializer, | ||
$entityDeserializerFactory->newEntityDeserializer(), | ||
$this->maxBlobSize | ||
); | ||
|
||
$metaDataLookup = new PrefetchingWikiPageEntityMetaDataAccessor( | ||
new WikiPageEntityMetaDataLookup( | ||
$this->entityNamespaceLookup, | ||
$this->databaseNames[$repositoryName], | ||
$repositoryName | ||
) | ||
); | ||
|
||
return new WikiPageEntityRevisionLookup( | ||
$codec, | ||
$metaDataLookup, | ||
$this->databaseNames[$repositoryName] | ||
); | ||
} | ||
|
||
} |
138 changes: 138 additions & 0 deletions
138
lib/tests/phpunit/Store/ForeignEntityRevisionLookupFactoryTest.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
<?php | ||
|
||
namespace Wikibase\Lib\Tests\Store; | ||
|
||
use DataValues\Deserializers\DataValueDeserializer; | ||
use Serializers\Serializer; | ||
use Wikibase\DataModel\Entity\EntityIdParser; | ||
use Wikibase\DataModel\Services\EntityId\PrefixMappingEntityIdParserFactory; | ||
use Wikibase\DataModel\Services\Lookup\UnknownForeignRepositoryException; | ||
use Wikibase\Lib\Store\EntityNamespaceLookup; | ||
use Wikibase\Lib\Store\ForeignEntityRevisionLookupFactory; | ||
use Wikibase\Lib\Store\WikiPageEntityRevisionLookup; | ||
use Wikimedia\Assert\ParameterAssertionException; | ||
|
||
/** | ||
* @covers Wikibase\Lib\Store\ForeignEntityRevisionLookupFactory | ||
* | ||
* @group Wikibase | ||
* @group WikibaseLib | ||
* | ||
* @license GPL-2.0+ | ||
*/ | ||
class ForeignEntityRevisionLookupFactoryTest extends \PHPUnit_Framework_TestCase { | ||
|
||
/** | ||
* @return EntityIdParser | ||
*/ | ||
private function getEntityIdParser() { | ||
return $this->getMock( EntityIdParser::class ); | ||
} | ||
|
||
/** | ||
* @return PrefixMappingEntityIdParserFactory | ||
*/ | ||
private function getPrefixMappingEntityIdParserFactory() { | ||
$factory = $this->getMockBuilder( PrefixMappingEntityIdParserFactory::class ) | ||
->disableOriginalConstructor() | ||
->getMock(); | ||
$factory->expects( $this->any() ) | ||
->method( 'getIdParser' ) | ||
->will( $this->returnValue( $this->getEntityIdParser() ) ); | ||
return $factory; | ||
} | ||
|
||
/** | ||
* @return Serializer | ||
*/ | ||
private function getEntitySerializer() { | ||
return $this->getMock( Serializer::class ); | ||
} | ||
|
||
/** | ||
* @return DataValueDeserializer | ||
*/ | ||
private function getDataValueDeserializer() { | ||
return $this->getMock( DataValueDeserializer::class ); | ||
} | ||
|
||
/** | ||
* @return EntityNamespaceLookup | ||
*/ | ||
private function getEntityNamespaceLookup() { | ||
return new EntityNamespaceLookup( [ 'item' => 100 ] ); | ||
} | ||
|
||
public function testGivenKnownRepository_getLookupReturnsInstanceOfWikiPageEntityRevisionLookup() { | ||
$factory = new ForeignEntityRevisionLookupFactory( | ||
$this->getPrefixMappingEntityIdParserFactory(), | ||
$this->getEntitySerializer(), | ||
$this->getDataValueDeserializer(), | ||
$this->getEntityNamespaceLookup(), | ||
0, | ||
[ 'foo' => 'foodb' ] | ||
); | ||
|
||
$this->assertInstanceOf( WikiPageEntityRevisionLookup::class, $factory->getLookup( 'foo' ) ); | ||
} | ||
|
||
public function testGivenUnknownRepository_getLookupThrowsException() { | ||
$factory = new ForeignEntityRevisionLookupFactory( | ||
$this->getPrefixMappingEntityIdParserFactory(), | ||
$this->getEntitySerializer(), | ||
$this->getDataValueDeserializer(), | ||
$this->getEntityNamespaceLookup(), | ||
0, | ||
[ 'foo' => 'foodb' ] | ||
); | ||
|
||
$this->setExpectedException( UnknownForeignRepositoryException::class ); | ||
|
||
$this->assertInstanceOf( WikiPageEntityRevisionLookup::class, $factory->getLookup( 'bar' ) ); | ||
} | ||
|
||
public function testGetLookupReusesTheInstanceOverMultipleCalls() { | ||
$factory = new ForeignEntityRevisionLookupFactory( | ||
$this->getPrefixMappingEntityIdParserFactory(), | ||
$this->getEntitySerializer(), | ||
$this->getDataValueDeserializer(), | ||
$this->getEntityNamespaceLookup(), | ||
0, | ||
[ 'foo' => 'foodb' ] | ||
); | ||
|
||
$lookupOne = $factory->getLookup( 'foo' ); | ||
$lookupTwo = $factory->getLookup( 'foo' ); | ||
|
||
$this->assertSame( $lookupOne, $lookupTwo ); | ||
} | ||
|
||
public function provideInvalidDatabaseNamesValue() { | ||
return [ | ||
'repository name containing a colon' => [ [ 'fo:o' => 'foodb' ] ], | ||
'providing database name for local repository' => [ [ '' => 'foodb' ] ], | ||
'non-string key' => [ [ 0 => 'foodb' ] ], | ||
'not a string as a database name (false)' => [ [ 'foo' => false ] ], | ||
'not a string as a database name (true)' => [ [ 'foo' => true ] ], | ||
'not a string as a database name (null)' => [ [ 'foo' => null ] ], | ||
'not a string as a database name (int)' => [ [ 'foo' => 100 ] ], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider provideInvalidDatabaseNamesValue | ||
*/ | ||
public function testGivenInvalidDatabaseNamesValue_exceptionIsThrown( array $databaseNames ) { | ||
$this->setExpectedException( ParameterAssertionException::class ); | ||
|
||
new ForeignEntityRevisionLookupFactory( | ||
$this->getPrefixMappingEntityIdParserFactory(), | ||
$this->getEntitySerializer(), | ||
$this->getDataValueDeserializer(), | ||
$this->getEntityNamespaceLookup(), | ||
0, | ||
$databaseNames | ||
); | ||
} | ||
|
||
} |