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@12
|
183 if (! is_array($data) && ! is_object($data)) {
|
Chris@12
|
184 throw new Exception\InvalidArgumentException(
|
Chris@12
|
185 'Passed variable is not an array or object, using empty array instead'
|
Chris@12
|
186 );
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 if (is_object($data) && ($data instanceof self || $data instanceof \ArrayObject)) {
|
Chris@0
|
190 $data = $data->getArrayCopy();
|
Chris@0
|
191 }
|
Chris@12
|
192 if (! is_array($data)) {
|
Chris@0
|
193 $data = (array) $data;
|
Chris@0
|
194 }
|
Chris@0
|
195
|
Chris@0
|
196 $storage = $this->storage;
|
Chris@0
|
197
|
Chris@0
|
198 $this->storage = $data;
|
Chris@0
|
199
|
Chris@0
|
200 return $storage;
|
Chris@0
|
201 }
|
Chris@0
|
202
|
Chris@0
|
203 /**
|
Chris@0
|
204 * Creates a copy of the ArrayObject.
|
Chris@0
|
205 *
|
Chris@0
|
206 * @return array
|
Chris@0
|
207 */
|
Chris@0
|
208 public function getArrayCopy()
|
Chris@0
|
209 {
|
Chris@0
|
210 return $this->storage;
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 /**
|
Chris@0
|
214 * Gets the behavior flags.
|
Chris@0
|
215 *
|
Chris@0
|
216 * @return int
|
Chris@0
|
217 */
|
Chris@0
|
218 public function getFlags()
|
Chris@0
|
219 {
|
Chris@0
|
220 return $this->flag;
|
Chris@0
|
221 }
|
Chris@0
|
222
|
Chris@0
|
223 /**
|
Chris@0
|
224 * Create a new iterator from an ArrayObject instance
|
Chris@0
|
225 *
|
Chris@0
|
226 * @return \Iterator
|
Chris@0
|
227 */
|
Chris@0
|
228 public function getIterator()
|
Chris@0
|
229 {
|
Chris@0
|
230 $class = $this->iteratorClass;
|
Chris@0
|
231
|
Chris@0
|
232 return new $class($this->storage);
|
Chris@0
|
233 }
|
Chris@0
|
234
|
Chris@0
|
235 /**
|
Chris@0
|
236 * Gets the iterator classname for the ArrayObject.
|
Chris@0
|
237 *
|
Chris@0
|
238 * @return string
|
Chris@0
|
239 */
|
Chris@0
|
240 public function getIteratorClass()
|
Chris@0
|
241 {
|
Chris@0
|
242 return $this->iteratorClass;
|
Chris@0
|
243 }
|
Chris@0
|
244
|
Chris@0
|
245 /**
|
Chris@0
|
246 * Sort the entries by key
|
Chris@0
|
247 *
|
Chris@0
|
248 * @return void
|
Chris@0
|
249 */
|
Chris@0
|
250 public function ksort()
|
Chris@0
|
251 {
|
Chris@0
|
252 ksort($this->storage);
|
Chris@0
|
253 }
|
Chris@0
|
254
|
Chris@0
|
255 /**
|
Chris@0
|
256 * Sort an array using a case insensitive "natural order" algorithm
|
Chris@0
|
257 *
|
Chris@0
|
258 * @return void
|
Chris@0
|
259 */
|
Chris@0
|
260 public function natcasesort()
|
Chris@0
|
261 {
|
Chris@0
|
262 natcasesort($this->storage);
|
Chris@0
|
263 }
|
Chris@0
|
264
|
Chris@0
|
265 /**
|
Chris@0
|
266 * Sort entries using a "natural order" algorithm
|
Chris@0
|
267 *
|
Chris@0
|
268 * @return void
|
Chris@0
|
269 */
|
Chris@0
|
270 public function natsort()
|
Chris@0
|
271 {
|
Chris@0
|
272 natsort($this->storage);
|
Chris@0
|
273 }
|
Chris@0
|
274
|
Chris@0
|
275 /**
|
Chris@0
|
276 * Returns whether the requested key exists
|
Chris@0
|
277 *
|
Chris@0
|
278 * @param mixed $key
|
Chris@0
|
279 * @return bool
|
Chris@0
|
280 */
|
Chris@0
|
281 public function offsetExists($key)
|
Chris@0
|
282 {
|
Chris@0
|
283 return isset($this->storage[$key]);
|
Chris@0
|
284 }
|
Chris@0
|
285
|
Chris@0
|
286 /**
|
Chris@0
|
287 * Returns the value at the specified key
|
Chris@0
|
288 *
|
Chris@0
|
289 * @param mixed $key
|
Chris@0
|
290 * @return mixed
|
Chris@0
|
291 */
|
Chris@0
|
292 public function &offsetGet($key)
|
Chris@0
|
293 {
|
Chris@0
|
294 $ret = null;
|
Chris@12
|
295 if (! $this->offsetExists($key)) {
|
Chris@0
|
296 return $ret;
|
Chris@0
|
297 }
|
Chris@0
|
298 $ret =& $this->storage[$key];
|
Chris@0
|
299
|
Chris@0
|
300 return $ret;
|
Chris@0
|
301 }
|
Chris@0
|
302
|
Chris@0
|
303 /**
|
Chris@0
|
304 * Sets the value at the specified key to value
|
Chris@0
|
305 *
|
Chris@0
|
306 * @param mixed $key
|
Chris@0
|
307 * @param mixed $value
|
Chris@0
|
308 * @return void
|
Chris@0
|
309 */
|
Chris@0
|
310 public function offsetSet($key, $value)
|
Chris@0
|
311 {
|
Chris@0
|
312 $this->storage[$key] = $value;
|
Chris@0
|
313 }
|
Chris@0
|
314
|
Chris@0
|
315 /**
|
Chris@0
|
316 * Unsets the value at the specified key
|
Chris@0
|
317 *
|
Chris@0
|
318 * @param mixed $key
|
Chris@0
|
319 * @return void
|
Chris@0
|
320 */
|
Chris@0
|
321 public function offsetUnset($key)
|
Chris@0
|
322 {
|
Chris@0
|
323 if ($this->offsetExists($key)) {
|
Chris@0
|
324 unset($this->storage[$key]);
|
Chris@0
|
325 }
|
Chris@0
|
326 }
|
Chris@0
|
327
|
Chris@0
|
328 /**
|
Chris@0
|
329 * Serialize an ArrayObject
|
Chris@0
|
330 *
|
Chris@0
|
331 * @return string
|
Chris@0
|
332 */
|
Chris@0
|
333 public function serialize()
|
Chris@0
|
334 {
|
Chris@0
|
335 return serialize(get_object_vars($this));
|
Chris@0
|
336 }
|
Chris@0
|
337
|
Chris@0
|
338 /**
|
Chris@0
|
339 * Sets the behavior flags
|
Chris@0
|
340 *
|
Chris@0
|
341 * @param int $flags
|
Chris@0
|
342 * @return void
|
Chris@0
|
343 */
|
Chris@0
|
344 public function setFlags($flags)
|
Chris@0
|
345 {
|
Chris@0
|
346 $this->flag = $flags;
|
Chris@0
|
347 }
|
Chris@0
|
348
|
Chris@0
|
349 /**
|
Chris@0
|
350 * Sets the iterator classname for the ArrayObject
|
Chris@0
|
351 *
|
Chris@0
|
352 * @param string $class
|
Chris@0
|
353 * @return void
|
Chris@0
|
354 */
|
Chris@0
|
355 public function setIteratorClass($class)
|
Chris@0
|
356 {
|
Chris@0
|
357 if (class_exists($class)) {
|
Chris@0
|
358 $this->iteratorClass = $class;
|
Chris@0
|
359
|
Chris@0
|
360 return ;
|
Chris@0
|
361 }
|
Chris@0
|
362
|
Chris@0
|
363 if (strpos($class, '\\') === 0) {
|
Chris@0
|
364 $class = '\\' . $class;
|
Chris@0
|
365 if (class_exists($class)) {
|
Chris@0
|
366 $this->iteratorClass = $class;
|
Chris@0
|
367
|
Chris@0
|
368 return ;
|
Chris@0
|
369 }
|
Chris@0
|
370 }
|
Chris@0
|
371
|
Chris@0
|
372 throw new Exception\InvalidArgumentException('The iterator class does not exist');
|
Chris@0
|
373 }
|
Chris@0
|
374
|
Chris@0
|
375 /**
|
Chris@0
|
376 * Sort the entries with a user-defined comparison function and maintain key association
|
Chris@0
|
377 *
|
Chris@0
|
378 * @param callable $function
|
Chris@0
|
379 * @return void
|
Chris@0
|
380 */
|
Chris@0
|
381 public function uasort($function)
|
Chris@0
|
382 {
|
Chris@0
|
383 if (is_callable($function)) {
|
Chris@0
|
384 uasort($this->storage, $function);
|
Chris@0
|
385 }
|
Chris@0
|
386 }
|
Chris@0
|
387
|
Chris@0
|
388 /**
|
Chris@0
|
389 * Sort the entries by keys using a user-defined comparison function
|
Chris@0
|
390 *
|
Chris@0
|
391 * @param callable $function
|
Chris@0
|
392 * @return void
|
Chris@0
|
393 */
|
Chris@0
|
394 public function uksort($function)
|
Chris@0
|
395 {
|
Chris@0
|
396 if (is_callable($function)) {
|
Chris@0
|
397 uksort($this->storage, $function);
|
Chris@0
|
398 }
|
Chris@0
|
399 }
|
Chris@0
|
400
|
Chris@0
|
401 /**
|
Chris@0
|
402 * Unserialize an ArrayObject
|
Chris@0
|
403 *
|
Chris@0
|
404 * @param string $data
|
Chris@0
|
405 * @return void
|
Chris@0
|
406 */
|
Chris@0
|
407 public function unserialize($data)
|
Chris@0
|
408 {
|
Chris@0
|
409 $ar = unserialize($data);
|
Chris@0
|
410 $this->protectedProperties = array_keys(get_object_vars($this));
|
Chris@0
|
411
|
Chris@0
|
412 $this->setFlags($ar['flag']);
|
Chris@0
|
413 $this->exchangeArray($ar['storage']);
|
Chris@0
|
414 $this->setIteratorClass($ar['iteratorClass']);
|
Chris@0
|
415
|
Chris@0
|
416 foreach ($ar as $k => $v) {
|
Chris@0
|
417 switch ($k) {
|
Chris@0
|
418 case 'flag':
|
Chris@0
|
419 $this->setFlags($v);
|
Chris@0
|
420 break;
|
Chris@0
|
421 case 'storage':
|
Chris@0
|
422 $this->exchangeArray($v);
|
Chris@0
|
423 break;
|
Chris@0
|
424 case 'iteratorClass':
|
Chris@0
|
425 $this->setIteratorClass($v);
|
Chris@0
|
426 break;
|
Chris@0
|
427 case 'protectedProperties':
|
Chris@17
|
428 break;
|
Chris@0
|
429 default:
|
Chris@0
|
430 $this->__set($k, $v);
|
Chris@0
|
431 }
|
Chris@0
|
432 }
|
Chris@0
|
433 }
|
Chris@0
|
434 }
|