Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
25 / 25
CRAP
100.00% covered (success)
100.00%
1 / 1
AbstractArray
100.00% covered (success)
100.00%
50 / 50
100.00% covered (success)
100.00%
25 / 25
40
100.00% covered (success)
100.00%
1 / 1
 getIterator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 first
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 next
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 current
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 last
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 key
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 contains
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sort
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 sortDesc
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 ksort
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 ksortDesc
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 usort
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 uksort
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 split
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 join
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
4
 toArray
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 __set
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 __get
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 __isset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 __unset
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 offsetSet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 offsetGet
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetExists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 offsetUnset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2declare(strict_types=1);
3/**
4 * Pop PHP Framework (https://www.popphp.org/)
5 *
6 * @link       https://github.com/popphp/popphp-framework
7 * @author     Nick Sagona, III <nick@popphp.org>
8 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
9 * @license    https://www.popphp.org/license     New BSD License
10 */
11
12/**
13 * @namespace
14 */
15namespace Pop\Utils;
16
17use ArrayIterator;
18use ArrayAccess;
19use Countable;
20use IteratorAggregate;
21
22/**
23 * Pop utils abstract array object class
24 *
25 * @category   Pop
26 * @package    Pop\Utils
27 * @author     Nick Sagona, III <nick@popphp.org>
28 * @copyright  Copyright (c) 2009-2026 Nick Sagona, III
29 * @license    https://www.popphp.org/license     New BSD License
30 * @version    3.0.0
31 */
32abstract class AbstractArray implements ArrayableInterface, ArrayAccess, Countable, IteratorAggregate
33{
34
35    /**
36     * Array data
37     * @var mixed
38     */
39    protected mixed $data = null;
40
41    /**
42     * Method to iterate over the array object
43     *
44     * @return ArrayIterator
45     */
46    public function getIterator(): ArrayIterator
47    {
48        return new ArrayIterator($this->data);
49    }
50
51    /**
52     * Method to get the count of data in the collection
53     *
54     * @return int
55     */
56    public function count(): int
57    {
58        return count($this->data);
59    }
60
61    /**
62     * Get the first item of the array
63     *
64     * @return mixed
65     */
66    public function first(): mixed
67    {
68        return reset($this->data);
69    }
70
71    /**
72     * Get the next item of the array
73     *
74     * @return mixed
75     */
76    public function next(): mixed
77    {
78        return next($this->data);
79    }
80
81    /**
82     * Get the current item of the array
83     *
84     * @return mixed
85     */
86    public function current(): mixed
87    {
88        return current($this->data);
89    }
90
91    /**
92     * Get the last item of the array
93     *
94     * @return mixed
95     */
96    public function last(): mixed
97    {
98        return end($this->data);
99    }
100
101    /**
102     * Get the key of the current item of the array
103     *
104     * @return mixed
105     */
106    public function key(): mixed
107    {
108        return key($this->data);
109    }
110
111    /**
112     * Determine if an item exists in the array
113     *
114     * @param  mixed $key
115     * @param  bool  $strict
116     * @return bool
117     */
118    public function contains(mixed $key, bool $strict = false): bool
119    {
120        return in_array($key, $this->data, $strict);
121    }
122
123    /**
124     * Sort array
125     *
126     * @param  int  $flags
127     * @param  bool $assoc
128     * @param  bool $descending
129     * @return static
130     */
131    public function sort(int $flags = SORT_REGULAR, bool $assoc = true, bool $descending = false): static
132    {
133        if ($descending) {
134            $func = ($assoc) ? 'arsort' : 'rsort';
135        } else {
136            $func = ($assoc) ? 'asort' : 'sort';
137        }
138
139        $func($this->data, $flags);
140
141        return $this;
142    }
143
144    /**
145     * Sort array descending
146     *
147     * @param  int  $flags
148     * @param  bool $assoc
149     * @return static
150     */
151    public function sortDesc(int $flags = SORT_REGULAR, bool $assoc = true): static
152    {
153        return $this->sort($flags, $assoc, true);
154    }
155
156    /**
157     * Sort array by keys
158     *
159     * @param  int  $flags
160     * @param  bool $descending
161     * @return static
162     */
163    public function ksort(int $flags = SORT_REGULAR, bool $descending = false): static
164    {
165        if ($descending) {
166            krsort($this->data, $flags);
167        } else {
168            ksort($this->data, $flags);
169        }
170
171        return $this;
172    }
173
174    /**
175     * Sort array by keys, descending
176     *
177     * @param  int $flags
178     * @return static
179     */
180    public function ksortDesc(int $flags = SORT_REGULAR): static
181    {
182        return $this->ksort($flags, true);
183    }
184
185    /**
186     * Sort array by user-defined callback
187     *
188     * @param  mixed $callback
189     * @param  bool  $assoc
190     * @return static
191     */
192    public function usort(mixed $callback, bool $assoc = true): static
193    {
194        if ($assoc) {
195            uasort($this->data, $callback);
196        } else {
197            usort($this->data, $callback);
198        }
199
200        return $this;
201    }
202
203    /**
204     * Sort array by user-defined callback using keys
205     *
206     * @param  mixed $callback
207     * @return static
208     */
209    public function uksort(mixed $callback): static
210    {
211        uksort($this->data, $callback);
212        return $this;
213    }
214
215    /**
216     * Split a string into an array object
217     *
218     * @param  string $string
219     * @param  string $separator
220     * @param  int    $limit
221     * @return static
222     */
223    public static function split(string $string, string $separator, int $limit = PHP_INT_MAX): static
224    {
225        return new static(explode($separator, $string, $limit));
226    }
227
228    /**
229     * Join the array values into a string
230     *
231     * @param  string $glue
232     * @param  string $finalGlue
233     * @return string
234     */
235    public function join(string $glue, string $finalGlue = ''): string
236    {
237        if ($finalGlue === '') {
238            return implode($glue, $this->data);
239        }
240
241        if (count($this->data) == 0) {
242            return '';
243        }
244
245        if (count($this->data) == 1) {
246            return end($this->data);
247        }
248
249        $finalItem = array_pop($this->data);
250
251        return implode($glue, $this->data) . $finalGlue . $finalItem;
252    }
253
254    /**
255     * Get the values as an array
256     *
257     * @return array
258     */
259    public function toArray(): array
260    {
261        $data = Arr::toArray($this->data);
262
263        foreach ($data as $key => $value) {
264            if (is_object($value) && method_exists($value, 'toArray')) {
265                $data[$key] = $value->toArray();
266            }
267        }
268
269        return $data;
270    }
271
272    /**
273     * Magic method to set the property to the value of $this->data[$name]
274     *
275     * @param  ?string $name
276     * @param  mixed $value
277     * @return void
278     */
279    public function __set(?string $name = null, mixed $value = null): void
280    {
281        if ($name !== null) {
282            $this->data[$name] = $value;
283        } else {
284            $this->data[] = $value;
285        }
286    }
287
288    /**
289     * Get a value
290     *
291     * @param  string $name
292     * @return mixed
293     */
294    public function __get(string $name): mixed
295    {
296        return (array_key_exists($name, (array)$this->data)) ? $this->data[$name] : null;
297    }
298
299    /**
300     * Is value set
301     *
302     * @param  string $name
303     * @return bool
304     */
305    public function __isset(string $name): bool
306    {
307        return array_key_exists($name, (array)$this->data);
308    }
309
310    /**
311     * Unset a value
312     *
313     * @param  string $name
314     * @return void
315     */
316    public function __unset(string $name): void
317    {
318        if (array_key_exists($name, (array)$this->data)) {
319            unset($this->data[$name]);
320        }
321    }
322
323    /**
324     * ArrayAccess offsetSet
325     *
326     * @param  mixed $offset
327     * @param  mixed $value
328     * @return void
329     */
330    public function offsetSet(mixed $offset, mixed $value): void
331    {
332        $this->__set(($offset !== null) ? (string)$offset : null, $value);
333    }
334
335    /**
336     * ArrayAccess offsetGet
337     *
338     * @param  mixed $offset
339     * @return mixed
340     */
341    public function offsetGet(mixed $offset): mixed
342    {
343        return $this->__get((string)$offset);
344    }
345
346    /**
347     * ArrayAccess offsetExists
348     *
349     * @param  mixed $offset
350     * @return bool
351     */
352    public function offsetExists(mixed $offset): bool
353    {
354        return $this->__isset((string)$offset);
355    }
356
357    /**
358     * ArrayAccess offsetUnset
359     *
360     * @param  mixed $offset
361     * @return void
362     */
363    public function offsetUnset(mixed $offset): void
364    {
365        $this->__unset((string)$offset);
366    }
367
368}