Chris@0
|
1 <?php
|
Chris@0
|
2 /*
|
Chris@0
|
3 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
Chris@0
|
4 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
Chris@0
|
5 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
Chris@0
|
6 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
Chris@0
|
7 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
Chris@0
|
8 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
Chris@0
|
9 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
Chris@0
|
10 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
Chris@0
|
11 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
Chris@0
|
12 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
Chris@0
|
13 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
Chris@0
|
14 *
|
Chris@0
|
15 * This software consists of voluntary contributions made by many individuals
|
Chris@0
|
16 * and is licensed under the MIT license. For more information, see
|
Chris@0
|
17 * <http://www.doctrine-project.org>.
|
Chris@0
|
18 */
|
Chris@0
|
19
|
Chris@0
|
20 namespace Doctrine\Common\Collections;
|
Chris@0
|
21
|
Chris@0
|
22 use ArrayIterator;
|
Chris@0
|
23 use Closure;
|
Chris@0
|
24 use Doctrine\Common\Collections\Expr\ClosureExpressionVisitor;
|
Chris@0
|
25
|
Chris@0
|
26 /**
|
Chris@0
|
27 * An ArrayCollection is a Collection implementation that wraps a regular PHP array.
|
Chris@0
|
28 *
|
Chris@0
|
29 * @since 2.0
|
Chris@0
|
30 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
Chris@0
|
31 * @author Jonathan Wage <jonwage@gmail.com>
|
Chris@0
|
32 * @author Roman Borschel <roman@code-factory.org>
|
Chris@0
|
33 */
|
Chris@0
|
34 class ArrayCollection implements Collection, Selectable
|
Chris@0
|
35 {
|
Chris@0
|
36 /**
|
Chris@0
|
37 * An array containing the entries of this collection.
|
Chris@0
|
38 *
|
Chris@0
|
39 * @var array
|
Chris@0
|
40 */
|
Chris@0
|
41 private $elements;
|
Chris@0
|
42
|
Chris@0
|
43 /**
|
Chris@0
|
44 * Initializes a new ArrayCollection.
|
Chris@0
|
45 *
|
Chris@0
|
46 * @param array $elements
|
Chris@0
|
47 */
|
Chris@0
|
48 public function __construct(array $elements = array())
|
Chris@0
|
49 {
|
Chris@0
|
50 $this->elements = $elements;
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 /**
|
Chris@0
|
54 * {@inheritDoc}
|
Chris@0
|
55 */
|
Chris@0
|
56 public function toArray()
|
Chris@0
|
57 {
|
Chris@0
|
58 return $this->elements;
|
Chris@0
|
59 }
|
Chris@0
|
60
|
Chris@0
|
61 /**
|
Chris@0
|
62 * {@inheritDoc}
|
Chris@0
|
63 */
|
Chris@0
|
64 public function first()
|
Chris@0
|
65 {
|
Chris@0
|
66 return reset($this->elements);
|
Chris@0
|
67 }
|
Chris@0
|
68
|
Chris@0
|
69 /**
|
Chris@0
|
70 * {@inheritDoc}
|
Chris@0
|
71 */
|
Chris@0
|
72 public function last()
|
Chris@0
|
73 {
|
Chris@0
|
74 return end($this->elements);
|
Chris@0
|
75 }
|
Chris@0
|
76
|
Chris@0
|
77 /**
|
Chris@0
|
78 * {@inheritDoc}
|
Chris@0
|
79 */
|
Chris@0
|
80 public function key()
|
Chris@0
|
81 {
|
Chris@0
|
82 return key($this->elements);
|
Chris@0
|
83 }
|
Chris@0
|
84
|
Chris@0
|
85 /**
|
Chris@0
|
86 * {@inheritDoc}
|
Chris@0
|
87 */
|
Chris@0
|
88 public function next()
|
Chris@0
|
89 {
|
Chris@0
|
90 return next($this->elements);
|
Chris@0
|
91 }
|
Chris@0
|
92
|
Chris@0
|
93 /**
|
Chris@0
|
94 * {@inheritDoc}
|
Chris@0
|
95 */
|
Chris@0
|
96 public function current()
|
Chris@0
|
97 {
|
Chris@0
|
98 return current($this->elements);
|
Chris@0
|
99 }
|
Chris@0
|
100
|
Chris@0
|
101 /**
|
Chris@0
|
102 * {@inheritDoc}
|
Chris@0
|
103 */
|
Chris@0
|
104 public function remove($key)
|
Chris@0
|
105 {
|
Chris@0
|
106 if ( ! isset($this->elements[$key]) && ! array_key_exists($key, $this->elements)) {
|
Chris@0
|
107 return null;
|
Chris@0
|
108 }
|
Chris@0
|
109
|
Chris@0
|
110 $removed = $this->elements[$key];
|
Chris@0
|
111 unset($this->elements[$key]);
|
Chris@0
|
112
|
Chris@0
|
113 return $removed;
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@0
|
116 /**
|
Chris@0
|
117 * {@inheritDoc}
|
Chris@0
|
118 */
|
Chris@0
|
119 public function removeElement($element)
|
Chris@0
|
120 {
|
Chris@0
|
121 $key = array_search($element, $this->elements, true);
|
Chris@0
|
122
|
Chris@0
|
123 if ($key === false) {
|
Chris@0
|
124 return false;
|
Chris@0
|
125 }
|
Chris@0
|
126
|
Chris@0
|
127 unset($this->elements[$key]);
|
Chris@0
|
128
|
Chris@0
|
129 return true;
|
Chris@0
|
130 }
|
Chris@0
|
131
|
Chris@0
|
132 /**
|
Chris@0
|
133 * Required by interface ArrayAccess.
|
Chris@0
|
134 *
|
Chris@0
|
135 * {@inheritDoc}
|
Chris@0
|
136 */
|
Chris@0
|
137 public function offsetExists($offset)
|
Chris@0
|
138 {
|
Chris@0
|
139 return $this->containsKey($offset);
|
Chris@0
|
140 }
|
Chris@0
|
141
|
Chris@0
|
142 /**
|
Chris@0
|
143 * Required by interface ArrayAccess.
|
Chris@0
|
144 *
|
Chris@0
|
145 * {@inheritDoc}
|
Chris@0
|
146 */
|
Chris@0
|
147 public function offsetGet($offset)
|
Chris@0
|
148 {
|
Chris@0
|
149 return $this->get($offset);
|
Chris@0
|
150 }
|
Chris@0
|
151
|
Chris@0
|
152 /**
|
Chris@0
|
153 * Required by interface ArrayAccess.
|
Chris@0
|
154 *
|
Chris@0
|
155 * {@inheritDoc}
|
Chris@0
|
156 */
|
Chris@0
|
157 public function offsetSet($offset, $value)
|
Chris@0
|
158 {
|
Chris@0
|
159 if ( ! isset($offset)) {
|
Chris@0
|
160 return $this->add($value);
|
Chris@0
|
161 }
|
Chris@0
|
162
|
Chris@0
|
163 $this->set($offset, $value);
|
Chris@0
|
164 }
|
Chris@0
|
165
|
Chris@0
|
166 /**
|
Chris@0
|
167 * Required by interface ArrayAccess.
|
Chris@0
|
168 *
|
Chris@0
|
169 * {@inheritDoc}
|
Chris@0
|
170 */
|
Chris@0
|
171 public function offsetUnset($offset)
|
Chris@0
|
172 {
|
Chris@0
|
173 return $this->remove($offset);
|
Chris@0
|
174 }
|
Chris@0
|
175
|
Chris@0
|
176 /**
|
Chris@0
|
177 * {@inheritDoc}
|
Chris@0
|
178 */
|
Chris@0
|
179 public function containsKey($key)
|
Chris@0
|
180 {
|
Chris@0
|
181 return isset($this->elements[$key]) || array_key_exists($key, $this->elements);
|
Chris@0
|
182 }
|
Chris@0
|
183
|
Chris@0
|
184 /**
|
Chris@0
|
185 * {@inheritDoc}
|
Chris@0
|
186 */
|
Chris@0
|
187 public function contains($element)
|
Chris@0
|
188 {
|
Chris@0
|
189 return in_array($element, $this->elements, true);
|
Chris@0
|
190 }
|
Chris@0
|
191
|
Chris@0
|
192 /**
|
Chris@0
|
193 * {@inheritDoc}
|
Chris@0
|
194 */
|
Chris@0
|
195 public function exists(Closure $p)
|
Chris@0
|
196 {
|
Chris@0
|
197 foreach ($this->elements as $key => $element) {
|
Chris@0
|
198 if ($p($key, $element)) {
|
Chris@0
|
199 return true;
|
Chris@0
|
200 }
|
Chris@0
|
201 }
|
Chris@0
|
202
|
Chris@0
|
203 return false;
|
Chris@0
|
204 }
|
Chris@0
|
205
|
Chris@0
|
206 /**
|
Chris@0
|
207 * {@inheritDoc}
|
Chris@0
|
208 */
|
Chris@0
|
209 public function indexOf($element)
|
Chris@0
|
210 {
|
Chris@0
|
211 return array_search($element, $this->elements, true);
|
Chris@0
|
212 }
|
Chris@0
|
213
|
Chris@0
|
214 /**
|
Chris@0
|
215 * {@inheritDoc}
|
Chris@0
|
216 */
|
Chris@0
|
217 public function get($key)
|
Chris@0
|
218 {
|
Chris@0
|
219 return isset($this->elements[$key]) ? $this->elements[$key] : null;
|
Chris@0
|
220 }
|
Chris@0
|
221
|
Chris@0
|
222 /**
|
Chris@0
|
223 * {@inheritDoc}
|
Chris@0
|
224 */
|
Chris@0
|
225 public function getKeys()
|
Chris@0
|
226 {
|
Chris@0
|
227 return array_keys($this->elements);
|
Chris@0
|
228 }
|
Chris@0
|
229
|
Chris@0
|
230 /**
|
Chris@0
|
231 * {@inheritDoc}
|
Chris@0
|
232 */
|
Chris@0
|
233 public function getValues()
|
Chris@0
|
234 {
|
Chris@0
|
235 return array_values($this->elements);
|
Chris@0
|
236 }
|
Chris@0
|
237
|
Chris@0
|
238 /**
|
Chris@0
|
239 * {@inheritDoc}
|
Chris@0
|
240 */
|
Chris@0
|
241 public function count()
|
Chris@0
|
242 {
|
Chris@0
|
243 return count($this->elements);
|
Chris@0
|
244 }
|
Chris@0
|
245
|
Chris@0
|
246 /**
|
Chris@0
|
247 * {@inheritDoc}
|
Chris@0
|
248 */
|
Chris@0
|
249 public function set($key, $value)
|
Chris@0
|
250 {
|
Chris@0
|
251 $this->elements[$key] = $value;
|
Chris@0
|
252 }
|
Chris@0
|
253
|
Chris@0
|
254 /**
|
Chris@0
|
255 * {@inheritDoc}
|
Chris@0
|
256 */
|
Chris@0
|
257 public function add($value)
|
Chris@0
|
258 {
|
Chris@0
|
259 $this->elements[] = $value;
|
Chris@0
|
260
|
Chris@0
|
261 return true;
|
Chris@0
|
262 }
|
Chris@0
|
263
|
Chris@0
|
264 /**
|
Chris@0
|
265 * {@inheritDoc}
|
Chris@0
|
266 */
|
Chris@0
|
267 public function isEmpty()
|
Chris@0
|
268 {
|
Chris@0
|
269 return empty($this->elements);
|
Chris@0
|
270 }
|
Chris@0
|
271
|
Chris@0
|
272 /**
|
Chris@0
|
273 * Required by interface IteratorAggregate.
|
Chris@0
|
274 *
|
Chris@0
|
275 * {@inheritDoc}
|
Chris@0
|
276 */
|
Chris@0
|
277 public function getIterator()
|
Chris@0
|
278 {
|
Chris@0
|
279 return new ArrayIterator($this->elements);
|
Chris@0
|
280 }
|
Chris@0
|
281
|
Chris@0
|
282 /**
|
Chris@0
|
283 * {@inheritDoc}
|
Chris@0
|
284 */
|
Chris@0
|
285 public function map(Closure $func)
|
Chris@0
|
286 {
|
Chris@0
|
287 return new static(array_map($func, $this->elements));
|
Chris@0
|
288 }
|
Chris@0
|
289
|
Chris@0
|
290 /**
|
Chris@0
|
291 * {@inheritDoc}
|
Chris@0
|
292 */
|
Chris@0
|
293 public function filter(Closure $p)
|
Chris@0
|
294 {
|
Chris@0
|
295 return new static(array_filter($this->elements, $p));
|
Chris@0
|
296 }
|
Chris@0
|
297
|
Chris@0
|
298 /**
|
Chris@0
|
299 * {@inheritDoc}
|
Chris@0
|
300 */
|
Chris@0
|
301 public function forAll(Closure $p)
|
Chris@0
|
302 {
|
Chris@0
|
303 foreach ($this->elements as $key => $element) {
|
Chris@0
|
304 if ( ! $p($key, $element)) {
|
Chris@0
|
305 return false;
|
Chris@0
|
306 }
|
Chris@0
|
307 }
|
Chris@0
|
308
|
Chris@0
|
309 return true;
|
Chris@0
|
310 }
|
Chris@0
|
311
|
Chris@0
|
312 /**
|
Chris@0
|
313 * {@inheritDoc}
|
Chris@0
|
314 */
|
Chris@0
|
315 public function partition(Closure $p)
|
Chris@0
|
316 {
|
Chris@0
|
317 $matches = $noMatches = array();
|
Chris@0
|
318
|
Chris@0
|
319 foreach ($this->elements as $key => $element) {
|
Chris@0
|
320 if ($p($key, $element)) {
|
Chris@0
|
321 $matches[$key] = $element;
|
Chris@0
|
322 } else {
|
Chris@0
|
323 $noMatches[$key] = $element;
|
Chris@0
|
324 }
|
Chris@0
|
325 }
|
Chris@0
|
326
|
Chris@0
|
327 return array(new static($matches), new static($noMatches));
|
Chris@0
|
328 }
|
Chris@0
|
329
|
Chris@0
|
330 /**
|
Chris@0
|
331 * Returns a string representation of this object.
|
Chris@0
|
332 *
|
Chris@0
|
333 * @return string
|
Chris@0
|
334 */
|
Chris@0
|
335 public function __toString()
|
Chris@0
|
336 {
|
Chris@0
|
337 return __CLASS__ . '@' . spl_object_hash($this);
|
Chris@0
|
338 }
|
Chris@0
|
339
|
Chris@0
|
340 /**
|
Chris@0
|
341 * {@inheritDoc}
|
Chris@0
|
342 */
|
Chris@0
|
343 public function clear()
|
Chris@0
|
344 {
|
Chris@0
|
345 $this->elements = array();
|
Chris@0
|
346 }
|
Chris@0
|
347
|
Chris@0
|
348 /**
|
Chris@0
|
349 * {@inheritDoc}
|
Chris@0
|
350 */
|
Chris@0
|
351 public function slice($offset, $length = null)
|
Chris@0
|
352 {
|
Chris@0
|
353 return array_slice($this->elements, $offset, $length, true);
|
Chris@0
|
354 }
|
Chris@0
|
355
|
Chris@0
|
356 /**
|
Chris@0
|
357 * {@inheritDoc}
|
Chris@0
|
358 */
|
Chris@0
|
359 public function matching(Criteria $criteria)
|
Chris@0
|
360 {
|
Chris@0
|
361 $expr = $criteria->getWhereExpression();
|
Chris@0
|
362 $filtered = $this->elements;
|
Chris@0
|
363
|
Chris@0
|
364 if ($expr) {
|
Chris@0
|
365 $visitor = new ClosureExpressionVisitor();
|
Chris@0
|
366 $filter = $visitor->dispatch($expr);
|
Chris@0
|
367 $filtered = array_filter($filtered, $filter);
|
Chris@0
|
368 }
|
Chris@0
|
369
|
Chris@0
|
370 if ($orderings = $criteria->getOrderings()) {
|
Chris@0
|
371 foreach (array_reverse($orderings) as $field => $ordering) {
|
Chris@0
|
372 $next = ClosureExpressionVisitor::sortByField($field, $ordering == Criteria::DESC ? -1 : 1);
|
Chris@0
|
373 }
|
Chris@0
|
374
|
Chris@0
|
375 uasort($filtered, $next);
|
Chris@0
|
376 }
|
Chris@0
|
377
|
Chris@0
|
378 $offset = $criteria->getFirstResult();
|
Chris@0
|
379 $length = $criteria->getMaxResults();
|
Chris@0
|
380
|
Chris@0
|
381 if ($offset || $length) {
|
Chris@0
|
382 $filtered = array_slice($filtered, (int)$offset, $length);
|
Chris@0
|
383 }
|
Chris@0
|
384
|
Chris@0
|
385 return new static($filtered);
|
Chris@0
|
386 }
|
Chris@0
|
387 }
|