|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
namespace Wikibase\DataModel; |
|
4
|
|
|
|
|
5
|
|
|
use Hashable; |
|
6
|
|
|
use InvalidArgumentException; |
|
7
|
|
|
use Traversable; |
|
8
|
|
|
use Wikibase\DataModel\Snak\Snak; |
|
9
|
|
|
|
|
10
|
|
|
/** |
|
11
|
|
|
* List of Reference objects. |
|
12
|
|
|
* |
|
13
|
|
|
* Note that this implementation is based on SplObjectStorage and |
|
14
|
|
|
* is not enforcing the type of objects set via it's native methods. |
|
15
|
|
|
* Therefore one can add non-Reference-implementing objects when |
|
16
|
|
|
* not sticking to the methods of the References interface. |
|
17
|
|
|
* |
|
18
|
|
|
* @since 0.1 |
|
19
|
|
|
* Does not implement References anymore since 2.0 |
|
20
|
|
|
* |
|
21
|
|
|
* @licence GNU GPL v2+ |
|
22
|
|
|
* @author Jeroen De Dauw < [email protected] > |
|
23
|
|
|
* @author H. Snater < [email protected] > |
|
24
|
|
|
* @author Thiemo Mättig |
|
25
|
|
|
*/ |
|
26
|
|
|
class ReferenceList extends HashableObjectStorage { |
|
|
|
|
|
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* @param Reference[]|Traversable $references |
|
30
|
|
|
* |
|
31
|
|
|
* @throws InvalidArgumentException |
|
32
|
|
|
*/ |
|
33
|
|
|
public function __construct( $references = array() ) { |
|
34
|
29 |
|
if ( !is_array( $references ) && !( $references instanceof Traversable ) ) { |
|
35
|
29 |
|
throw new InvalidArgumentException( '$references must be an array or an instance of Traversable' ); |
|
36
|
8 |
|
} |
|
37
|
|
|
|
|
38
|
|
|
foreach ( $references as $reference ) { |
|
39
|
21 |
|
if ( !( $reference instanceof Reference ) ) { |
|
40
|
12 |
|
throw new InvalidArgumentException( 'Every element in $references must be an instance of Reference' ); |
|
41
|
4 |
|
} |
|
42
|
|
|
|
|
43
|
|
|
$this->addReference( $reference ); |
|
44
|
8 |
|
} |
|
45
|
17 |
|
} |
|
46
|
17 |
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* Adds the provided reference to the list. |
|
49
|
|
|
* |
|
50
|
|
|
* @since 0.1 |
|
51
|
|
|
* |
|
52
|
|
|
* @param Reference $reference |
|
53
|
|
|
* @param int|null $index |
|
54
|
|
|
* |
|
55
|
|
|
* @throws InvalidArgumentException |
|
56
|
|
|
*/ |
|
57
|
|
|
public function addReference( Reference $reference, $index = null ) { |
|
58
|
14 |
|
if ( !is_int( $index ) && $index !== null ) { |
|
59
|
14 |
|
throw new InvalidArgumentException( '$index must be an integer or null' ); |
|
60
|
|
|
} |
|
61
|
|
|
|
|
62
|
|
|
if ( $index === null || $index >= count( $this ) ) { |
|
63
|
14 |
|
// Append object to the end of the reference list. |
|
64
|
|
|
$this->attach( $reference ); |
|
65
|
14 |
|
} else { |
|
66
|
14 |
|
$this->insertReferenceAtIndex( $reference, $index ); |
|
67
|
2 |
|
} |
|
68
|
|
|
} |
|
69
|
14 |
|
|
|
70
|
|
|
/** |
|
71
|
|
|
* @see SplObjectStorage::attach |
|
72
|
|
|
* |
|
73
|
|
|
* @param Reference $reference |
|
74
|
|
|
* @param mixed $data Unused in the ReferenceList class. |
|
75
|
|
|
*/ |
|
76
|
|
|
public function attach( $reference, $data = null ) { |
|
77
|
14 |
|
if ( !$reference->isEmpty() ) { |
|
78
|
14 |
|
parent::attach( $reference, $data ); |
|
79
|
14 |
|
} |
|
80
|
14 |
|
} |
|
81
|
14 |
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* @since 1.1 |
|
84
|
|
|
* |
|
85
|
|
|
* @param Snak[]|Snak $snaks |
|
86
|
|
|
* @param Snak [$snak2,...] |
|
87
|
|
|
* |
|
88
|
|
|
* @throws InvalidArgumentException |
|
89
|
|
|
*/ |
|
90
|
|
|
public function addNewReference( $snaks = array() /*...*/ ) { |
|
91
|
6 |
|
if ( $snaks instanceof Snak ) { |
|
92
|
6 |
|
$snaks = func_get_args(); |
|
93
|
5 |
|
} |
|
94
|
5 |
|
|
|
95
|
|
|
$this->addReference( new Reference( $snaks ) ); |
|
96
|
6 |
|
} |
|
97
|
5 |
|
|
|
98
|
|
|
/** |
|
99
|
|
|
* @param Reference $reference |
|
100
|
|
|
* @param int $index |
|
101
|
|
|
*/ |
|
102
|
|
|
private function insertReferenceAtIndex( Reference $reference, $index ) { |
|
103
|
2 |
|
$referencesToShift = array(); |
|
104
|
2 |
|
$i = 0; |
|
105
|
2 |
|
|
|
106
|
|
|
// Determine the references that need to be shifted and detach them: |
|
107
|
|
|
foreach ( $this as $object ) { |
|
108
|
2 |
|
if ( $i++ >= $index ) { |
|
109
|
2 |
|
$referencesToShift[] = $object; |
|
110
|
2 |
|
} |
|
111
|
2 |
|
} |
|
112
|
2 |
|
|
|
113
|
|
|
foreach ( $referencesToShift as $object ) { |
|
114
|
2 |
|
$this->detach( $object ); |
|
115
|
2 |
|
} |
|
116
|
2 |
|
|
|
117
|
|
|
// Attach the new reference and reattach the previously detached references: |
|
118
|
|
|
$this->attach( $reference ); |
|
119
|
2 |
|
|
|
120
|
|
|
foreach ( $referencesToShift as $object ) { |
|
121
|
2 |
|
$this->attach( $object ); |
|
122
|
2 |
|
} |
|
123
|
2 |
|
} |
|
124
|
2 |
|
|
|
125
|
|
|
/** |
|
126
|
|
|
* Returns if the list contains a reference with the same hash as the provided reference. |
|
127
|
|
|
* |
|
128
|
|
|
* @since 0.1 |
|
129
|
|
|
* |
|
130
|
|
|
* @param Reference $reference |
|
131
|
|
|
* |
|
132
|
|
|
* @return boolean |
|
133
|
|
|
*/ |
|
134
|
|
|
public function hasReference( Reference $reference ) { |
|
135
|
6 |
|
return $this->contains( $reference ) |
|
136
|
6 |
|
|| $this->hasReferenceHash( $reference->getHash() ); |
|
137
|
6 |
|
} |
|
138
|
|
|
|
|
139
|
|
|
/** |
|
140
|
|
|
* Returns the index of a reference or false if the reference could not be found. |
|
141
|
|
|
* |
|
142
|
|
|
* @since 0.5 |
|
143
|
|
|
* |
|
144
|
|
|
* @param Reference $reference |
|
145
|
|
|
* |
|
146
|
|
|
* @return int|boolean |
|
147
|
|
|
*/ |
|
148
|
|
|
public function indexOf( Reference $reference ) { |
|
149
|
2 |
|
$index = 0; |
|
150
|
2 |
|
|
|
151
|
|
|
foreach ( $this as $object ) { |
|
152
|
2 |
|
if ( $object === $reference ) { |
|
153
|
1 |
|
return $index; |
|
154
|
1 |
|
} |
|
155
|
|
|
$index++; |
|
156
|
1 |
|
} |
|
157
|
2 |
|
|
|
158
|
|
|
return false; |
|
159
|
2 |
|
} |
|
160
|
|
|
|
|
161
|
|
|
/** |
|
162
|
|
|
* Removes the reference with the same hash as the provided reference if such a reference exists in the list. |
|
163
|
|
|
* |
|
164
|
|
|
* @since 0.1 |
|
165
|
|
|
* |
|
166
|
|
|
* @param Reference $reference |
|
167
|
|
|
*/ |
|
168
|
|
|
public function removeReference( Reference $reference ) { |
|
169
|
3 |
|
$this->removeReferenceHash( $reference->getHash() ); |
|
170
|
3 |
|
} |
|
171
|
3 |
|
|
|
172
|
|
|
/** |
|
173
|
|
|
* Returns if the list contains a reference with the provided hash. |
|
174
|
|
|
* |
|
175
|
|
|
* @since 0.3 |
|
176
|
|
|
* |
|
177
|
|
|
* @param string $referenceHash |
|
178
|
|
|
* |
|
179
|
|
|
* @return boolean |
|
180
|
|
|
*/ |
|
181
|
|
|
public function hasReferenceHash( $referenceHash ) { |
|
182
|
8 |
|
return $this->getReference( $referenceHash ) !== null; |
|
183
|
8 |
|
} |
|
184
|
|
|
|
|
185
|
|
|
/** |
|
186
|
|
|
* Removes the reference with the provided hash if it exists in the list. |
|
187
|
|
|
* |
|
188
|
|
|
* @since 0.3 |
|
189
|
|
|
* |
|
190
|
|
|
* @param string $referenceHash ` |
|
191
|
|
|
*/ |
|
192
|
|
|
public function removeReferenceHash( $referenceHash ) { |
|
193
|
5 |
|
$reference = $this->getReference( $referenceHash ); |
|
194
|
5 |
|
|
|
195
|
|
|
if ( $reference !== null ) { |
|
196
|
5 |
|
$this->detach( $reference ); |
|
197
|
3 |
|
} |
|
198
|
3 |
|
} |
|
199
|
5 |
|
|
|
200
|
|
|
/** |
|
201
|
|
|
* Returns the reference with the provided hash, or null if there is no such reference in the list. |
|
202
|
|
|
* |
|
203
|
|
|
* @since 0.3 |
|
204
|
|
|
* |
|
205
|
|
|
* @param string $referenceHash |
|
206
|
|
|
* |
|
207
|
|
|
* @return Reference|null |
|
208
|
|
|
*/ |
|
209
|
|
|
public function getReference( $referenceHash ) { |
|
210
|
14 |
|
/** |
|
211
|
|
|
* @var Hashable $hashable |
|
212
|
|
|
*/ |
|
213
|
|
|
foreach ( $this as $hashable ) { |
|
214
|
14 |
|
if ( $hashable->getHash() === $referenceHash ) { |
|
215
|
10 |
|
return $hashable; |
|
216
|
10 |
|
} |
|
217
|
|
|
} |
|
218
|
9 |
|
|
|
219
|
|
|
return null; |
|
220
|
9 |
|
} |
|
221
|
|
|
|
|
222
|
|
|
/** |
|
223
|
|
|
* @see Serializable::serialize |
|
224
|
|
|
* |
|
225
|
|
|
* @since 2.1 |
|
226
|
|
|
* |
|
227
|
|
|
* @return string |
|
228
|
|
|
*/ |
|
229
|
|
|
public function serialize() { |
|
230
|
3 |
|
return serialize( iterator_to_array( $this ) ); |
|
231
|
3 |
|
} |
|
232
|
|
|
|
|
233
|
|
|
/** |
|
234
|
|
|
* @see Serializable::unserialize |
|
235
|
|
|
* |
|
236
|
|
|
* @since 2.1 |
|
237
|
|
|
* |
|
238
|
|
|
* @param string $data |
|
239
|
|
|
*/ |
|
240
|
|
|
public function unserialize( $data ) { |
|
241
|
3 |
|
$this->__construct( unserialize( $data ) ); |
|
242
|
3 |
|
} |
|
243
|
3 |
|
|
|
244
|
|
|
/** |
|
245
|
|
|
* @since 4.4 |
|
246
|
|
|
* |
|
247
|
|
|
* @return bool |
|
248
|
|
|
*/ |
|
249
|
|
|
public function isEmpty() { |
|
250
|
3 |
|
return $this->count() === 0; |
|
251
|
3 |
|
} |
|
252
|
|
|
|
|
253
|
|
|
} |
|
254
|
|
|
|
This class, trait or interface has been deprecated. The supplier of the file has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the type will be removed from the class and what other constant to use instead.