Skip to content

Commit f0060d9

Browse files
committed
Merge pull request #419 from wmde/StatementByGuidMap
Added StatementByGuidMap
2 parents 4879467 + 98a796b commit f0060d9

3 files changed

Lines changed: 319 additions & 1 deletion

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
<?php
2+
3+
namespace Wikibase\DataModel\Statement;
4+
5+
use ArrayIterator;
6+
use Countable;
7+
use InvalidArgumentException;
8+
use IteratorAggregate;
9+
use Traversable;
10+
11+
/**
12+
* Ordered and unique collection of Statement objects.
13+
* Can only contain Statements that have a non-null GUID.
14+
*
15+
* Provides indexed access by Statement GUID.
16+
* Does not provide complex modification functionality.
17+
*
18+
* @since 3.0
19+
*
20+
* @licence GNU GPL v2+
21+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
22+
* @author Kai Nissen < kai.nissen@wikimedia.de >
23+
*/
24+
class StatementByGuidMap implements IteratorAggregate, Countable {
25+
26+
private $statements = array();
27+
28+
/**
29+
* @param Statement[] $statements
30+
*/
31+
public function __construct( $statements = array() ) {
32+
foreach ( $statements as $statement ) {
33+
$this->addStatement( $statement );
34+
}
35+
}
36+
37+
/**
38+
* If the provided statement has a GUID not yet in the map, it will be appended to the map.
39+
* If the GUID is already in the map, the statement with this guid will be replaced.
40+
*
41+
* @param Statement $statement
42+
*/
43+
public function addStatement( Statement $statement ) {
44+
if ( $statement->getGuid() === null ) {
45+
throw new InvalidArgumentException( 'Can only add statements that have a non-null GUID' );
46+
}
47+
48+
$this->statements[$statement->getGuid()] = $statement;
49+
}
50+
51+
/**
52+
* @param string $statementGuid
53+
*
54+
* @return bool
55+
* @throws InvalidArgumentException
56+
*/
57+
public function hasStatementWithGuid( $statementGuid ) {
58+
$this->assertIsStatementGuid( $statementGuid );
59+
60+
return array_key_exists( $statementGuid, $this->statements );
61+
}
62+
63+
private function assertIsStatementGuid( $statementGuid ) {
64+
if ( !is_string( $statementGuid ) ) {
65+
throw new InvalidArgumentException( '$statementGuid needs to be a string' );
66+
}
67+
}
68+
69+
/**
70+
* @param string $statementGuid
71+
*
72+
* @return Statement|null
73+
*/
74+
public function getStatementByGuid( $statementGuid ) {
75+
$this->assertIsStatementGuid( $statementGuid );
76+
77+
if ( array_key_exists( $statementGuid, $this->statements ) ) {
78+
return $this->statements[$statementGuid];
79+
}
80+
81+
return null;
82+
}
83+
84+
/**
85+
* Removes the statement with the specified GUID if it exists.
86+
*
87+
* @param string $statementGuid
88+
*/
89+
public function removeStatementWithGuid( $statementGuid ) {
90+
$this->assertIsStatementGuid( $statementGuid );
91+
unset( $this->statements[$statementGuid] );
92+
}
93+
94+
/**
95+
* @see Countable::count
96+
* @return int
97+
*/
98+
public function count() {
99+
return count( $this->statements );
100+
}
101+
102+
/**
103+
* The iterator has the GUIDs of the statements as keys.
104+
*
105+
* @see IteratorAggregate::getIterator
106+
* @return Traversable
107+
*/
108+
public function getIterator() {
109+
return new ArrayIterator( $this->statements );
110+
}
111+
112+
/**
113+
* Returns the map in array form. The array keys are the GUIDs of their associated statement.
114+
*
115+
* @return Statement[]
116+
*/
117+
public function toArray() {
118+
return $this->statements;
119+
}
120+
121+
}

src/Statement/StatementList.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
use Wikibase\DataModel\Snak\Snaks;
1717

