069f05e00909efbc7ad98540c1e75244539ec93c
[yaffs-website] / src / Utility / ArrayObject.php
1 <?php
2 /**
3  * @file
4  * Contains \Drupal\bootstrap\Utility\ArrayObject.
5  */
6
7 namespace Drupal\bootstrap\Utility;
8
9 use Drupal\Component\Utility\NestedArray;
10 use Drupal\Core\Cache\RefinableCacheableDependencyInterface;
11 use Drupal\Core\Render\AttachmentsInterface;
12 use Drupal\Core\Render\BubbleableMetadata;
13
14 /**
15  * Custom ArrayObject implementation.
16  *
17  * The native ArrayObject is unnecessarily complicated.
18  *
19  * @ingroup utility
20  */
21 class ArrayObject implements \IteratorAggregate, \ArrayAccess, \Serializable, \Countable, AttachmentsInterface, RefinableCacheableDependencyInterface {
22
23   /**
24    * The array.
25    *
26    * @var array
27    */
28   protected $array;
29
30   /**
31    * Array object constructor.
32    *
33    * @param array $array
34    *   An array.
35    */
36   public function __construct(array $array = []) {
37     $this->array = $array;
38   }
39
40   /**
41    * Returns whether the requested key exists.
42    *
43    * @param mixed $key
44    *   A key.
45    *
46    * @return bool
47    *   TRUE or FALSE
48    */
49   public function __isset($key) {
50     return $this->offsetExists($key);
51   }
52
53   /**
54    * Sets the value at the specified key to value.
55    *
56    * @param mixed $key
57    *   A key.
58    * @param mixed $value
59    *   A value.
60    */
61   public function __set($key, $value) {
62     $this->offsetSet($key, $value);
63   }
64
65   /**
66    * Unsets the value at the specified key.
67    *
68    * @param mixed $key
69    *   A key.
70    */
71   public function __unset($key) {
72     $this->offsetUnset($key);
73   }
74
75   /**
76    * Returns the value at the specified key by reference.
77    *
78    * @param mixed $key
79    *   A key.
80    *
81    * @return mixed
82    *   The stored value.
83    */
84   public function &__get($key) {
85     $ret =& $this->offsetGet($key);
86     return $ret;
87   }
88
89   /**
90    * {@inheritdoc}
91    */
92   public function addAttachments(array $attachments) {
93     BubbleableMetadata::createFromRenderArray($this->array)->addAttachments($attachments)->applyTo($this->array);
94     return $this;
95   }
96
97   /**
98    * {@inheritdoc}
99    */
100   public function addCacheContexts(array $cache_contexts) {
101     BubbleableMetadata::createFromRenderArray($this->array)->addCacheContexts($cache_contexts)->applyTo($this->array);
102     return $this;
103   }
104
105   /**
106    * {@inheritdoc}
107    */
108   public function addCacheTags(array $cache_tags) {
109     BubbleableMetadata::createFromRenderArray($this->array)->addCacheTags($cache_tags)->applyTo($this->array);
110     return $this;
111   }
112
113   /**
114    * {@inheritdoc}
115    */
116   public function addCacheableDependency($other_object) {
117     BubbleableMetadata::createFromRenderArray($this->array)->addCacheableDependency($other_object)->applyTo($this->array);
118     return $this;
119   }
120
121   /**
122    * Appends the value.
123    *
124    * @param mixed $value
125    *   A value.
126    */
127   public function append($value) {
128     $this->array[] = $value;
129   }
130
131   /**
132    * Sort the entries by value.
133    */
134   public function asort() {
135     asort($this->array);
136   }
137
138   /**
139    * Merges an object's cacheable metadata into the variables array.
140    *
141    * @param \Drupal\Core\Cache\CacheableDependencyInterface|mixed $object
142    *   The object whose cacheability metadata to retrieve. If it implements
143    *   CacheableDependencyInterface, its cacheability metadata will be used,
144    *   otherwise, the passed in object must be assumed to be uncacheable, so
145    *   max-age 0 is set.
146    *
147    * @return $this
148    */
149   public function bubbleObject($object) {
150     BubbleableMetadata::createFromRenderArray($this->array)->merge(BubbleableMetadata::createFromObject($object))->applyTo($this->array);
151     return $this;
152   }
153
154   /**
155    * Merges a render array's cacheable metadata into the variables array.
156    *
157    * @param array $build
158    *   A render array.
159    *
160    * @return $this
161    */
162   public function bubbleRenderArray(array $build) {
163     BubbleableMetadata::createFromRenderArray($this->array)->merge(BubbleableMetadata::createFromRenderArray($build))->applyTo($this->array);
164     return $this;
165   }
166
167   /**
168    * Get the number of public properties in the ArrayObject.
169    *
170    * @return int
171    *   The count.
172    */
173   public function count() {
174     return count($this->array);
175   }
176
177   /**
178    * Exchange the array for another one.
179    *
180    * @param array|ArrayObject $data
181    *   New data.
182    *
183    * @return array
184    *   The old array.
185    *
186    * @throws \InvalidArgumentException
187    *   When the passed data is not an array or an instance of ArrayObject.
188    */
189   public function exchangeArray($data) {
190     if (!is_array($data) && is_object($data) && !($data instanceof ArrayObject)) {
191       throw new \InvalidArgumentException('Passed variable is not an array or an instance of \Drupal\bootstrap\Utility\ArrayObject.');
192     }
193     if (is_object($data) && $data instanceof ArrayObject) {
194       $data = $data->getArrayCopy();
195     }
196     $old = $this->array;
197     $this->array = $data;
198     return $old;
199   }
200
201   /**
202    * Creates a copy of the ArrayObject.
203    *
204    * @return array
205    *   A copy of the array.
206    */
207   public function getArrayCopy() {
208     return $this->array;
209   }
210
211   /**
212    * {@inheritdoc}
213    */
214   public function getAttachments() {
215     return BubbleableMetadata::createFromRenderArray($this->array)->getAttachments();
216   }
217
218   /**
219    * {@inheritdoc}
220    */
221   public function getCacheContexts() {
222     return BubbleableMetadata::createFromRenderArray($this->array)->getCacheContexts();
223   }
224
225   /**
226    * {@inheritdoc}
227    */
228   public function getCacheTags() {
229     return BubbleableMetadata::createFromRenderArray($this->array)->getCacheTags();
230   }
231
232   /**
233    * {@inheritdoc}
234    */
235   public function getCacheMaxAge() {
236     return BubbleableMetadata::createFromRenderArray($this->array)->getCacheMaxAge();
237   }
238
239   /**
240    * Creates a new iterator from an ArrayObject instance.
241    *
242    * @return \ArrayIterator
243    *   An array iterator.
244    */
245   public function getIterator() {
246     return new \ArrayIterator($this->array);
247   }
248
249   /**
250    * Sort the entries by key.
251    */
252   public function ksort() {
253     ksort($this->array);
254   }
255
256   /**
257    * Merges multiple values into the array.
258    *
259    * @param array $values
260    *   An associative key/value array.
261    * @param bool $recursive
262    *   Flag determining whether or not to recursively merge key/value pairs.
263    */
264   public function merge(array $values, $recursive = TRUE) {
265     if ($recursive) {
266       $this->array = NestedArray::mergeDeepArray([$this->array, $values], TRUE);
267     }
268     else {
269       $this->array += $values;
270     }
271   }
272
273   /**
274    * {@inheritdoc}
275    */
276   public function mergeCacheMaxAge($max_age) {
277     BubbleableMetadata::createFromRenderArray($this->array)->mergeCacheMaxAge($max_age)->applyTo($this->array);
278     return $this;
279   }
280
281   /**
282    * Sort an array using a case insensitive "natural order" algorithm.
283    */
284   public function natcasesort() {
285     natcasesort($this->array);
286   }
287
288   /**
289    * Sort entries using a "natural order" algorithm.
290    */
291   public function natsort() {
292     natsort($this->array);
293   }
294
295   /**
296    * Returns whether the requested key exists.
297    *
298    * @param mixed $key
299    *   A key.
300    *
301    * @return bool
302    *   TRUE or FALSE
303    */
304   public function offsetExists($key) {
305     return isset($this->array[$key]);
306   }
307
308   /**
309    * Returns the value at the specified key.
310    *
311    * @param mixed $key
312    *   A key.
313    * @param mixed $default
314    *   The default value to set if $key does not exist.
315    *
316    * @return mixed
317    *   The value.
318    */
319   public function &offsetGet($key, $default = NULL) {
320     if (!$this->offsetExists($key)) {
321       $this->array[$key] = $default;
322     }
323     $ret = &$this->array[$key];
324     return $ret;
325   }
326
327   /**
328    * Sets the value at the specified key to value.
329    *
330    * @param mixed $key
331    *   A key.
332    * @param mixed $value
333    *   A value.
334    */
335   public function offsetSet($key, $value) {
336     $this->array[$key] = $value;
337   }
338
339   /**
340    * Unsets the value at the specified key.
341    *
342    * @param mixed $key
343    *   A key.
344    */
345   public function offsetUnset($key) {
346     if ($this->offsetExists($key)) {
347       unset($this->array[$key]);
348     }
349   }
350
351   /**
352    * Serialize an ArrayObject.
353    *
354    * @return string
355    *   The serialized value.
356    */
357   public function serialize() {
358     return serialize(get_object_vars($this));
359   }
360
361   /**
362    * {@inheritdoc}
363    */
364   public function setAttachments(array $attachments) {
365     BubbleableMetadata::createFromRenderArray($this->array)->setAttachments($attachments)->applyTo($this->array);
366     return $this;
367   }
368
369   /**
370    * Sort entries with a user-defined function and maintain key association.
371    *
372    * @param mixed $function
373    *   A callable function.
374    */
375   public function uasort($function) {
376     if (is_callable($function)) {
377       uasort($this->array, $function);
378     }
379   }
380
381   /**
382    * Sort the entries by keys using a user-defined comparison function.
383    *
384    * @param mixed $function
385    *   A callable function.
386    */
387   public function uksort($function) {
388     if (is_callable($function)) {
389       uksort($this->array, $function);
390     }
391   }
392
393   /**
394    * Unserialize an ArrayObject.
395    *
396    * @param string $data
397    *   The serialized data.
398    */
399   public function unserialize($data) {
400     $data = unserialize($data);
401     $this->exchangeArray($data['array']);
402   }
403
404 }