Skip to content

Commit bd63f2f

Browse files
committed
Create ByPropertyIdMap
1 parent 1e085d2 commit bd63f2f

2 files changed

Lines changed: 396 additions & 0 deletions

File tree

src/ByPropertyIdMap.php

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
<?php
2+
3+
namespace Wikibase\DataModel;
4+
5+
use InvalidArgumentException;
6+
use OutOfBoundsException;
7+
use Traversable;
8+
use Wikibase\DataModel\Entity\PropertyId;
9+
10+
/**
11+
* Maps property id providers by their property id.
12+
*
13+
* @since 3.0
14+
*
15+
* @license GNU GPL v2+
16+
* @author Bene* < benestar.wikimedia@gmail.com >
17+
*/
18+
class ByPropertyIdMap {
19+
20+
/**
21+
* @var array[]
22+
*/
23+
private $byPropertyId = array();
24+
25+
/**
26+
* @var PropertyId[]
27+
*/
28+
private $propertyIds = array();
29+
30+
/**
31+
* @param PropertyIdProvider[]|Traversable $propertyIdProviders
32+
*
33+
* @throws InvalidArgumentException
34+
*/
35+
public function __construct( $propertyIdProviders ) {
36+
$byPropertyIdGrouper = new ByPropertyIdGrouper( $propertyIdProviders );
37+
38+
$this->propertyIds = $byPropertyIdGrouper->getPropertyIds();
39+
foreach ( $this->propertyIds as $propertyId ) {
40+
$this->byPropertyId[$propertyId->getSerialization()] = $byPropertyIdGrouper->getByPropertyId( $propertyId );
41+
}
42+
}
43+
44+
/**
45+
* @param PropertyId $propertyId
46+
* @param int $index
47+
* @throws InvalidArgumentException
48+
* @throws OutOfBoundsException
49+
*/
50+
public function moveGroupToIndex( PropertyId $propertyId, $index ) {
51+
$this->assertIsIndex( $index );
52+
53+
$oldIndex = array_search( $propertyId, $this->propertyIds );
54+
55+
if ( $oldIndex === false ) {
56+
throw new OutOfBoundsException( 'There is no group for property id ' . $propertyId->getSerialization() );
57+
}
58+
59+
array_splice( $this->propertyIds, $oldIndex, 1 );
60+
array_splice( $this->propertyIds, $index, 0, array( $propertyId ) );
61+
}
62+
63+
/**
64+
* @param PropertyIdProvider $propertyIdProvider
65+
* @param int $index
66+
* @throws InvalidArgumentException
67+
* @throws OutOfBoundsException
68+
*/
69+
public function movePropertyIdProviderToIndex( PropertyIdProvider $propertyIdProvider, $index ) {
70+
$this->assertIsIndex( $index );
71+
72+
$idSerialization = $propertyIdProvider->getPropertyId()->getSerialization();
73+
74+
if ( !isset( $this->byPropertyId[$idSerialization] ) ) {
75+
throw new OutOfBoundsException( 'There is no group for property id ' . $idSerialization );
76+
}
77+
78+
$oldIndex = array_search( $propertyIdProvider, $this->byPropertyId[$idSerialization] );
79+
80+
if ( $oldIndex === false ) {
81+
throw new OutOfBoundsException( 'The property id provider does not exist in this map.' );
82+
}
83+
84+
array_splice( $this->byPropertyId[$idSerialization], $oldIndex, 1 );
85+
array_splice( $this->byPropertyId[$idSerialization], $index, 0, array( $propertyIdProvider ) );
86+
}
87+
88+
/**
89+
* @param PropertyIdProvider $propertyIdProvider
90+
* @param int $index
91+
* @throws InvalidArgumentException
92+
*/
93+
public function addPropertyIdProviderAtIndex( PropertyIdProvider $propertyIdProvider, $index ) {
94+
$this->assertIsIndex( $index );
95+
96+
$idSerialization = $propertyIdProvider->getPropertyId()->getSerialization();
97+
98+
if ( !isset( $this->byPropertyId[$idSerialization] ) ) {
99+
$this->byPropertyId[$idSerialization] = array();
100+
$this->propertyIds[] = $propertyIdProvider->getPropertyId();
101+
}
102+
103+
array_splice( $this->byPropertyId[$idSerialization], $index, 0, array( $propertyIdProvider ) );
104+
}
105+
106+
private function assertIsIndex( $index ) {
107+
if ( !is_int( $index ) || $index < 0 ) {
108+
throw new InvalidArgumentException( '$index must be a non-negative integer.' );
109+
}
110+
}
111+
112+
/**
113+
* @return PropertyIdProvider[]
114+
*/
115+
public function getFlatArray() {
116+
$propertyIdProviders = array();
117+
118+
foreach ( $this->propertyIds as $propertyId ) {
119+
foreach ( $this->byPropertyId[$propertyId->getSerialization()] as $propertyIdProvider ) {
120+
$propertyIdProviders[] = $propertyIdProvider;
121+
}
122+
}
123+
124+
return $propertyIdProviders;
125+
}
126+
127+
}

