Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@0
|
3 * Zend Framework (http://framework.zend.com/)
|
Chris@0
|
4 *
|
Chris@0
|
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
|
Chris@0
|
6 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
Chris@0
|
7 * @license http://framework.zend.com/license/new-bsd New BSD License
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 namespace Zend\Stdlib;
|
Chris@0
|
11
|
Chris@0
|
12 use ArrayAccess;
|
Chris@0
|
13 use Countable;
|
Chris@0
|
14 use IteratorAggregate;
|
Chris@0
|
15 use Serializable;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Custom framework ArrayObject implementation
|
Chris@0
|
19 *
|
Chris@0
|
20 * Extends version-specific "abstract" implementation.
|
Chris@0
|
21 */
|
Chris@0
|
22 class ArrayObject implements IteratorAggregate, ArrayAccess, Serializable, Countable
|
Chris@0
|
23 {
|
Chris@0
|
24 /**
|
Chris@0
|
25 * Properties of the object have their normal functionality
|
Chris@0
|
26 * when accessed as list (var_dump, foreach, etc.).
|
Chris@0
|
27 */
|
Chris@0
|
28 const STD_PROP_LIST = 1;
|
Chris@0
|
29
|
Chris@0
|
30 /**
|
Chris@0
|
31 * Entries can be accessed as properties (read and write).
|
Chris@0
|
32 */
|
Chris@0
|
33 const ARRAY_AS_PROPS = 2;
|
Chris@0
|
34
|
Chris@0
|
35 /**
|
Chris@0
|
36 * @var array
|
Chris@0
|
37 */
|
Chris@0
|
38 protected $storage;
|
Chris@0
|
39
|
Chris@0
|
40 /**
|
Chris@0
|
41 * @var int
|
Chris@0
|
42 */
|
Chris@0
|
43 protected $flag;
|
Chris@0
|
44
|
Chris@0
|
45 /**
|
Chris@0
|
46 * @var string
|
Chris@0
|
47 */
|
Chris@0
|
48 protected $iteratorClass;
|
Chris@0
|
49
|
Chris@0
|
50 /**
|
Chris@0
|
51 * @var array
|
Chris@0
|
52 */
|
Chris@0
|
53 protected $protectedProperties;
|
Chris@0
|
54
|
Chris@0
|
55 /**
|
Chris@0
|
56 * Constructor
|
Chris@0
|
57 *
|
Chris@0
|
58 * @param array $input
|
Chris@0
|
59 * @param int $flags
|
Chris@0
|
60 * @param string $iteratorClass
|
Chris@0
|
61 */
|
Chris@0
|
62 public function __construct($input = [], $flags = self::STD_PROP_LIST, $iteratorClass = 'ArrayIterator')
|
Chris@0
|
63 {
|
Chris@0
|
64 $this->setFlags($flags);
|
Chris@0
|
65 $this->storage = $input;
|
Chris@0
|
66 $this->setIteratorClass($iteratorClass);
|
Chris@0
|
67 $this->protectedProperties = array_keys(get_object_vars($this));
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 /**
|
Chris@0
|
71 * Returns whether the requested key exists
|
Chris@0
|
72 *
|
Chris@0
|
73 * @param mixed $key
|
Chris@0
|
74 * @return bool
|
Chris@0
|
75 */
|
Chris@0
|
76 public function __isset($key)
|
Chris@0
|
77 {
|
Chris@0
|
78 if ($this->flag == self::ARRAY_AS_PROPS) {
|
Chris@0
|
79 return $this->offsetExists($key);
|
Chris@0
|
80 }
|
Chris@0
|
81 if (in_array($key, $this->protectedProperties)) {
|
Chris@0
|
82 throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
|
Chris@0
|
83 }
|
Chris@0
|
84
|
Chris@0
|
85 return isset($this->$key);
|
Chris@0
|
86 }
|
Chris@0
|
87
|
Chris@0
|
88 /**
|
Chris@0
|
89 * Sets the value at the specified key to value
|
Chris@0
|
90 *
|
Chris@0
|
91 * @param mixed $key
|
Chris@0
|
92 * @param mixed $value
|
Chris@0
|
93 * @return void
|
Chris@0
|
94 */
|
Chris@0
|
95 public function __set($key, $value)
|
Chris@0
|
96 {
|
Chris@0
|
97 if ($this->flag == self::ARRAY_AS_PROPS) {
|
Chris@0
|
98 return $this->offsetSet($key, $value);
|
Chris@0
|
99 }
|
Chris@0
|
100 if (in_array($key, $this->protectedProperties)) {
|
Chris@0
|
101 throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
|
Chris@0
|
102 }
|
Chris@0
|
103 $this->$key = $value;
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 /**
|
Chris@0
|
107 * Unsets the value at the specified key
|
Chris@0
|
108 *
|
Chris@0
|
109 * @param mixed $key
|
Chris@0
|
110 * @return void
|
Chris@0
|
111 */
|
Chris@0
|
112 public function __unset($key)
|
Chris@0
|
113 {
|
Chris@0
|
114 if ($this->flag == self::ARRAY_AS_PROPS) {
|
Chris@0
|
115 return $this->offsetUnset($key);
|
Chris@0
|
116 }
|
Chris@0
|
117 if (in_array($key, $this->protectedProperties)) {
|
Chris@0
|
118 throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
|
Chris@0
|
119 }
|
Chris@0
|
120 unset($this->$key);
|
Chris@0
|
121 }
|
Chris@0
|
122
|
Chris@0
|
123 /**
|
Chris@0
|
124 * Returns the value at the specified key by reference
|
Chris@0
|
125 *
|
Chris@0
|
126 * @param mixed $key
|
Chris@0
|
127 * @return mixed
|
Chris@0
|
128 */
|
Chris@0
|
129 public function &__get($key)
|
Chris@0
|
130 {
|
Chris@0
|
131 $ret = null;
|
Chris@0
|
132 if ($this->flag == self::ARRAY_AS_PROPS) {
|
Chris@0
|
133 $ret =& $this->offsetGet($key);
|
Chris@0
|
134
|
Chris@0
|
135 return $ret;
|
Chris@0
|
136 }
|
Chris@0
|
137 if (in_array($key, $this->protectedProperties)) {
|
Chris@0
|
138 throw new Exception\InvalidArgumentException('$key is a protected property, use a different key');
|
Chris@0
|
139 }
|
Chris@0
|
140
|
Chris@0
|
141 return $this->$key;
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 /**
|
Chris@0
|
145 * Appends the value
|
Chris@0
|
146 *
|
Chris@0
|
147 * @param mixed $value
|
Chris@0
|
148 * @return void
|
Chris@0
|
149 */
|
Chris@0
|
150 public function append($value)
|
Chris@0
|
151 {
|
Chris@0
|
152 $this->storage[] = $value;
|
Chris@0
|
153 }
|
Chris@0
|
154
|
Chris@0
|
155 /**
|
Chris@0
|
156 * Sort the entries by value
|
Chris@0
|
157 *
|
Chris@0
|
158 * @return void
|
Chris@0
|
159 */
|
Chris@0
|
160 public function asort()
|
Chris@0
|
161 {
|
Chris@0
|
162 asort($this->storage);
|
Chris@0
|
163 }
|
Chris@0
|
164
|
Chris@0
|
165 /**
|
Chris@0
|
166 * Get the number of public properties in the ArrayObject
|
Chris@0
|
167 *
|
Chris@0
|
168 * @return int
|
Chris@0
|
169 */
|
Chris@0
|
170 public function count()
|
Chris@0
|
171 {
|
Chris@0
|
172 return count($this->storage);
|
Chris@0
|
173 }
|
Chris@0
|
174
|
Chris@0
|
175 /**
|
Chris@0
|
176 * Exchange the array for another one.
|
Chris@0
|
177 *
|
Chris@0
|
178 * @param array|ArrayObject $data
|
Chris@0
|
179 * @return array
|
Chris@0
|
180 */
|
Chris@0
|
181 public function exchangeArray($data)
|
Chris@0
|
182 {
|
Chris@0
|
183 if (!is_array($data) && !is_object($data)) {
|
Chris@0
|
184 throw new Exception\InvalidArgumentException('Passed variable is not an array or object, using empty array instead');
|
Chris@0
|
185 }
|
Chris@0
|
186
|
Chris@0
|
187 if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) {
|
Chris@0
|
188 $data = $data->getArrayCopy();
|
Chris@0
|
189 }
|
Chris@0
|
190 if (!is_array($data)) {
|
Chris@0
|
191 $data = (array) $data;
|
Chris@0
|
192 }
|
Chris@0
|
193
|
Chris@0
|
194 $storage = $this->storage;
|
Chris@0
|
195
|
Chris@0
|
196 $this->storage = $data;
|
Chris@0
|
197
|
Chris@0
|
198 return $storage;
|
Chris@0
|
199 }
|
Chris@0
|
200
|
Chris@0
|
201 /**
|
Chris@0
|
202 * Creates a copy of the ArrayObject.
|
Chris@0
|
203 *
|
Chris@0
|
204 * @return array
|
Chris@0
|
205 */
|
Chris@0
|
206 public function getArrayCopy()
|
Chris@0
|
207 {
|
Chris@0
|
208 return $this->storage;
|
Chris@0
|
209 }
|
Chris@0
|
210
|
Chris@0
|
211 /**
|
Chris@0
|
212 * Gets the behavior flags.
|
Chris@0
|
213 *
|
Chris@0
|
214 * @return int
|
Chris@0
|
215 */
|
Chris@0
|
216 public function getFlags()
|
Chris@0
|
217 {
|
Chris@0
|
218 return $this->flag;
|
Chris@0
|
219 }
|
Chris@0
|
220
|
Chris@0
|
221 /**
|
Chris@0
|
222 * Create a new iterator from an ArrayObject instance
|
Chris@0
|
223 *
|
Chris@0
|
224 * @return \Iterator
|
Chris@0
|
225 */
|
Chris@0
|
226 public function getIterator()
|
Chris@0
|
227 {
|
Chris@0
|
228 $class = $this->iteratorClass;
|
Chris@0
|
229
|
Chris@0
|
230 return new $class($this->storage);
|
Chris@0
|
231 }
|
Chris@0
|
232
|
Chris@0
|
233 /**
|
Chris@0
|
234 * Gets the iterator classname for the ArrayObject.
|
Chris@0
|
235 *
|
Chris@0
|
236 * @return string
|
Chris@0
|
237 */
|
Chris@0
|
238 public function getIteratorClass()
|
Chris@0
|
239 {
|
Chris@0
|
240 return $this->iteratorClass;
|
Chris@0
|
241 }
|
Chris@0
|
242
|
Chris@0
|
243 /**
|
Chris@0
|
244 * Sort the entries by key
|
Chris@0
|
245 *
|
Chris@0
|
246 * @return void
|
Chris@0
|
247 */
|
Chris@0
|
248 public function ksort()
|
Chris@0
|
249 {
|
Chris@0
|
250 ksort($this->storage);
|
Chris@0
|
251 }
|
Chris@0
|
252
|
Chris@0
|
253 /**
|
Chris@0
|
254 * Sort an array using a case insensitive "natural order" algorithm
|
Chris@0
|
255 *
|
Chris@0
|
256 * @return void
|
Chris@0
|
257 */
|
Chris@0
|
258 public function natcasesort()
|
Chris@0
|
259 {
|
Chris@0
|
260 natcasesort($this->storage);
|
Chris@0
|
261 }
|
Chris@0
|
262
|
Chris@0
|
263 /**
|
Chris@0
|
264 * Sort entries using a "natural order" algorithm
|
Chris@0
|
265 *
|
Chris@0
|
266 * @return void
|
Chris@0
|
267 */
|
Chris@0
|
268 public function natsort()
|
Chris@0
|
269 {
|
Chris@0
|
270 natsort($this->storage);
|
Chris@0
|
271 }
|
Chris@0
|
272
|
Chris@0
|
273 /**
|
Chris@0
|
274 * Returns whether the requested key exists
|
Chris@0
|
275 *
|
Chris@0
|
276 * @param mixed $key
|
Chris@0
|
277 * @return bool
|
Chris@0
|
278 */
|
Chris@0
|
279 public function offsetExists($key)
|
Chris@0
|
280 {
|
Chris@0
|
281 return isset($this->storage[$key]);
|
Chris@0
|
282 }
|
Chris@0
|
283
|
Chris@0
|
284 /**
|
Chris@0
|
285 * Returns the value at the specified key
|
Chris@0
|
286 *
|
Chris@0
|
287 * @param mixed $key
|
Chris@0
|
288 * @return mixed
|
Chris@0
|
289 */
|
Chris@0
|
290 public function &offsetGet($key)
|
Chris@0
|
291 {
|
Chris@0
|
292 $ret = null;
|
Chris@0
|
293 if (!$this->offsetExists($key)) {
|
Chris@0
|
294 return $ret;
|
Chris@0
|
295 }
|
Chris@0
|
296 $ret =& $this->storage[$key];
|
Chris@0
|
297
|
Chris@0
|
298 return $ret;
|
Chris@0
|
299 }
|
Chris@0
|
300
|
Chris@0
|
301 /**
|
Chris@0
|
302 * Sets the value at the specified key to value
|
Chris@0
|
303 *
|
Chris@0
|
304 * @param mixed $key
|
Chris@0
|
305 * @param mixed $value
|
Chris@0
|
306 * @return void
|
Chris@0
|
307 */
|
Chris@0
|
308 public function offsetSet($key, $value)
|
Chris@0
|
309 {
|
Chris@0
|
310 $this->storage[$key] = $value;
|
Chris@0
|
311 }
|
Chris@0
|
312
|
Chris@0
|
313 /**
|
Chris@0
|
314 * Unsets the value at the specified key
|
Chris@0
|
315 *
|
Chris@0
|
316 * @param mixed $key
|
Chris@0
|
317 * @return void
|
Chris@0
|
318 */
|
Chris@0
|
319 public function offsetUnset($key)
|
Chris@0
|
320 {
|
Chris@0
|
321 if ($this->offsetExists($key)) {
|
Chris@0
|
322 unset($this->storage[$key]);
|
Chris@0
|
323 }
|
Chris@0
|
324 }
|
Chris@0
|
325
|
Chris@0
|
326 /**
|
Chris@0
|
327 * Serialize an ArrayObject
|
Chris@0
|
328 *
|
Chris@0
|
329 * @return string
|
Chris@0
|
330 */
|
Chris@0
|
331 public function serialize()
|
Chris@0
|
332 {
|
Chris@0
|
333 return serialize(get_object_vars($this));
|
Chris@0
|
334 }
|
Chris@0
|
335
|
Chris@0
|
336 /**
|
Chris@0
|
337 * Sets the behavior flags
|
Chris@0
|
338 *
|
Chris@0
|
339 * @param int $flags
|
Chris@0
|
340 * @return void
|
Chris@0
|
341 */
|
Chris@0
|
342 public function setFlags($flags)
|
Chris@0
|
343 {
|
Chris@0
|
344 $this->flag = $flags;
|
Chris@0
|
345 }
|
Chris@0
|
346
|
Chris@0
|
347 /**
|
Chris@0
|
348 * Sets the iterator classname for the ArrayObject
|
Chris@0
|
349 *
|
Chris@0
|
350 * @param string $class
|
Chris@0
|
351 * @return void
|
Chris@0
|
352 */
|
Chris@0
|
353 public function setIteratorClass($class)
|
Chris@0
|
354 {
|
Chris@0
|
355 if (class_exists($class)) {
|
Chris@0
|
356 $this->iteratorClass = $class;
|
Chris@0
|
357
|
Chris@0
|
358 return ;
|
Chris@0
|
359 }
|
Chris@0
|
360
|
Chris@0
|
361 if (strpos($class, '\\') === 0) {
|
Chris@0
|
362 $class = '\\' . $class;
|
Chris@0
|
363 if (class_exists($class)) {
|
Chris@0
|
364 $this->iteratorClass = $class;
|
Chris@0
|
365
|
Chris@0
|
366 return ;
|
Chris@0
|
367 }
|
Chris@0
|
368 }
|
Chris@0
|
369
|
Chris@0
|
370 throw new Exception\InvalidArgumentException('The iterator class does not exist');
|
Chris@0
|
371 }
|
Chris@0
|
372
|
Chris@0
|
373 /**
|
Chris@0
|
374 * Sort the entries with a user-defined comparison function and maintain key association
|
Chris@0
|
375 *
|
Chris@0
|
376 * @param callable $function
|
Chris@0
|
377 * @return void
|
Chris@0
|
378 */
|
Chris@0
|
379 public function uasort($function)
|
Chris@0
|
380 {
|
Chris@0
|
381 if (is_callable($function)) {
|
Chris@0
|
382 uasort($this->storage, $function);
|
Chris@0
|
383 }
|
Chris@0
|
384 }
|
Chris@0
|
385
|
Chris@0
|
386 /**
|
Chris@0
|
387 * Sort the entries by keys using a user-defined comparison function
|
Chris@0
|
388 *
|
Chris@0
|
389 * @param callable $function
|
Chris@0
|
390 * @return void
|
Chris@0
|
391 */
|
Chris@0
|
392 public function uksort($function)
|
Chris@0
|
393 {
|
Chris@0
|
394 if (is_callable($function)) {
|
Chris@0
|
395 uksort($this->storage, $function);
|
Chris@0
|
396 }
|
Chris@0
|
397 }
|
Chris@0
|
398
|
Chris@0
|
399 /**
|
Chris@0
|
400 * Unserialize an ArrayObject
|
Chris@0
|
401 *
|
Chris@0
|
402 * @param string $data
|
Chris@0
|
403 * @return void
|
Chris@0
|
404 */
|
Chris@0
|
405 public function unserialize($data)
|
Chris@0
|
406 {
|
Chris@0
|
407 $ar = unserialize($data);
|
Chris@0
|
408 $this->protectedProperties = array_keys(get_object_vars($this));
|
Chris@0
|
409
|
Chris@0
|
410 $this->setFlags($ar['flag']);
|
Chris@0
|
411 $this->exchangeArray($ar['storage']);
|
Chris@0
|
412 $this->setIteratorClass($ar['iteratorClass']);
|
Chris@0
|
413
|
Chris@0
|
414 foreach ($ar as $k => $v) {
|
Chris@0
|
415 switch ($k) {
|
Chris@0
|
416 case 'flag':
|
Chris@0
|
417 $this->setFlags($v);
|
Chris@0
|
418 break;
|
Chris@0
|
419 case 'storage':
|
Chris@0
|
420 $this->exchangeArray($v);
|
Chris@0
|
421 break;
|
Chris@0
|
422 case 'iteratorClass':
|
Chris@0
|
423 $this->setIteratorClass($v);
|
Chris@0
|
424 break;
|
Chris@0
|
425 case 'protectedProperties':
|
Chris@0
|
426 continue;
|
Chris@0
|
427 default:
|
Chris@0
|
428 $this->__set($k, $v);
|
Chris@0
|
429 }
|
Chris@0
|
430 }
|
Chris@0
|
431 }
|
Chris@0
|
432 }
|