diff --git a/Aliases.php b/Aliases.php index 006fce9e..a01e48a2 100644 --- a/Aliases.php +++ b/Aliases.php @@ -83,7 +83,7 @@ class Claims extends \Wikibase\DataModel\Claim\Claims {} /** * @deprecated since 0.6, use the base class instead. */ - class Statement extends \Wikibase\DataModel\Claim\Statement {} + class Statement extends DataModel\Statement\Statement {} /** * @deprecated since 0.6, use the base class instead. */ @@ -160,3 +160,12 @@ class ItemDiff extends \Wikibase\DataModel\Entity\Diff\ItemDiff {} class EntityDiff extends \Wikibase\DataModel\Entity\Diff\EntityDiff {} } + +namespace Wikibase\DataModel\Claim { + + /** + * @deprecated since 1.0, use the base class instead. + */ + class Statement extends \Wikibase\DataModel\Statement\Statement {} + +} diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index cbfd9c8a..81d1675e 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -54,6 +54,7 @@ Other breaking changes: #### Additions * Added `ClaimList` +* Added `StatementList` * Added `ClaimListDiffer` * Added `PropertyDataTypeLookup` and trivial implementation `InMemoryDataTypeLookup` * Added `PropertyNotFoundException` @@ -67,6 +68,7 @@ Other breaking changes: * Undeprecated passing an integer to `Item::setId` and `Property::setId` * Deprecated `Entity::setId`, `Entity::newClaim` and `Entity::getAllSnaks` * Deprecated `Item::getClaims` in favour of `Item::getStatements` +* The FQN of `Statement` is now `Wikibase\DataModel\Statement\Statement`. The old FQN is deprecated. ## Version 0.9 (2014-08-15) diff --git a/WikibaseDataModel.php b/WikibaseDataModel.php index 2f8797f4..32f5e6b2 100644 --- a/WikibaseDataModel.php +++ b/WikibaseDataModel.php @@ -37,7 +37,7 @@ class_alias( 'Wikibase\DataModel\ByPropertyIdArray', 'Wikibase\ByPropertyIdArray class_alias( 'Wikibase\DataModel\Claim\Claim', 'Wikibase\Claim' ); class_alias( 'Wikibase\DataModel\Claim\ClaimListAccess', 'Wikibase\ClaimListAccess' ); class_alias( 'Wikibase\DataModel\Claim\Claims', 'Wikibase\Claims' ); -class_alias( 'Wikibase\DataModel\Claim\Statement', 'Wikibase\Statement' ); +class_alias( 'Wikibase\DataModel\Statement\Statement', 'Wikibase\Statement' ); class_alias( 'Wikibase\DataModel\Entity\Entity', 'Wikibase\Entity' ); class_alias( 'Wikibase\DataModel\Entity\Item', 'Wikibase\Item' ); class_alias( 'Wikibase\DataModel\Entity\Property', 'Wikibase\Property' ); @@ -59,3 +59,4 @@ class_alias( 'Wikibase\DataModel\LegacyIdInterpreter', 'Wikibase\DataModel\Inter // Aliases introduced in 1.0 class_alias( 'Wikibase\DataModel\Entity\Diff\EntityDiff', 'Wikibase\DataModel\Entity\EntityDiff' ); class_alias( 'Wikibase\DataModel\Entity\Diff\ItemDiff', 'Wikibase\DataModel\Entity\ItemDiff' ); +class_alias( 'Wikibase\DataModel\Statement\Statement', 'Wikibase\DataModel\Claim\Statement' ); diff --git a/src/Claim/Claim.php b/src/Claim/Claim.php index f48d2e8e..f628d1af 100644 --- a/src/Claim/Claim.php +++ b/src/Claim/Claim.php @@ -9,6 +9,7 @@ use Wikibase\DataModel\Snak\Snak; use Wikibase\DataModel\Snak\SnakList; use Wikibase\DataModel\Snak\Snaks; +use Wikibase\DataModel\Statement\Statement; /** * Class that represents a single Wikibase claim. diff --git a/src/Claim/ClaimList.php b/src/Claim/ClaimList.php index 499bbaa9..3cea4149 100644 --- a/src/Claim/ClaimList.php +++ b/src/Claim/ClaimList.php @@ -41,26 +41,6 @@ public function __construct( $claims = array() ) { $this->claims = $claims; } - /** - * Returns the best claims per property. - * The best claims are those with the highest rank for a particular property. - * Deprecated ranks are never included. - * - * Caution: the ranking is done per property, not globally, as in the Claims class. - * - * @return self - */ - public function getBestClaimPerProperty() { - $claimList = new self(); - - foreach ( $this->getPropertyIds() as $propertyId ) { - $claims = new Claims( $this->claims ); - $claimList->addClaims( $claims->getClaimsForProperty( $propertyId )->getBestClaims() ); - } - - return $claimList; - } - /** * Returns the property ids used by the claims. * The keys of the returned array hold the serializations of the property ids. @@ -77,12 +57,6 @@ public function getPropertyIds() { return $propertyIds; } - private function addClaims( Claims $claims ) { - foreach ( $claims as $claim ) { - $this->addClaim( $claim ); - } - } - public function addClaim( Claim $claim ) { $this->claims[] = $claim; } diff --git a/src/Entity/Item.php b/src/Entity/Item.php index e5e2606c..39e270bd 100644 --- a/src/Entity/Item.php +++ b/src/Entity/Item.php @@ -10,7 +10,7 @@ use OutOfBoundsException; use Wikibase\DataModel\Claim\Claim; use Wikibase\DataModel\Claim\Claims; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\Diff\EntityDiff; use Wikibase\DataModel\Entity\Diff\ItemDiff; use Wikibase\DataModel\SiteLink; @@ -339,7 +339,7 @@ public function addClaim( Claim $claim ) { /** * @since 1.0 * - * @return Statement[] + * @return \Wikibase\DataModel\Statement\Statement[] */ public function getStatements() { return $this->statements; diff --git a/src/Claim/Statement.php b/src/Statement/Statement.php similarity index 97% rename from src/Claim/Statement.php rename to src/Statement/Statement.php index 306a6aa9..fec42a90 100644 --- a/src/Claim/Statement.php +++ b/src/Statement/Statement.php @@ -1,8 +1,9 @@ + */ +class StatementList implements \IteratorAggregate { + + /** + * @var Statement[] + */ + private $statements = array(); + + /** + * @param Statement[]|Traversable $statements + * + * @throws InvalidArgumentException + */ + public function __construct( $statements = array() ) { + $this->addStatements( $statements ); + } + + /** + * Returns the best statements per property. + * The best statements are those with the highest rank for a particular property. + * Deprecated ranks are never included. + * + * @return self + */ + public function getBestStatementPerProperty() { + $statementList = new self(); + + foreach ( $this->getPropertyIds() as $propertyId ) { + $claims = new Claims( $this->statements ); + $statementList->addStatements( $claims->getClaimsForProperty( $propertyId )->getBestClaims() ); + } + + return $statementList; + } + + private function addStatements( $statements ) { + $this->assertAreStatements( $statements ); + + foreach ( $statements as $statement ) { + $this->statements[] = $statement; + } + } + + private function assertAreStatements( $statements ) { + if ( !is_array( $statements ) && !( $statements instanceof Traversable ) ) { + throw new InvalidArgumentException( '$statements should be an array or a Traversable' ); + } + + foreach ( $statements as $statement ) { + if ( !( $statement instanceof Statement ) ) { + throw new InvalidArgumentException( 'All elements need to be of type Statement' ); + } + } + } + + /** + * Returns the property ids used by the statements. + * The keys of the returned array hold the serializations of the property ids. + * + * @return PropertyId[] + */ + public function getPropertyIds() { + $propertyIds = array(); + + foreach ( $this->statements as $statement ) { + $propertyIds[$statement->getPropertyId()->getSerialization()] = $statement->getPropertyId(); + } + + return $propertyIds; + } + + public function addStatement( Statement $statement ) { + $this->statements[] = $statement; + } + + /** + * @param Snak $mainSnak + * @param Snak[]|Snaks|null $qualifiers + * @param Reference[]|References|null $references + * @param string|null $guid + */ + public function addNewStatement( Snak $mainSnak, $qualifiers = null, $references = null, $guid = null ) { + $qualifiers = is_array( $qualifiers ) ? new SnakList( $qualifiers ) : $qualifiers; + $references = is_array( $references ) ? new ReferenceList( $references ) : $references; + + $statement = new Statement( $mainSnak, $qualifiers, $references ); + $statement->setGuid( $guid ); + + $this->addStatement( $statement ); + } + + /** + * Statements that have a main snak already in the list are filtered out. + * The last occurrences are retained. + * + * @return self + */ + public function getWithUniqueMainSnaks() { + $statements = array(); + + foreach ( $this->statements as $statement ) { + $statements[$statement->getMainSnak()->getHash()] = $statement; + } + + return new self( $statements ); + } + + /** + * @return Traversable + */ + public function getIterator() { + return new \ArrayIterator( $this->statements ); + } + + /** + * @return Statement[] + */ + public function toArray() { + return $this->statements; + } + +} diff --git a/tests/unit/ByPropertyIdArrayTest.php b/tests/unit/ByPropertyIdArrayTest.php index abd5ee4d..15dfa64f 100644 --- a/tests/unit/ByPropertyIdArrayTest.php +++ b/tests/unit/ByPropertyIdArrayTest.php @@ -8,7 +8,7 @@ use Wikibase\Claims; use Wikibase\DataModel\ByPropertyIdArray; use Wikibase\DataModel\Claim\Claim; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\PropertyId; use Wikibase\DataModel\Snak\PropertyNoValueSnak; use Wikibase\DataModel\Snak\PropertySomeValueSnak; diff --git a/tests/unit/Claim/ClaimListTest.php b/tests/unit/Claim/ClaimListTest.php index 2941393b..2528c65e 100644 --- a/tests/unit/Claim/ClaimListTest.php +++ b/tests/unit/Claim/ClaimListTest.php @@ -89,34 +89,6 @@ public function testCanIterate() { } } - public function testGetBestClaimPerProperty() { - $list = new ClaimList( array( - $this->getStubClaim( 1, 'one', Claim::RANK_PREFERRED ), - $this->getStubClaim( 1, 'two', Claim::RANK_NORMAL ), - $this->getStubClaim( 1, 'three', Claim::RANK_PREFERRED ), - - $this->getStubClaim( 2, 'four', Claim::RANK_DEPRECATED ), - - $this->getStubClaim( 3, 'five', Claim::RANK_DEPRECATED ), - $this->getStubClaim( 3, 'six', Claim::RANK_NORMAL ), - - $this->getStubClaim( 4, 'seven', Claim::RANK_PREFERRED ), - $this->getStubClaim( 4, 'eight', Claim::RANK_TRUTH ), - ) ); - - $this->assertEquals( - array( - $this->getStubClaim( 1, 'one', Claim::RANK_PREFERRED ), - $this->getStubClaim( 1, 'three', Claim::RANK_PREFERRED ), - - $this->getStubClaim( 3, 'six', Claim::RANK_NORMAL ), - - $this->getStubClaim( 4, 'eight', Claim::RANK_TRUTH ), - ), - $list->getBestClaimPerProperty()->toArray() - ); - } - public function testGetUniqueMainSnaksReturnsListWithoutDuplicates() { $list = new ClaimList( array( $this->getClaimWithSnak( 1, 'foo' ), diff --git a/tests/unit/Claim/ClaimStandaloneTest.php b/tests/unit/Claim/ClaimStandaloneTest.php index ea2c9e37..46484cca 100644 --- a/tests/unit/Claim/ClaimStandaloneTest.php +++ b/tests/unit/Claim/ClaimStandaloneTest.php @@ -3,7 +3,7 @@ namespace Wikibase\Test; use Wikibase\DataModel\Claim\Claim; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Snak\PropertyNoValueSnak; use Wikibase\DataModel\Snak\PropertySomeValueSnak; use Wikibase\DataModel\Snak\SnakList; diff --git a/tests/unit/Claim/ClaimsTest.php b/tests/unit/Claim/ClaimsTest.php index 989cdcfe..30760dab 100644 --- a/tests/unit/Claim/ClaimsTest.php +++ b/tests/unit/Claim/ClaimsTest.php @@ -12,7 +12,7 @@ use Wikibase\DataModel\ByPropertyIdArray; use Wikibase\DataModel\Claim\Claim; use Wikibase\DataModel\Claim\Claims; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\PropertyId; use Wikibase\DataModel\Reference; use Wikibase\DataModel\ReferenceList; diff --git a/tests/unit/Entity/Diff/ItemDifferTest.php b/tests/unit/Entity/Diff/ItemDifferTest.php index 34aa65e4..ba5494af 100644 --- a/tests/unit/Entity/Diff/ItemDifferTest.php +++ b/tests/unit/Entity/Diff/ItemDifferTest.php @@ -6,7 +6,7 @@ use Diff\DiffOp\DiffOpAdd; use Diff\DiffOp\DiffOpChange; use Diff\DiffOp\DiffOpRemove; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\Diff\ItemDiffer; use Wikibase\DataModel\Entity\Item; use Wikibase\DataModel\Snak\PropertySomeValueSnak; diff --git a/tests/unit/Entity/EntityTest.php b/tests/unit/Entity/EntityTest.php index c3bcf9f1..a6064c6e 100644 --- a/tests/unit/Entity/EntityTest.php +++ b/tests/unit/Entity/EntityTest.php @@ -6,7 +6,7 @@ use Diff\DiffOp\DiffOpAdd; use Diff\DiffOp\DiffOpChange; use Diff\DiffOp\DiffOpRemove; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\Diff\EntityDiff; use Wikibase\DataModel\Entity\Entity; use Wikibase\DataModel\Entity\Item; diff --git a/tests/unit/Entity/ItemTest.php b/tests/unit/Entity/ItemTest.php index 54e51b51..c623662d 100644 --- a/tests/unit/Entity/ItemTest.php +++ b/tests/unit/Entity/ItemTest.php @@ -9,7 +9,7 @@ use Diff\DiffOp\DiffOpRemove; use Wikibase\DataModel\Claim\Claim; use Wikibase\DataModel\Claim\Claims; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\Diff\ItemDiff; use Wikibase\DataModel\Entity\EntityIdValue; use Wikibase\DataModel\Entity\Item; @@ -691,7 +691,7 @@ public function testNewClaimReturnsStatementWithProvidedMainSnak() { $item = Item::newEmpty(); $statement = $item->newClaim( $snak ); - $this->assertInstanceOf( 'Wikibase\DataModel\Claim\Statement', $statement ); + $this->assertInstanceOf( 'Wikibase\DataModel\Statement\Statement', $statement ); $this->assertEquals( $snak, $statement->getMainSnak() ); } diff --git a/tests/unit/Statement/StatementListTest.php b/tests/unit/Statement/StatementListTest.php new file mode 100644 index 00000000..069cc32c --- /dev/null +++ b/tests/unit/Statement/StatementListTest.php @@ -0,0 +1,251 @@ + + */ +class StatementListTest extends \PHPUnit_Framework_TestCase { + + public function testGivenNoStatements_getPropertyIdsReturnsEmptyArray() { + $list = new StatementList(); + $this->assertSame( array(), $list->getPropertyIds() ); + } + + public function testGivenStatements_getPropertyIdsReturnsArrayWithoutDuplicates() { + $list = new StatementList( array( + $this->getStubStatement( 1, 'kittens' ), + $this->getStubStatement( 3, 'foo' ), + $this->getStubStatement( 2, 'bar' ), + $this->getStubStatement( 2, 'baz' ), + $this->getStubStatement( 1, 'bah' ), + ) ); + + $this->assertEquals( + array( + 'P1' => new PropertyId( 'P1' ), + 'P3' => new PropertyId( 'P3' ), + 'P2' => new PropertyId( 'P2' ), + ), + $list->getPropertyIds() + ); + } + + private function getStubStatement( $propertyId, $guid, $rank = Statement::RANK_NORMAL ) { + $statement = $this->getMockBuilder( 'Wikibase\DataModel\Statement\Statement' ) + ->disableOriginalConstructor()->getMock(); + + $statement->expects( $this->any() ) + ->method( 'getGuid' ) + ->will( $this->returnValue( $guid ) ); + + $statement->expects( $this->any() ) + ->method( 'getPropertyId' ) + ->will( $this->returnValue( PropertyId::newFromNumber( $propertyId ) ) ); + + $statement->expects( $this->any() ) + ->method( 'getRank' ) + ->will( $this->returnValue( $rank ) ); + + return $statement; + } + + public function testCanIterate() { + $statement = $this->getStubStatement( 1, 'kittens' ); + $list = new StatementList( array( $statement ) ); + + foreach ( $list as $statementFormList ) { + $this->assertEquals( $statement, $statementFormList ); + } + } + + public function testGetBestStatementPerProperty() { + $list = new StatementList( array( + $this->getStubStatement( 1, 'one', Statement::RANK_PREFERRED ), + $this->getStubStatement( 1, 'two', Statement::RANK_NORMAL ), + $this->getStubStatement( 1, 'three', Statement::RANK_PREFERRED ), + + $this->getStubStatement( 2, 'four', Statement::RANK_DEPRECATED ), + + $this->getStubStatement( 3, 'five', Statement::RANK_DEPRECATED ), + $this->getStubStatement( 3, 'six', Statement::RANK_NORMAL ), + + $this->getStubStatement( 4, 'seven', Statement::RANK_PREFERRED ), + $this->getStubStatement( 4, 'eight', Statement::RANK_TRUTH ), + ) ); + + $this->assertEquals( + array( + $this->getStubStatement( 1, 'one', Statement::RANK_PREFERRED ), + $this->getStubStatement( 1, 'three', Statement::RANK_PREFERRED ), + + $this->getStubStatement( 3, 'six', Statement::RANK_NORMAL ), + + $this->getStubStatement( 4, 'eight', Statement::RANK_TRUTH ), + ), + $list->getBestStatementPerProperty()->toArray() + ); + } + + public function testGetUniqueMainSnaksReturnsListWithoutDuplicates() { + $list = new StatementList( array( + $this->getStatementWithSnak( 1, 'foo' ), + $this->getStatementWithSnak( 2, 'foo' ), + $this->getStatementWithSnak( 1, 'foo' ), + $this->getStatementWithSnak( 2, 'bar' ), + $this->getStatementWithSnak( 1, 'bar' ), + ) ); + + $this->assertEquals( + array( + $this->getStatementWithSnak( 1, 'foo' ), + $this->getStatementWithSnak( 2, 'foo' ), + $this->getStatementWithSnak( 2, 'bar' ), + $this->getStatementWithSnak( 1, 'bar' ), + ), + array_values( $list->getWithUniqueMainSnaks()->toArray() ) + ); + } + + private function getStatementWithSnak( $propertyId, $stringValue ) { + $snak = $this->newSnak( $propertyId, $stringValue ); + $claim = new Statement( $snak ); + $claim->setGuid( sha1( $snak->getHash() ) ); + return $claim; + } + + private function newSnak( $propertyId, $stringValue ) { + return new PropertyValueSnak( $propertyId, new StringValue( $stringValue ) ); + } + + public function testAddStatementWithOnlyMainSnak() { + $list = new StatementList(); + + $list->addNewStatement( $this->newSnak( 42, 'foo' ) ); + + $this->assertEquals( + new StatementList( array( + new Statement( $this->newSnak( 42, 'foo' ) ) + ) ), + $list + ); + } + + public function testAddStatementWithQualifiersAsSnakArray() { + $list = new StatementList(); + + $list->addNewStatement( + $this->newSnak( 42, 'foo' ), + array( + $this->newSnak( 1, 'bar' ) + ) + ); + + $this->assertEquals( + new StatementList( array( + new Statement( + $this->newSnak( 42, 'foo' ), + new SnakList( array( + $this->newSnak( 1, 'bar' ) + ) ) + ) + ) ), + $list + ); + } + + public function testAddStatementWithQualifiersAsSnakList() { + $list = new StatementList(); + $snakList = new SnakList( array( + $this->newSnak( 1, 'bar' ) + ) ); + + $list->addNewStatement( + $this->newSnak( 42, 'foo' ), + $snakList + ); + + $this->assertEquals( + new StatementList( array( + new Statement( + $this->newSnak( 42, 'foo' ), + $snakList + ) + ) ), + $list + ); + } + + public function testAddStatementWithGuid() { + $list = new StatementList(); + + $list->addNewStatement( + $this->newSnak( 42, 'foo' ), + null, + null, + 'kittens' + ); + + $statement = new Statement( + $this->newSnak( 42, 'foo' ), + null + ); + + $statement->setGuid( 'kittens' ); + + $this->assertEquals( + new StatementList( array( $statement ) ), + $list + ); + } + + public function testCanConstructWithClaimsObjectContainingOnlyStatements() { + $statementArray = array( + $this->getStatementWithSnak( 1, 'foo' ), + $this->getStatementWithSnak( 2, 'bar' ), + ); + + $claimsObject = new Claims( $statementArray ); + + $list = new StatementList( $claimsObject ); + + $this->assertEquals( + $statementArray, + array_values( $list->toArray() ) + ); + } + + public function testGivenTraversableWithNonStatements_constructorThrowsException() { + $claim = new Claim( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $claim->setGuid( 'meh' ); + + $claimArray = array( + $this->getStatementWithSnak( 1, 'foo' ), + $claim, + $this->getStatementWithSnak( 2, 'bar' ), + ); + + $claimsObject = new Claims( $claimArray ); + + $this->setExpectedException( 'InvalidArgumentException' ); + new StatementList( $claimsObject ); + } + + public function testGivenNonTraversable_constructorThrowsException() { + $this->setExpectedException( 'InvalidArgumentException' ); + new StatementList( null ); + } + +} diff --git a/tests/unit/Claim/StatementTest.php b/tests/unit/Statement/StatementTest.php similarity index 97% rename from tests/unit/Claim/StatementTest.php rename to tests/unit/Statement/StatementTest.php index 59397fe9..d10c2d75 100644 --- a/tests/unit/Claim/StatementTest.php +++ b/tests/unit/Statement/StatementTest.php @@ -4,7 +4,7 @@ use DataValues\StringValue; use Wikibase\DataModel\Claim\Claim; -use Wikibase\DataModel\Claim\Statement; +use Wikibase\DataModel\Statement\Statement; use Wikibase\DataModel\Entity\PropertyId; use Wikibase\DataModel\Reference; use Wikibase\DataModel\ReferenceList; @@ -14,7 +14,7 @@ use Wikibase\DataModel\Snak\SnakList; /** - * @covers Wikibase\DataModel\Claim\Statement + * @covers Wikibase\DataModel\Statement\Statement * * @group Wikibase * @group WikibaseDataModel @@ -162,7 +162,7 @@ public function testGetHash() { * @dataProvider instanceProvider */ public function testGetAllSnaks( Claim $claim ) { - /* @var Statement $statement */ + /* @var \Wikibase\DataModel\Statement\Statement $statement */ $statement = $claim; $snaks = $statement->getAllSnaks();