-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move EntityIdComposer from Wikibase to DataModelServices
- Loading branch information
Showing
2 changed files
with
170 additions
and
0 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
<?php | ||
|
||
namespace Wikibase\DataModel\Services\EntityId; | ||
|
||
use InvalidArgumentException; | ||
use UnexpectedValueException; | ||
use Wikibase\DataModel\Entity\EntityId; | ||
|
||
/** | ||
* Constructs EntityId objects from entity type identifiers and unique parts of entity ID | ||
* serializations. The unique part is typically the numeric part of an entity ID, excluding the | ||
* static part that's the same for all IDs of that type. | ||
* | ||
* Meant to be the counterpart for @see Int32EntityId::getNumericId, as well as an extensible | ||
* replacement for @see LegacyIdInterpreter::newIdFromTypeAndNumber. | ||
* | ||
* @license GPL-2.0+ | ||
* @author Thiemo Mättig | ||
*/ | ||
class EntityIdComposer { | ||
|
||
/** | ||
* @var callable[] | ||
*/ | ||
private $composers; | ||
|
||
/** | ||
* @param callable[] $composers Array mapping entity type identifiers to callables accepting a | ||
* single mixed value, representing the unique part of an entity ID serialization, and | ||
* returning an EntityId object. | ||
* | ||
* @throws InvalidArgumentException | ||
*/ | ||
public function __construct( array $composers ) { | ||
foreach ( $composers as $entityType => $composer ) { | ||
if ( !is_string( $entityType ) || $entityType === '' || !is_callable( $composer ) ) { | ||
throw new InvalidArgumentException( '$composers must map non-empty strings to callables' ); | ||
} | ||
} | ||
|
||
$this->composers = $composers; | ||
} | ||
|
||
/** | ||
* @param string $repositoryName | ||
* @param string $entityType | ||
* @param mixed $uniquePart | ||
* | ||
* @throws InvalidArgumentException when the entity type is not known or the unique part is not | ||
* unique. | ||
* @throws UnexpectedValueException when the configured composer did not return an EntityId | ||
* object. | ||
* @return EntityId | ||
*/ | ||
public function composeEntityId( $repositoryName, $entityType, $uniquePart ) { | ||
if ( !isset( $this->composers[$entityType] ) ) { | ||
throw new InvalidArgumentException( 'Unknown entity type ' . $entityType ); | ||
} | ||
|
||
$id = $this->composers[$entityType]( $repositoryName, $uniquePart ); | ||
|
||
if ( !( $id instanceof EntityId ) ) { | ||
throw new UnexpectedValueException( 'Composer for ' . $entityType . ' is invalid' ); | ||
} | ||
|
||
return $id; | ||
} | ||
|
||
} | ||
|
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,100 @@ | ||
<?php | ||
|
||
namespace Wikibase\DataModel\Services\Tests\EntityId; | ||
|
||
use InvalidArgumentException; | ||
use PHPUnit_Framework_TestCase; | ||
use UnexpectedValueException; | ||
use Wikibase\DataModel\Entity\EntityId; | ||
use Wikibase\DataModel\Entity\ItemId; | ||
use Wikibase\DataModel\Services\EntityId\EntityIdComposer; | ||
|
||
/** | ||
* @covers Wikibase\DataModel\Services\EntityId\EntityIdComposer | ||
* | ||
* @group Wikibase | ||
* | ||
* @licence GNU GPL v2+ | ||
* @author Thiemo Mättig | ||
*/ | ||
class EntityIdComposerTest extends PHPUnit_Framework_TestCase { | ||
|
||
private function getComposer() { | ||
return new EntityIdComposer( [ | ||
'numeric-item' => function( $repositoryName, $uniquePart ) { | ||
return new ItemId( 'Q' . $uniquePart ); | ||
}, | ||
'custom-item' => function( $repositoryName, $uniquePart ) { | ||
return new ItemId( 'Q100' . $uniquePart ); | ||
}, | ||
] ); | ||
} | ||
|
||
public function invalidConstructorArgumentProvider() { | ||
$callable = function( $repositoryName, $uniquePart ) { | ||
}; | ||
|
||
return [ | ||
[ [ 0 => $callable ] ], | ||
[ [ '' => $callable ] ], | ||
[ [ 'string' => null ] ], | ||
[ [ 'string' => 'not a callable' ] ], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider invalidConstructorArgumentProvider | ||
*/ | ||
public function testGivenInvalidComposer_constructorFails( $composers ) { | ||
$this->setExpectedException( InvalidArgumentException::class ); | ||
new EntityIdComposer( $composers ); | ||
} | ||
|
||
public function testGivenInvalidCallback_buildFails() { | ||
$composer = new EntityIdComposer( [ | ||
'item' => function( $repositoryName, $uniquePart ) { | ||
return null; | ||
}, | ||
] ); | ||
$this->setExpectedException( UnexpectedValueException::class ); | ||
$composer->composeEntityId( '', 'item', 1 ); | ||
} | ||
|
||
public function validUniquePartProvider() { | ||
return [ | ||
'int' => [ 'numeric-item', 3, new ItemId( 'Q3' ) ], | ||
'float' => [ 'numeric-item', 4.0, new ItemId( 'Q4' ) ], | ||
'string' => [ 'numeric-item', '5', new ItemId( 'Q5' ) ], | ||
|
||
'custom' => [ 'custom-item', 6, new ItemId( 'Q1006' ) ], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider validUniquePartProvider | ||
*/ | ||
public function testGivenValidFragment_buildSucceeds( $entityType, $uniquePart, EntityId $expected ) { | ||
$id = $this->getComposer()->composeEntityId( '', $entityType, $uniquePart ); | ||
$this->assertEquals( $expected, $id ); | ||
} | ||
|
||
public function invalidUniquePartProvider() { | ||
return [ | ||
[ null, 1 ], | ||
[ 'unknown', 2 ], | ||
[ 'numeric-item', null ], | ||
[ 'numeric-item', new ItemId( 'Q4' ) ], | ||
]; | ||
} | ||
|
||
/** | ||
* @dataProvider invalidUniquePartProvider | ||
*/ | ||
public function testGivenInvalidFragment_buildFails( $entityType, $uniquePart ) { | ||
$composer = $this->getComposer(); | ||
$this->setExpectedException( InvalidArgumentException::class ); | ||
$composer->composeEntityId( '', $entityType, $uniquePart ); | ||
} | ||
|
||
} | ||
|