1818
/**
19-
* Ordered, non-unique, collection of Statement objects.
19+
* Ordered and non-unique collection of Statement objects.
2020
* Provides various filter operations.
2121
*
2222
* Does not do any indexing by default.
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
<?php
2+
3+
namespace Wikibase\DataModel\Tests\Statement;
4+
5+
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
6+
use Wikibase\DataModel\Statement\Statement;
7+
use Wikibase\DataModel\Statement\StatementByGuidMap;
8+
9+
/**
10+
* @covers Wikibase\DataModel\Statement\StatementByGuidMap
11+
*
12+
* @licence GNU GPL v2+
13+
* @author Jeroen De Dauw < jeroendedauw@gmail.com >
14+
* @author Kai Nissen < kai.nissen@wikimedia.de >
15+
*/
16+
class StatementByGuidMapTest extends \PHPUnit_Framework_TestCase {
17+
18+
public function testGivenNotPresentGuid_hasClaimWithGuidReturnsFalse() {
19+
$statements = new StatementByGuidMap();
20+
21+
$this->assertFalse( $statements->hasStatementWithGuid( 'some guid' ) );
22+
}
23+
24+
public function testGivenPresentGuid_hasStatementWithGuidReturnsTrue() {
25+
26+
$statements = new StatementByGuidMap( array(
27+
$this->newStatement( 1, 'some guid' )
28+
) );
29+
30+
$this->assertTrue( $statements->hasStatementWithGuid( 'some guid' ) );
31+
}
32+
33+
private function newStatement( $propertyId, $guid ) {
34+
$statement = new Statement( new PropertyNoValueSnak( $propertyId ) );
35+
$statement->setGuid( $guid );
36+
return $statement;
37+
}
38+
39+
/**
40+
* @dataProvider nonStringProvider
41+
*/
42+
public function testGivenNonStringGuid_hasClaimWithGuidThrowsException( $nonString ) {
43+
$statements = new StatementByGuidMap();
44+
45+
$this->setExpectedException( 'InvalidArgumentException' );
46+
$statements->hasStatementWithGuid( $nonString );
47+
}
48+
49+
public function nonStringProvider() {
50+
return array(
51+
array( null ),
52+
array( 42 ),
53+
array( 4.2 ),
54+
array( array() ),
55+
array( (object)array() ),
56+
);
57+
}
58+
59+
public function testGivenGuidOfPresentStatement_getStatementByGuidReturnsStatement() {
60+
$statement = $this->newStatement( 1, 'some guid' );
61+
62+
$statements = new StatementByGuidMap( array( $statement ) );
63+
64+
$this->assertEquals( $statement, $statements->getStatementByGuid( 'some guid' ) );
65+
}
66+
67+
public function testGivenGuidOfNotPresentStatement_getStatementByGuidReturnsNull() {
68+
$statements = new StatementByGuidMap();
69+
70+
$this->assertNull( $statements->getStatementByGuid( 'some guid' ) );
71+
}
72+
73+
/**
74+
* @dataProvider nonStringProvider
75+
*/
76+
public function testGivenNonStringGuid_getStatementByGuidThrowsException( $nonString ) {
77+
$statements = new StatementByGuidMap();
78+
79+
$this->setExpectedException( 'InvalidArgumentException' );
80+
$statements->getStatementByGuid( $nonString );
81+
}
82+
83+
public function testGivenGuidOfPresentStatement_removeStatementWithGuidRemovesTheStatement() {
84+
$statement = $this->newStatement( 1, 'some guid' );
85+
$statements = new StatementByGuidMap( array( $statement ) );
86+
87+
$statements->removeStatementWithGuid( 'some guid' );
88+
89+
$this->assertFalse( $statements->hasStatementWithGuid( 'some guid' ) );
90+
}
91+
92+
public function testGivenGuidOfNonPresentStatement_removeStatementWithGuidDoesNoOp() {
93+
$statement = $this->newStatement( 1, 'some guid' );
94+
$statements = new StatementByGuidMap( array( $statement ) );
95+
96+
$statements->removeStatementWithGuid( '-- different guid --' );
97+
98+
$this->assertTrue( $statements->hasStatementWithGuid( 'some guid' ) );
99+
}
100+
101+
/**
102+
* @dataProvider nonStringProvider
103+
*/
104+
public function testGivenNonStringGuid_removeStatementWithGuidThrowsException( $nonString ) {
105+
$statements = new StatementByGuidMap();
106+
107+
$this->setExpectedException( 'InvalidArgumentException' );
108+
$statements->removeStatementWithGuid( $nonString );
109+
}
110+
111+
public function testGivenStatementWithNoGuid_constructorThrowsException() {
112+
$this->setExpectedException( 'InvalidArgumentException' );
113+
114+
new StatementByGuidMap( array(
115+
$this->newStatement( 1, null )
116+
) );
117+
}
118+
119+
public function testCanConstructWithStatementIterable() {
120+
$statementList = new \ArrayObject( array(
121+
$this->newStatement( 1, 'some guid' )
122+
) );
123+
124+
$statementMap = new StatementByGuidMap( $statementList );
125+
126+
$this->assertTrue( $statementMap->hasStatementWithGuid( 'some guid' ) );
127+
}
128+
129+
public function testWhenMapIsEmpty_countReturnsZero() {
130+
$statements = new StatementByGuidMap();
131+
132+
$this->assertSame( 0, $statements->count() );
133+
}
134+
135+
public function testMapCanBePassedToCount() {
136+
$statements = new StatementByGuidMap( array(
137+
$this->newStatement( 1, 'some guid' ),
138+
$this->newStatement( 2, 'other guid' )
139+
) );
140+
141+
$this->assertSame( 2, count( $statements ) );
142+
}
143+
144+
public function testMapCanBeIteratedOver() {
145+
$statement1 = $this->newStatement( 1, 'some guid' );
146+
$statement2 = $this->newStatement( 2, 'other guid' );
147+
148+
$statementMap = new StatementByGuidMap( array( $statement1, $statement2 ) );
149+
150+
$iteratedStatements = array();
151+
152+
foreach ( $statementMap as $guid => $statement ) {
153+
$iteratedStatements[$guid] = $statement;
154+
}
155+
156+
$expectedStatements = array(
157+
'some guid' => $statement1,
158+
'other guid' => $statement2
159+
);
160+
161+
$this->assertEquals( $expectedStatements, $iteratedStatements );
162+
}
163+
164+
public function testGivenNotPresentStatement_addStatementAddsIt() {
165+
$statements = new StatementByGuidMap();
166+
167+
$statements->addStatement( $this->newStatement( 1, 'some guid' ) );
168+
169+
$this->assertTrue( $statements->hasStatementWithGuid( 'some guid' ) );
170+
}
171+
172+
public function testGivenStatementWithPresentGuid_addStatementReplacesThePresentStatement() {
173+
$statement1 = $this->newStatement( 1, 'some guid' );
174+
$statement2 = $this->newStatement( 2, 'some guid' );
175+
176+
$statements = new StatementByGuidMap( array( $statement1 ) );
177+
178+
$statements->addStatement( $statement2 );
179+
180+
$this->assertEquals( $statement2, $statements->getStatementByGuid( 'some guid' ) );
181+
}
182+
183+
public function testToArray() {
184+
$statement1 = $this->newStatement( 1, 'some guid' );
185+
$statement2 = $this->newStatement( 2, 'other guid' );
186+
187+
$statementMap = new StatementByGuidMap( array( $statement1, $statement2 ) );
188+
189+
$expectedStatements = array(
190+
'some guid' => $statement1,
191+
'other guid' => $statement2
192+
);
193+
194+
$this->assertEquals( $expectedStatements, $statementMap->toArray() );
195+
}
196+
197+
}

0 commit comments

Comments
 (0)