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