tests/unit/ByPropertyIdMapTest.php

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
<?php
2+
3+
namespace Wikibase\Test;
4+
5+
use DataValues\StringValue;
6+
use Wikibase\DataModel\ByPropertyIdMap;
7+
use Wikibase\DataModel\Entity\PropertyId;
8+
use Wikibase\DataModel\Snak\PropertyValueSnak;
9+
10+
/**
11+
* @covers Wikibase\DataModel\ByPropertyIdMap
12+
*
13+
* @author Bene* < benestar.wikimedia@gmail.com >
14+
*/
15+
class ByPropertyIdMapTest extends \PHPUnit_Framework_TestCase {
16+
17+
private function getPropertyIdProvider( $propertyId, $value ) {
18+
return new PropertyValueSnak( new PropertyId( $propertyId ), new StringValue( $value ) );
19+
}
20+
21+
private function assertTypesAreEqual( array $types, ByPropertyIdMap $byPropertyIdMap ) {
22+
$flatArray = $byPropertyIdMap->getFlatArray();
23+
24+
array_walk( $flatArray, function( PropertyValueSnak &$snak ) {
25+
$snak = $snak->getDataValue()->getValue();
26+
} );
27+
28+
$this->assertEquals( $types, $flatArray );
29+
}
30+
31+
public function testConstructWithGroupedList_getFlatArrayReturnsSameList() {
32+
$byPropertyIdMap = new ByPropertyIdMap( array(
33+
$this->getPropertyIdProvider( 'P321', 'foo' ),
34+
$this->getPropertyIdProvider( 'P123', 'bar' ),
35+
$this->getPropertyIdProvider( 'P123', 'baz' ),
36+
$this->getPropertyIdProvider( 'P789', 'boo' )
37+
) );
38+
39+
$this->assertTypesAreEqual( array( 'foo', 'bar', 'baz', 'boo' ), $byPropertyIdMap );
40+
}
41+
42+
public function testConstructWithUngroupedList_getFlatArrayReturnsGroupedList() {
43+
$byPropertyIdMap = new ByPropertyIdMap( array(
44+
$this->getPropertyIdProvider( 'P321', 'foo' ),
45+
$this->getPropertyIdProvider( 'P123', 'bar' ),
46+
$this->getPropertyIdProvider( 'P123', 'baz' ),
47+
$this->getPropertyIdProvider( 'P321', 'boo' )
48+
) );
49+
50+
$this->assertTypesAreEqual( array( 'foo', 'boo', 'bar', 'baz' ), $byPropertyIdMap );
51+
}
52+
53+
public function testGivenIntegerIndex_moveGroupToIndexMovesGroup() {
54+
$byPropertyIdMap = new ByPropertyIdMap( array(
55+
$this->getPropertyIdProvider( 'P321', 'foo' ),
56+
$this->getPropertyIdProvider( 'P123', 'bar' ),
57+
$this->getPropertyIdProvider( 'P123', 'baz' ),
58+
$this->getPropertyIdProvider( 'P789', 'boo' )
59+
) );
60+
61+
$byPropertyIdMap->moveGroupToIndex( new PropertyId( 'P123' ), 2 );
62+
63+
$this->assertTypesAreEqual( array( 'foo', 'boo', 'bar', 'baz' ), $byPropertyIdMap );
64+
}
65+
66+
public function testGivenZeroIndex_moveGroupToIndexMovesGroupToBeginning() {
67+
$byPropertyIdMap = new ByPropertyIdMap( array(
68+
$this->getPropertyIdProvider( 'P321', 'foo' ),
69+
$this->getPropertyIdProvider( 'P123', 'bar' ),
70+
$this->getPropertyIdProvider( 'P123', 'baz' ),
71+
$this->getPropertyIdProvider( 'P789', 'boo' )
72+
) );
73+
74+
$byPropertyIdMap->moveGroupToIndex( new PropertyId( 'P789' ), 0 );
75+
76+
$this->assertTypesAreEqual( array( 'boo', 'foo', 'bar', 'baz' ), $byPropertyIdMap );
77+
}
78+
79+
public function testGivenHugeIndex_moveGroupToIndexMovesGroupToEnd() {
80+
$byPropertyIdMap = new ByPropertyIdMap( array(
81+
$this->getPropertyIdProvider( 'P321', 'foo' ),
82+
$this->getPropertyIdProvider( 'P123', 'bar' ),
83+
$this->getPropertyIdProvider( 'P123', 'baz' ),
84+
$this->getPropertyIdProvider( 'P789', 'boo' )
85+
) );
86+
87+
$byPropertyIdMap->moveGroupToIndex( new PropertyId( 'P321' ), 999999 );
88+
89+
$this->assertTypesAreEqual( array( 'bar', 'baz', 'boo', 'foo' ), $byPropertyIdMap );
90+
}
91+
92+
/**
93+
* @expectedException InvalidArgumentException
94+
*/
95+
public function testGivenNonIntegerIndex_moveGroupToIndexThrowsException() {
96+
$byPropertyIdMap = new ByPropertyIdMap( array() );
97+
98+
$byPropertyIdMap->moveGroupToIndex( new PropertyId( 'P42' ), null );
99+
}
100+
101+
/**
102+
* @expectedException InvalidArgumentException
103+
*/
104+
public function testGivenNegativeIndex_moveGroupToIndexThrowsException() {
105+
$byPropertyIdMap = new ByPropertyIdMap( array() );
106+
107+
$byPropertyIdMap->moveGroupToIndex( new PropertyId( 'P42' ), -1 );
108+
}
109+
110+
/**
111+
* @expectedException OutOfBoundsException
112+
*/
113+
public function testGivenNotExistingPropertyId_moveGroupToIndexThrowsException() {
114+
$byPropertyIdMap = new ByPropertyIdMap( array() );
115+
116+
$byPropertyIdMap->moveGroupToIndex( new PropertyId( 'P42' ), 0 );
117+
}
118+
119+
public function testGivenIntegerIndex_movePropertyIdProviderToIndexMovesPropertyIdProvider() {
120+
$byPropertyIdMap = new ByPropertyIdMap( array(
121+
$this->getPropertyIdProvider( 'P321', 'foo' ),
122+
$this->getPropertyIdProvider( 'P123', 'bar' ),
123+
$this->getPropertyIdProvider( 'P123', 'baz' ),
124+
$this->getPropertyIdProvider( 'P123', 'boo' )
125+
) );
126+
127+
$propertyIdProvider = $this->getPropertyIdProvider( 'P123', 'bar' );
128+
$byPropertyIdMap->movePropertyIdProviderToIndex( $propertyIdProvider, 1 );
129+
130+
$this->assertTypesAreEqual( array( 'foo', 'baz', 'bar', 'boo' ), $byPropertyIdMap );
131+
}
132+
133+
public function testGivenZeroIndex_movePropertyIdProviderToIndexMovesPropertyIdProviderToBeginning() {
134+
$byPropertyIdMap = new ByPropertyIdMap( array(
135+
$this->getPropertyIdProvider( 'P321', 'foo' ),
136+
$this->getPropertyIdProvider( 'P123', 'bar' ),
137+
$this->getPropertyIdProvider( 'P123', 'baz' ),
138+
$this->getPropertyIdProvider( 'P123', 'boo' )
139+
) );
140+
141+
$propertyIdProvider = $this->getPropertyIdProvider( 'P123', 'boo' );
142+
$byPropertyIdMap->movePropertyIdProviderToIndex( $propertyIdProvider, 0 );
143+
144+
$this->assertTypesAreEqual( array( 'foo', 'boo', 'bar', 'baz' ), $byPropertyIdMap );
145+
}
146+
147+
public function testGivenHugeIndex_movePropertyIdProviderToIndexMovesPropertyIdProviderToEnd() {
148+
$byPropertyIdMap = new ByPropertyIdMap( array(
149+
$this->getPropertyIdProvider( 'P321', 'foo' ),
150+
$this->getPropertyIdProvider( 'P123', 'bar' ),
151+
$this->getPropertyIdProvider( 'P123', 'baz' ),
152+
$this->getPropertyIdProvider( 'P123', 'boo' )
153+
) );
154+
155+
$propertyIdProvider = $this->getPropertyIdProvider( 'P123', 'baz' );
156+
$byPropertyIdMap->movePropertyIdProviderToIndex( $propertyIdProvider, 999999 );
157+
158+
$this->assertTypesAreEqual( array( 'foo', 'bar', 'boo', 'baz' ), $byPropertyIdMap );
159+
}
160+
161+
/**
162+
* @expectedException InvalidArgumentException
163+
*/
164+
public function testGivenNonIntegerIndex_movePropertyIdProviderToIndexThrowsException() {
165+
$byPropertyIdMap = new ByPropertyIdMap( array() );
166+
167+
$byPropertyIdMap->movePropertyIdProviderToIndex( $this->getPropertyIdProvider( 'P42', 'foo' ), null );
168+
}
169+
170+
/**
171+
* @expectedException InvalidArgumentException
172+
*/
173+
public function testGivenNegativeIndex_movePropertyIdProviderToIndexThrowsException() {
174+
$byPropertyIdMap = new ByPropertyIdMap( array() );
175+
176+
$byPropertyIdMap->movePropertyIdProviderToIndex( $this->getPropertyIdProvider( 'P42', 'foo' ), -1 );
177+
}
178+
179+
/**
180+
* @expectedException OutOfBoundsException
181+
*/
182+
public function testGivenNotExistingPropertyId_movePropertyIdProviderToIndexThrowsException() {
183+
$byPropertyIdMap = new ByPropertyIdMap( array() );
184+
185+
$byPropertyIdMap->movePropertyIdProviderToIndex( $this->getPropertyIdProvider( 'P42', 'foo' ), 0 );
186+
}
187+
188+
/**
189+
* @expectedException OutOfBoundsException
190+
*/
191+
public function testGivenNotExistingPropertyIdProvider_movePropertyIdProviderToIndexThrowsException() {
192+
$byPropertyIdMap = new ByPropertyIdMap( array(
193+
$this->getPropertyIdProvider( 'P42', 'foo' )
194+
) );
195+
196+
$byPropertyIdMap->movePropertyIdProviderToIndex( $this->getPropertyIdProvider( 'P42', 'bar' ), 0 );
197+
}
198+
199+
public function testGivenIntegerIndex_addPropertyIdProviderAtIndexAddsPropertyIdProvider() {
200+
$byPropertyIdMap = new ByPropertyIdMap( array(
201+
$this->getPropertyIdProvider( 'P321', 'foo' ),
202+
$this->getPropertyIdProvider( 'P123', 'bar' ),
203+
$this->getPropertyIdProvider( 'P123', 'baz' )
204+
) );
205+
206+
$propertyIdProvider = $this->getPropertyIdProvider( 'P123', 'boo' );
207+
$byPropertyIdMap->addPropertyIdProviderAtIndex( $propertyIdProvider, 1 );
208+
209+
$this->assertTypesAreEqual( array( 'foo', 'bar', 'boo', 'baz' ), $byPropertyIdMap );
210+
}
211+
212+
public function testGivenZeroIndex_addPropertyIdProviderAtIndexAddsPropertyIdProviderAtBeginning() {
213+
$byPropertyIdMap = new ByPropertyIdMap( array(
214+
$this->getPropertyIdProvider( 'P321', 'foo' ),
215+
$this->getPropertyIdProvider( 'P123', 'bar' ),
216+
$this->getPropertyIdProvider( 'P123', 'baz' )
217+
) );
218+
219+
$propertyIdProvider = $this->getPropertyIdProvider( 'P321', 'boo' );
220+
$byPropertyIdMap->addPropertyIdProviderAtIndex( $propertyIdProvider, 0 );
221+
222+
$this->assertTypesAreEqual( array( 'boo', 'foo', 'bar', 'baz' ), $byPropertyIdMap );
223+
}
224+
225+
public function testGivenHugeIndex_addPropertyIdProviderAtIndexAddsPropertyIdProviderAtEnd() {
226+
$byPropertyIdMap = new ByPropertyIdMap( array(
227+
$this->getPropertyIdProvider( 'P321', 'foo' ),
228+
$this->getPropertyIdProvider( 'P123', 'bar' ),
229+
$this->getPropertyIdProvider( 'P123', 'baz' )
230+
) );
231+
232+
$propertyIdProvider = $this->getPropertyIdProvider( 'P321', 'boo' );
233+
$byPropertyIdMap->addPropertyIdProviderAtIndex( $propertyIdProvider, 999999 );
234+
235+
$this->assertTypesAreEqual( array( 'foo', 'boo', 'bar', 'baz' ), $byPropertyIdMap );
236+
}
237+
238+
public function testGivenNotExistingPropertyId_addPropertyIdProviderAtIndexCreatesNewGroupAtEnd() {
239+
$byPropertyIdMap = new ByPropertyIdMap( array(
240+
$this->getPropertyIdProvider( 'P321', 'foo' ),
241+
$this->getPropertyIdProvider( 'P123', 'bar' ),
242+
$this->getPropertyIdProvider( 'P123', 'baz' )
243+
) );
244+
245+
$propertyIdProvider = $this->getPropertyIdProvider( 'P456', 'boo' );
246+
$byPropertyIdMap->addPropertyIdProviderAtIndex( $propertyIdProvider, 1 );
247+
248+
$this->assertTypesAreEqual( array( 'foo', 'bar', 'baz', 'boo' ), $byPropertyIdMap );
249+
}
250+
251+
/**
252+
* @expectedException InvalidArgumentException
253+
*/
254+
public function testGivenNonIntegerIndex_addPropertyIdProviderAtIndexThrowsException() {
255+
$byPropertyIdMap = new ByPropertyIdMap( array() );
256+
257+
$byPropertyIdMap->addPropertyIdProviderAtIndex( $this->getPropertyIdProvider( 'P42', 'foo' ), null );
258+
}
259+
260+
/**
261+
* @expectedException InvalidArgumentException
262+
*/
263+
public function testGivenNegativeIndex_addPropertyIdProviderAtIndexThrowsException() {
264+
$byPropertyIdMap = new ByPropertyIdMap( array() );
265+
266+
$byPropertyIdMap->addPropertyIdProviderAtIndex( $this->getPropertyIdProvider( 'P42', 'foo' ), -1 );
267+
}
268+
269+
}

0 commit comments

Comments
 (0)