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