Skip to content

Commit

Permalink
Move EntityIdComposer from Wikibase to DataModelServices
Browse files Browse the repository at this point in the history
  • Loading branch information
Ladsgroup committed Jun 23, 2017
1 parent 26fb24d commit ecbf194
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 0 deletions.
70 changes: 70 additions & 0 deletions src/EntityId/EntityIdComposer.php
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;
}

}

100 changes: 100 additions & 0 deletions tests/unit/EntityId/EntityIdComposerTest.php
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 );
}

}

0 comments on commit ecbf194

Please sign in to comment.