Skip to content

Commit e01251e

Browse files
committed
Create ByPropertyIdMap
1 parent 1e085d2 commit e01251e

4 files changed

Lines changed: 887 additions & 0 deletions

File tree

src/ByPropertyIdArrayNew.php

Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
<?php
2+
3+
namespace Wikibase\DataModel;
4+
5+
use InvalidArgumentException;
6+
use OutOfBoundsException;
7+
use Wikibase\DataModel\Entity\PropertyId;
8+
9+
/**
10+
* Helper for managing objects grouped by property id.
11+
*
12+
* @since 0.2
13+
*
14+
* @license GNU GPL v2+
15+
* @author Bene* < benestar.wikimedia@gmail.com >
16+
*/
17+
class ByPropertyIdArrayNew {
18+
19+
/**
20+
* @var ByPropertyIdGrouper
21+
*/
22+
private $byPropertyIdGrouper;
23+
24+
/**
25+
* @var PropertyIdProvider[]
26+
*/
27+
private $flatArray;
28+
29+
/**
30+
* @param PropertyIdProvider[] $propertyIdProviders
31+
*
32+
* @throws InvalidArgumentException
33+
*/
34+
public function __construct( array $propertyIdProviders ) {
35+
$this->byPropertyIdGrouper = new ByPropertyIdGrouper( $propertyIdProviders );
36+
$this->flatArray = array();
37+
38+
foreach ( $this->byPropertyIdGrouper->getPropertyIds() as $propertyId ) {
39+
$propertyIdProviders = $this->byPropertyIdGrouper->getByPropertyId( $propertyId );
40+
$this->flatArray = array_merge( $this->flatArray, $propertyIdProviders );
41+
}
42+
}
43+
44+
/**
45+
* @since 0.2
46+
* @deprecated since 1.2
47+
*/
48+
public function buildIndex() {}
49+
50+
/**
51+
* @since 0.2
52+
* @deprecated since 1.2
53+
*
54+
* @param PropertyId $propertyId
55+
* @return PropertyIdProvider[]
56+
*
57+
* @throws OutOfBoundsException
58+
*/
59+
public function getByPropertyId( PropertyId $propertyId ) {
60+
return $this->byPropertyIdGrouper->getByPropertyId( $propertyId );
61+
}
62+
63+
/**
64+
* Returns the absolute index of an object or false if the object could not be found.
65+
*
66+
* @since 0.5
67+
* @deprecated since 1.2
68+
*
69+
* @param object $object
70+
* @return bool|int
71+
*
72+
* @throws RuntimeException
73+
*/
74+
public function getFlatArrayIndexOfObject( $object ) {
75+
return array_search( $object, $this->flatArray, true );
76+
}
77+
78+
/**
79+
* @since 0.2
80+
* @deprecated since 1.2
81+
*
82+
* @return PropertyId[]
83+
*/
84+
public function getPropertyIds() {
85+
return $this->byPropertyIdGrouper->getPropertyIds();
86+
}
87+
88+
/**
89+
* Returns a list of all PropertyIdProvider instances grouped by their PropertyId.
90+
*
91+
* @since 0.2
92+
*
93+
* @return PropertyIdProvider[]
94+
*/
95+
public function toFlatArray() {
96+
return $this->flatArray;
97+
}
98+
99+
/**
100+
* Returns the index of the given PropertyIdPovider in the flat array.
101+
*
102+
* @since 1.2
103+
*
104+
* @param PropertyIdProvider $propertyIdProvider
105+
* @return int
106+
*
107+
* @throws OutOfBoundsException
108+
*/
109+
public function getIndex( PropertyIdProvider $propertyIdProvider ) {
110+
$index = array_search( $propertyIdProvider, $this->flatArray, true );
111+
112+
if ( $index === false ) {
113+
throw new OutOfBoundsException( 'The given PropertyIdProvider was not found.' );
114+
}
115+
116+
return $index;
117+
}
118+
119+
/**
120+
* Adds the given PropertyIdProvider to the array at the given index.
121+
*
122+
* @since 0.2
123+
*
124+
* @param PropertyIdProvider $propertyIdProvider
125+
* @param int $index
126+
*
127+
* @throws InvalidArgumentException
128+
* @throws OutOfBoundsException
129+
*/
130+
public function addObjectAtIndex( PropertyIdProvider $propertyIdProvider, $index ) {
131+
$this->assertValidIndex( $index );
132+
133+
$groupIndices = $this->getFlatArrayGroupIndices();
134+
$propertyId = $propertyIdProvider->getPropertyId();
135+
$idSerialization = $propertyId->getSerialization();
136+
137+
if ( isset( $groupIndices[$idSerialization] ) ) {
138+
$groupIndex = $groupIndices[$idSerialization];
139+
$count = count( $this->byPropertyIdGrouper->getByPropertyId( $propertyId ) );
140+
} else {
141+
$groupIndex = 0;
142+
$count = 0;
143+
}
144+
145+
// if not inside of group also move property group
146+
if ( $index < $groupIndex || $groupIndex + $count <= $index ) {
147+
// find real index to insert
148+
$index = $index === 0 ? 0 : $this->findNextIndex( $index );
149+
$this->moveGroupInFlatArray( $groupIndex, $count, $index );
150+
}
151+
152+
$this->addtoFlatArray( $propertyIdProvider, $index );
153+
$this->byPropertyIdGrouper = new ByPropertyIdGrouper( $this->flatArray );
154+
}
155+
156+
/**
157+
* Removes the PropertyIdProvider at the given index and returns it.
158+
*
159+
* @since 1.2
160+
*
161+
* @param int $index
162+
* @return PropertyIdProvider
163+
*
164+
* @throws InvalidArgumentException
165+
* @throws OutOfBoundsException
166+
*/
167+
public function removeAtIndex( $index ) {
168+
$this->assertValidIndex( $index );
169+
170+
$object = $this->removeFromFlatArray( $index );
171+
$this->byPropertyIdGrouper = new ByPropertyIdGrouper( $this->flatArray );
172+
173+
return $object;
174+
}
175+
176+
/**
177+
* Removes the given PropertyIdProvider and returns it.
178+
*
179+
* @since 1.2
180+
*
181+
* @param PropertyIdProvider $propertyIdProvider
182+
* @return PropertyIdProvider
183+
*
184+
* @throws InvalidArgumentException
185+
* @throws OutOfBoundsException
186+
*/
187+
public function removeObject( PropertyIdProvider $propertyIdProvider ) {
188+
return $this->removeAtIndex( $this->getIndex( $propertyIdProvider ) );
189+
}
190+
191+
/**
192+
* Moves a PropertyIdProvider from the old to the new index and returns it.
193+
*
194+
* @since 1.2
195+
*
196+
* @param int $oldIndex
197+
* @param int $newIndex
198+
* @return PropertyIdProvider
199+
*
200+
* @throws InvalidArgumentException
201+
* @throws OutOfBoundsException
202+
*/
203+
public function moveToIndex( $oldIndex, $newIndex ) {
204+
$this->assertValidIndex( $oldIndex );
205+
$this->assertValidIndex( $newIndex );
206+
207+
$object = $this->removeAtIndex( $oldIndex );
208+
$this->addObjectAtIndex( $object, $newIndex );
209+
210+
return $object;
211+
}
212+
213+
/**
214+
* Moves the given PropertyIdProvider to the new index and returns it.
215+
*
216+
* @since 0.2
217+
*
218+
* @param PropertyIdProvider $propertyIdProvider
219+
* @param int $index
220+
* @return PropertyIdProvider
221+
*
222+
* @throws InvalidArgumentException
223+
* @throws OutOfBoundsException
224+
*/
225+
public function moveObjectToIndex( PropertyIdProvider $propertyIdProvider, $index ) {
226+
return $this->moveToIndex( $this->getIndex( $propertyIdProvider ), $index );
227+
}
228+
229+
/**
230+
* Adds the object at the given index.
231+
* @see array_splice
232+
*
233+
* @param PropertyIdProvider $propertyIdProvider
234+
* @param int $index
235+
*/
236+
private function addtoFlatArray( PropertyIdProvider $propertyIdProvider, $index ) {
237+
array_splice( $this->flatArray, $index, 0, array( $propertyIdProvider ) );
238+
}
239+
240+
/**
241+
* Removes the object at the given index and returns it.
242+
* @see array_splice
243+
*
244+
* @param int $index
245+
* @return PropertyIdProvider
246+
*/
247+
private function removeFromFlatArray( $index ) {
248+
$objects = array_splice( $this->flatArray, $index, 1 );
249+
return $objects[0];
250+
}
251+
252+
/**
253+
* Moves a list of objects with the given length from the start to the target index.
254+
* @see array_splice
255+
*
256+
* @param int $start
257+
* @param int $length
258+
* @param int $target
259+
*/
260+
private function moveGroupInFlatArray( $start, $length, $target ) {
261+
// make sure we do not exceed the limits
262+
if ( $start < $target ) {
263+
$target = $target - $length;
264+
}
265+
266+
$objects = array_splice( $this->flatArray, $start, $length );
267+
array_splice( $this->flatArray, $target, 0, $objects );
268+
}
269+
270+
/**
271+
* Finds the next index in the flat array which starts a new PropertyId group.
272+
*
273+
* @param int $index
274+
* @return int
275+
*/
276+
private function findNextIndex( $index ) {
277+
$groupIndices = $this->getFlatArrayGroupIndices();
278+
279+
foreach ( $groupIndices as $groupIndex ) {
280+
if ( $groupIndex >= $index ) {
281+
return $groupIndex;
282+
}
283+
}
284+
285+
return count( $this->flatArray );
286+
}
287+
288+
/**
289+
* Finds all indeces where a new PropertyId group starts.
290+
*
291+
* @return int[]
292+
*/
293+
private function getFlatArrayGroupIndices() {
294+
$indices = array();
295+
$index = 0;
296+
297+
foreach ( $this->byPropertyIdGrouper->getPropertyIds() as $propertyId ) {
298+
$indices[$propertyId->getSerialization()] = $index;
299+
$index += count( $this->byPropertyIdGrouper->getByPropertyId( $propertyId ) );
300+
}
301+
302+
return $indices;
303+
}
304+
305+
/**
306+
* Asserts that the given paramter is a valid index.
307+
*
308+
* @param int $index
309+
*
310+
* @throws InvalidArgumentException
311+
* @throws OutOfBoundsException
312+
*/
313+
private function assertValidIndex( $index ) {
314+
if ( !is_int( $index ) ) {
315+
throw new InvalidArgumentException( 'Only integer indices are supported.' );
316+
}
317+
318+
if ( $index < 0 || $index > count( $this->flatArray ) ) {
319+
throw new OutOfBoundsException( 'The index exceeds the array dimensions.' );
320+
}
321+
}
322+
323+
}

0 commit comments

Comments
 (0)