Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
19 / 19
CRAP
100.00% covered (success)
100.00%
1 / 1
Collection
100.00% covered (success)
100.00%
43 / 43
100.00% covered (success)
100.00%
19 / 19
32
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 each
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 every
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 filter
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 map
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 flip
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 has
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isEmpty
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 keys
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 column
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 values
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 merge
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 forPage
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 pop
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 push
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 shift
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 slice
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 splice
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 getDataAsArray
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2/**
3 * Pop PHP Framework (https://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@noladev.com>
7 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
8 * @license    https://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Utils;
15
16/**
17 * Pop utils array collection class
18 *
19 * @category   Pop
20 * @package    Pop\Utils
21 * @author     Nick Sagona, III <dev@noladev.com>
22 * @copyright  Copyright (c) 2009-2026 NOLA Interactive, LLC.
23 * @license    https://www.popphp.org/license     New BSD License
24 * @version    2.3.0
25 */
26class Collection extends AbstractArray
27{
28
29    /**
30     * Constructor
31     *
32     * Instantiate the collection object
33     *
34     * @param mixed $data
35     */
36    public function __construct(mixed $data = [])
37    {
38        $this->data = $this->getDataAsArray($data);
39    }
40
41    /**
42     * Execute a callback over each item
43     *
44     * @param  callable $callback
45     * @return Collection
46     */
47    public function each(callable $callback): Collection
48    {
49        foreach ($this->data as $key => $item) {
50            if ($callback($item, $key) === false) {
51                break;
52            }
53        }
54
55        return $this;
56    }
57
58    /**
59     * Create a new collection from every n-th element
60     *
61     * @param  int $step
62     * @param  int $offset
63     * @return Collection
64     */
65    public function every(int $step, int $offset = 0): Collection
66    {
67        $new      = [];
68        $position = 0;
69
70        foreach ($this->data as $item) {
71            if (($position % $step) === $offset) {
72                $new[] = $item;
73            }
74            $position++;
75        }
76
77        return new static($new);
78    }
79
80    /**
81     * Apply filter to the collection
82     *
83     * @param  ?callable $callback
84     * @param  int       $flag
85     * @return Collection
86     */
87    public function filter(?callable $callback = null, int $flag = 0): Collection
88    {
89        return new static(array_filter($this->data, $callback, $flag));
90    }
91
92    /**
93     * Apply map to the collection
94     *
95     * @param  callable $callback
96     * @return Collection
97     */
98    public function map(callable $callback): Collection
99    {
100        return new static(array_map($callback, $this->data));
101    }
102
103    /**
104     * Flip the data in the collection
105     *
106     * @return Collection
107     */
108    public function flip(): Collection
109    {
110        foreach ($this->data as $i => $item) {
111            $this->data[$i] = array_flip($item);
112        }
113        return new static($this->data);
114    }
115
116    /**
117     * Determine if the key exists
118     *
119     * @param  mixed $key
120     * @return bool
121     */
122    public function has(mixed $key): bool
123    {
124        return $this->offsetExists($key);
125    }
126
127    /**
128     * Determine if the collection is empty or not
129     *
130     * @return bool
131     */
132    public function isEmpty(): bool
133    {
134        return empty($this->data);
135    }
136
137    /**
138     * Get the keys of the collection data
139     *
140     * @return Collection
141     */
142    public function keys(): Collection
143    {
144        return new static(array_keys($this->data));
145    }
146
147    /**
148     * Get the values of a column
149     *
150     * @return Collection
151     */
152    public function column(string $column): Collection
153    {
154        return new static(array_column($this->data, $column));
155    }
156
157    /**
158     * Get the values of the collection data
159     *
160     * @return Collection
161     */
162    public function values(): Collection
163    {
164        return new static(array_values($this->data));
165    }
166
167    /**
168     * Merge the collection with the passed data
169     *
170     * @param  mixed $data
171     * @param  bool  $recursive
172     * @return Collection
173     */
174    public function merge(mixed $data, bool $recursive = false): Collection
175    {
176        return ($recursive) ?
177            new static(array_merge_recursive($this->data, $this->getDataAsArray($data))) :
178            new static(array_merge($this->data, $this->getDataAsArray($data)));
179    }
180
181    /**
182     * Slice the collection for a page
183     *
184     * @param  int  $page
185     * @param  int  $perPage
186     * @return Collection
187     */
188    public function forPage(int $page, int $perPage): Collection
189    {
190        return $this->slice(($page - 1) * $perPage, $perPage);
191    }
192
193    /**
194     * Get and remove the last item from the collection
195     *
196     * @return mixed
197     */
198    public function pop(): mixed
199    {
200        return array_pop($this->data);
201    }
202
203    /**
204     * Push an item onto the end of the collection.
205     *
206     * @param  mixed $value
207     * @return Collection
208     */
209    public function push(mixed $value): Collection
210    {
211        $this->offsetSet(null, $value);
212        return $this;
213    }
214
215    /**
216     * Get and remove the first item from the collection
217     *
218     * @return mixed
219     */
220    public function shift(): mixed
221    {
222        return array_shift($this->data);
223    }
224
225    /**
226     * Slice the collection
227     *
228     * @param  int  $offset
229     * @param  ?int $length
230     * @return Collection
231     */
232    public function slice(int $offset, ?int $length = null): Collection
233    {
234        return new static(array_slice($this->data, $offset, $length, true));
235    }
236
237    /**
238     * Splice a portion of the collection
239     *
240     * @param  int   $offset
241     * @param  ?int  $length
242     * @param  mixed $replacement
243     * @return Collection
244     */
245    public function splice(int $offset, ?int $length = null, mixed $replacement = []): Collection
246    {
247        return (($length === null) && (count($replacement) == 0)) ?
248            new static(array_splice($this->data, $offset)) :
249            new static(array_splice($this->data, $offset, $length, $replacement));
250    }
251
252    /**
253     * Method to get data as an array
254     *
255     * @param  mixed $data
256     * @return array
257     */
258    protected function getDataAsArray(mixed $data): array
259    {
260        if ($data instanceof self) {
261            $data = $data->toArray();
262        } else if ($data instanceof \ArrayObject) {
263            $data = (array)$data;
264        } else if (is_object($data) && method_exists($data, 'toArray')) {
265            $data = $data->toArray();
266        } else if ($data instanceof \Traversable) {
267            $data = iterator_to_array($data);
268        }
269
270        return $data;
271    }
272
273}