From 15590582d49b4191347260625db7fd07f2a0db75 Mon Sep 17 00:00:00 2001 From: Bene Date: Tue, 23 Jun 2015 12:51:14 +0200 Subject: [PATCH 1/2] Introduce StatementGroup Per https://github.com/wmde/WikibaseDataModel/pull/479#issuecomment-99865477 --- src/Statement/StatementGroup.php | 95 ++++++++++++++++++++ tests/unit/Statement/StatementGroupTest.php | 97 +++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 src/Statement/StatementGroup.php create mode 100644 tests/unit/Statement/StatementGroupTest.php diff --git a/src/Statement/StatementGroup.php b/src/Statement/StatementGroup.php new file mode 100644 index 00000000..4161210a --- /dev/null +++ b/src/Statement/StatementGroup.php @@ -0,0 +1,95 @@ + + */ +class StatementGroup implements PropertyIdProvider { + + /** + * @var Statement[][] + */ + private $statementsByRank = array(); + + /** + * @var PropertyId + */ + private $propertyId; + + /** + * @param PropertyId|int $propertyId + */ + public function __construct( $propertyId ) { + if ( is_int( $propertyId ) ) { + $propertyId = PropertyId::newFromNumber( $propertyId ); + } + + if ( !( $propertyId instanceof PropertyId ) ) { + throw new InvalidArgumentException( '$propertyId must be an integer or an instance of PropertyId' ); + } + + $this->propertyId = $propertyId; + } + + /** + * @param Statement[]|Traversable $statements + * @throws InvalidArgumentException + */ + public function addStatements( $statements ) { + if ( !is_array( $statements ) && !( $statements instanceof Traversable ) ) { + throw new InvalidArgumentException( '$statements must be an array or an instance of Traversable' ); + } + + foreach ( $statements as $statement ) { + if ( !( $statement instanceof Statement ) ) { + throw new InvalidArgumentException( 'Every element in $statements must be an instance of Statement' ); + } + + $this->addStatement( $statement ); + } + } + + /** + * @param Statement $statement + * @throws InvalidArgumentException + */ + public function addStatement( Statement $statement ) { + if ( !$statement->getPropertyId()->equals( $this->propertyId ) ) { + throw new InvalidArgumentException( '$statement must have the property id ' . $this->propertyId->getSerialization() ); + } + + $this->statementsByRank[$statement->getRank()][] = $statement; + } + + /** + * @see PropertyIdProvider::getPropertyId + * @return PropertyId + */ + public function getPropertyId() { + return $this->propertyId; + } + + /** + * @param int $rank + * @return Statement[] + */ + public function getByRank( $rank ) { + if ( isset( $this->statementsByRank[$rank] ) ) { + return $this->statementsByRank[$rank]; + } + + return array(); + } + +} diff --git a/tests/unit/Statement/StatementGroupTest.php b/tests/unit/Statement/StatementGroupTest.php new file mode 100644 index 00000000..0f997151 --- /dev/null +++ b/tests/unit/Statement/StatementGroupTest.php @@ -0,0 +1,97 @@ + + */ +class StatementGroupTest extends \PHPUnit_Framework_TestCase { + + public function testConstructor_numericId() { + $statementGroup = new StatementGroup( 42 ); + $this->assertEquals( new PropertyId( 'P42' ), $statementGroup->getPropertyId() ); + } + + public function testConstructor_propertyId() { + $statementGroup = new StatementGroup( new PropertyId( 'P42' ) ); + $this->assertEquals( new PropertyId( 'P42' ), $statementGroup->getPropertyId() ); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testConstructor_invalidArgument() { + new StatementGroup( 'foo' ); + } + + public function testAddStatement_validPropertyId() { + $statementGroup = new StatementGroup( 42 ); + $statement = new Statement( new PropertyNoValueSnak( 42 ) ); + $statementGroup->addStatement( $statement ); + + $this->assertEquals( array( $statement ), $statementGroup->getByRank( Statement::RANK_NORMAL ) ); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testAddStatement_invalidPropertyId() { + $statementGroup = new StatementGroup( 42 ); + $statement = new Statement( new PropertyNoValueSnak( 12 ) ); + $statementGroup->addStatement( $statement ); + } + + public function testAddStatements() { + $statementGroup = new StatementGroup( 42 ); + $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $baz = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $baz->setRank( Statement::RANK_PREFERRED ); + $statementGroup->addStatements( array( $foo, $bar, $baz ) ); + + $this->assertEquals( array(), $statementGroup->getByRank( Statement::RANK_DEPRECATED ) ); + $this->assertEquals( array( $foo, $bar ), $statementGroup->getByRank( Statement::RANK_NORMAL ) ); + $this->assertEquals( array( $baz ), $statementGroup->getByRank( Statement::RANK_PREFERRED ) ); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testAddStatements_invalidPropertyIds() { + $statementGroup = new StatementGroup( 42 ); + $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $baz = new Statement( new PropertyValueSnak( 12, new StringValue( 'foo' ) ) ); + $statementGroup->addStatements( array( $foo, $bar, $baz ) ); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testAddStatements_noStatement() { + $statementGroup = new StatementGroup( 42 ); + $statement = new Statement( new PropertyNoValueSnak( 12 ) ); + $statementGroup->addStatements( array( $statement, 'foo' ) ); + } + + /** + * @expectedException InvalidArgumentException + */ + public function testAddStatements_noArray() { + $statementGroup = new StatementGroup( 42 ); + $statementGroup->addStatements( 'foo' ); + } + +} From 6c98a5f70b5965356858511b782e54c12beed2c9 Mon Sep 17 00:00:00 2001 From: Bene Date: Wed, 26 Aug 2015 22:43:38 +0200 Subject: [PATCH 2/2] Remove indexing by rank (for now) --- src/Statement/StatementGroup.php | 59 ++++++++++++++++----- tests/unit/Statement/StatementGroupTest.php | 52 ++++++++++++++++-- 2 files changed, 94 insertions(+), 17 deletions(-) diff --git a/src/Statement/StatementGroup.php b/src/Statement/StatementGroup.php index 4161210a..65d775cd 100644 --- a/src/Statement/StatementGroup.php +++ b/src/Statement/StatementGroup.php @@ -2,30 +2,32 @@ namespace Wikibase\DataModel\Statement; +use Countable; use InvalidArgumentException; +use IteratorAggregate; use Traversable; use Wikibase\DataModel\Entity\PropertyId; use Wikibase\DataModel\PropertyIdProvider; /** - * List of statements with the same property id, grouped by rank. + * List of statements with the same property id. * - * @since 4.2 + * @since 4.3 * * @license GNU GPL v2+ * @author Bene* < benestar.wikimedia@gmail.com > */ -class StatementGroup implements PropertyIdProvider { +class StatementGroup implements IteratorAggregate, Countable { /** - * @var Statement[][] + * @var PropertyId */ - private $statementsByRank = array(); + private $propertyId; /** - * @var PropertyId + * @var Statement[] */ - private $propertyId; + private $statements = array(); /** * @param PropertyId|int $propertyId @@ -69,11 +71,10 @@ public function addStatement( Statement $statement ) { throw new InvalidArgumentException( '$statement must have the property id ' . $this->propertyId->getSerialization() ); } - $this->statementsByRank[$statement->getRank()][] = $statement; + $this->statements[] = $statement; } /** - * @see PropertyIdProvider::getPropertyId * @return PropertyId */ public function getPropertyId() { @@ -85,11 +86,45 @@ public function getPropertyId() { * @return Statement[] */ public function getByRank( $rank ) { - if ( isset( $this->statementsByRank[$rank] ) ) { - return $this->statementsByRank[$rank]; + $statements = array(); + + foreach ( $this->statements as $statement ) { + if ( $statement->getRank() === $rank ) { + $statements[] = $statement; + } } - return array(); + return $statements; + } + + /** + * @return Traversable + */ + public function getIterator() { + return new ArrayIterator( $this->statements ); + } + + /** + * @return Statement[] Numerically indexed (non-sparse) array. + */ + public function toArray() { + return $this->statements; + } + + /** + * @see Countable::count + * + * @return int + */ + public function count() { + return count( $this->statements ); + } + + /** + * @return bool + */ + public function isEmpty() { + return empty( $this->statements ); } } diff --git a/tests/unit/Statement/StatementGroupTest.php b/tests/unit/Statement/StatementGroupTest.php index 0f997151..20a02244 100644 --- a/tests/unit/Statement/StatementGroupTest.php +++ b/tests/unit/Statement/StatementGroupTest.php @@ -53,11 +53,11 @@ public function testAddStatement_invalidPropertyId() { $statementGroup->addStatement( $statement ); } - public function testAddStatements() { + public function testAddStatements_validPropertyIds() { $statementGroup = new StatementGroup( 42 ); $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); - $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); - $baz = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'bar' ) ) ); + $baz = new Statement( new PropertyValueSnak( 42, new StringValue( 'baz' ) ) ); $baz->setRank( Statement::RANK_PREFERRED ); $statementGroup->addStatements( array( $foo, $bar, $baz ) ); @@ -72,8 +72,8 @@ public function testAddStatements() { public function testAddStatements_invalidPropertyIds() { $statementGroup = new StatementGroup( 42 ); $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); - $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); - $baz = new Statement( new PropertyValueSnak( 12, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'bar' ) ) ); + $baz = new Statement( new PropertyValueSnak( 12, new StringValue( 'baz' ) ) ); $statementGroup->addStatements( array( $foo, $bar, $baz ) ); } @@ -94,4 +94,46 @@ public function testAddStatements_noArray() { $statementGroup->addStatements( 'foo' ); } + public function testToArray() { + $statementGroup = new StatementGroup( 42 ); + $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'bar' ) ) ); + $baz = new Statement( new PropertyValueSnak( 42, new StringValue( 'baz' ) ) ); + $statementGroup->addStatements( array( $foo, $bar, $baz ) ); + + $this->assertEquals( array( $foo, $bar, $baz ), $statementGroup->toArray() ); + } + + public function testCount_emptyGroup() { + $statementGroup = new StatementGroup( 42 ); + + $this->assertEquals( 0, $statementGroup->count() ); + } + + public function testCount_filledGroup() { + $statementGroup = new StatementGroup( 42 ); + $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'bar' ) ) ); + $baz = new Statement( new PropertyValueSnak( 42, new StringValue( 'baz' ) ) ); + $statementGroup->addStatements( array( $foo, $bar, $baz ) ); + + $this->assertEquals( 3, $statementGroup->count() ); + } + + public function testEmpty_emptyGroup() { + $statementGroup = new StatementGroup( 42 ); + + $this->assertTrue( $statementGroup->isEmpty() ); + } + + public function testEmpty_filledGroup() { + $statementGroup = new StatementGroup( 42 ); + $foo = new Statement( new PropertyValueSnak( 42, new StringValue( 'foo' ) ) ); + $bar = new Statement( new PropertyValueSnak( 42, new StringValue( 'bar' ) ) ); + $baz = new Statement( new PropertyValueSnak( 42, new StringValue( 'baz' ) ) ); + $statementGroup->addStatements( array( $foo, $bar, $baz ) ); + + $this->assertFalse( $statementGroup->isEmpty() ); + } + }