Passed
Push — develop ( 5cea65...ca634b )
by Mathieu
02:04
created

Collection::getRandom()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 9
ccs 0
cts 6
cp 0
crap 6
rs 10
c 0
b 0
f 0
1
<?php
2
namespace Suricate;
3
4
class Collection implements \IteratorAggregate, \Countable, \ArrayAccess, Interfaces\ICollection
5
{
6
    
7
    protected $items            = [];
8
    protected $mapping          = []; // to be deprecated ?
9
10
    const ITEM_TYPE             = '';
11
12
    public $pagination = [
13
        'nbPages'   => 0,
14
        'page'      => 1,
15
        'nbItems'   => 0,
16
    ];
17
    
18
    //protected $iteratorPosition  = 0;
19
20 23
    public function __construct($items = [])
21
    {
22 23
        $this->items = $items;
23 23
    }
24
25 1
    public function paginate($nbItemPerPage, $currentPage = 1)
26
    {
27 1
        $this->pagination['page']       = $currentPage;
28 1
        $this->pagination['nbItems']    = count($this->items);
29 1
        $this->pagination['nbPages']    = ceil($this->pagination['nbItems'] / $nbItemPerPage);
30
31 1
        $this->items = array_slice($this->items, ($currentPage - 1) * $nbItemPerPage, $nbItemPerPage);
32
33 1
        return $this;
34
    }
35
36
    public function getPossibleValuesFor($args, $key = null)
37
    {
38
        if (!is_array($args)) {
39
            $args = [
40
                'format' => '%s',
41
                'data' => [$args]
42
            ];
43
        }
44
45
        $values = [];
46
        foreach ($this->items as $item) {
47
            $itemValues = [];
48
            foreach ($args['data'] as $arg) {
49
                $itemValues[] = dataGet($item, $arg);
50
            }
51
            $arrayKey = ($key !== null) ? dataGet($item, $key) : null;
52
            $values[$arrayKey] = vsprintf($args['format'], $itemValues);
53
        }
54
55
        return $values;
56
    }
57
58 1
    public function getValuesFor($name)
59
    {
60 1
        $values = [];
61 1
        foreach ($this->items as $item) {
62 1
            $values[] = dataGet($item, $name);
63
        }
64
65 1
        return $values;
66
    }
67
68 12
    public function getItems()
69
    {
70 12
        return $this->items;
71
    }
72
73
    /*public function addItemLink($linkId)
74
    {
75
        $this->items[$this->itemOffset] = $linkId;
76
        // add mapping between item->index and $position in items pool
77
        $this->mapping[$this->itemOffset] = $linkId;
78
79
        $this->itemOffset++;
80
    }*/
81
82
    
83
84
    public function getItemFromKey($key)
85
    {
86
        $invertedMapping = array_flip($this->mapping);
87
        if (isset($invertedMapping[$key])) {
88
            return $this->items[$invertedMapping[$key]];
89
        }
90
    }
91
92
93
    /**
94
     * Implementation of countable interface
95
     *
96
     * @return int
97
     */
98 1
    public function count(): int
99
    {
100 1
        return count($this->items);
101
    }
102
103
    /**
104
     * Implementation of IteratorAggregate Interface
105
     *
106
     * @return \ArrayIterator
107
     */
108 1
    public function getIterator(): \ArrayIterator
109
    {
110 1
        return new \ArrayIterator($this->items);
111
    }
112
113
    /**
114
     * Implementation of ArrayAccess interface
115
     *
116
     * @param  mixed $offset Offset to verify
117
     * @return bool
118
     */
119 1
    public function offsetExists($offset): bool
120
    {
121 1
        return isset($this->items[$offset]);
122
    }
123
124
    /**
125
     * Implementation of ArrayAccess Interface
126
     *
127
     * @param  mixed $offset Offset to get
128
     * @return mixed
129
     */
130
    public function offsetGet($offset)
131
    {
132
        $item =isset($this->items[$offset]) ? $this->items[$offset] : null;
133
        if (gettype($item) == 'object' || $item == null) {
134
            return $item;
135
        }
136
        // Lazy load
137
        $itemType = $this::ITEM_TYPE;
138
        $itemToLoad = new $itemType;
139
        $itemToLoad->load($this->items[$offset]);
140
141
        $this->items[$offset] = $itemToLoad;
142
143
        return $this->items[$offset];
144
    }
145
146
    /**
147
     * Implementation of ArrayAccess Interface
148
     *
149
     * @param mixed $offset Offset to set
150
     * @param mixed $value  Value to set
151
     * @return void
152
     */
153
    public function offsetSet($offset, $value): void
154
    {
155
        if (is_null($offset)) {
156
            $this->items[] = $value;
157
        } else {
158
            $this->items[$offset] = $value;
159
        }
160
    }
161
162
    /**
163
     * Implementation of ArrayAccess Interface
164
     *
165
     * @param mixed $offset Offset to unset
166
     * @return void
167
     */
168
    public function offsetUnset($offset): void
169
    {
170
        unset($this->items[$offset]);
171
    }
172
173
    // Helpers
174
175
    /**
176
     * Get first item of the collection
177
     *
178
     * @return mixed
179
     */
180 1
    public function first()
181
    {
182 1
        foreach ($this->items as $currentItem) {
183 1
            return $currentItem;
184
        }
185
    }
186
187
    /**
188
     * Get last item of the collection
189
     *
190
     * @return mixed
191
     */
192 1
    public function last()
193
    {
194 1
        if (count($this->items)) {
195 1
            return end($this->items);
196
        }
197
        
198 1
        return null;
199
    }
200
201
    /**
202
     * Check if collection is empty
203
     *
204
     * @return bool
205
     */
206 1
    public function isEmpty(): bool
207
    {
208 1
        return empty($this->items);
209
    }
210
211
    /**
212
     * Return the sum of the collection
213
     *
214
     * @param mixed $field Field to use for sum
215
     * @return double|integer
216
     */
217 1
    public function sum($field = null)
218
    {
219 1
        if ($field === null) {
220 1
            return array_sum($this->items);
221
        }
222 1
        $result = 0;
223 1
        foreach ($this->items as $item) {
224 1
            $result += dataGet($item, $field);
225
        }
226 1
        return $result;
227
    }
228
229
    public function random($nbItems = 1)
230
    {
231
        if ($this->isEmpty()) {
232
            return null;
233
        }
234
235
        $keys = array_rand($this->items, $nbItems);
236
237
        if (is_array($keys)) {
238
            return array_intersect_key($this->items, array_flip($keys));
239
        }
240
        
241
        return $this->items[$keys];
242
    }
243
244
    public function shuffle()
245
    {
246
        shuffle($this->items);
247
248
        return $this;
249
    }
250
251 1
    public function unique()
252
    {
253 1
        return new static(array_unique($this->items));
254
    }
255
256
    /**
257
     * Apply a closure to each element of the collection
258
     *
259
     * @param \Closure $callback Closure to apply
260
     * @return Collection
261
     */
262
    public function each(\Closure $callback): Collection
263
    {
264
        array_map($callback, $this->items);
265
        return $this;
266
    }
267
268
    /**
269
     * Sort a collection using a closure
270
     *
271
     * @param \Closure $closure Closure to apply for sorting, similar to uasort() closure
272
     * @return Collection
273
     */
274
    public function sort(\Closure $closure): Collection
275
    {
276
        uasort($this->items, $closure);
277
278
        return $this;
279
    }
280
281
    public function sortBy($field, $reverse = false)
282
    {
283
        if ($reverse) {
284
            $sortFunction = function ($a, $b) use ($field) {
285
                $first = dataGet($a, $field);
286
                $second = dataGet($b, $field);
287
                if ($first == $second) {
288
                    return 0;
289
                }
290
                return ($first > $second) ? -1 : 1;
291
            };
292
        } else {
293
            $sortFunction = function ($a, $b) use ($field) {
294
                $first = dataGet($a, $field);
295
                $second = dataGet($b, $field);
296
                if ($first == $second) {
297
                    return 0;
298
                }
299
                return ($first < $second) ? -1 : 1;
300
            };
301
        }
302
303
304
        usort($this->items, $sortFunction);
305
306
        return $this;
307
    }
308
309 1
    public function filter(\Closure $closure)
310
    {
311 1
        return new static(array_filter($this->items, $closure));
312
    }
313
314 1
    public function search($value, $strict = false)
315
    {
316 1
        return array_search($value, $this->items, $strict);
317
    }
318
319 1
    public function has($key)
320
    {
321 1
        return $this->offsetExists($key);
322
    }
323
324 1
    public function keys()
325
    {
326 1
        return array_keys($this->items);
327
    }
328
329 1
    public function prepend($item)
330
    {
331 1
        array_unshift($this->items, $item);
332
333 1
        return $this;
334
    }
335
336 1
    public function push($item)
337
    {
338 1
        $this->items[] = $item;
339
340 1
        return $this;
341
    }
342
343 1
    public function put($key, $val)
344
    {
345 1
        $this->items[$key] = $val;
346
347 1
        return $this;
348
    }
349 1
    public function shift()
350
    {
351 1
        return array_shift($this->items);
352
    }
353
    
354 1
    public function pop()
355
    {
356 1
        return array_pop($this->items);
357
    }
358
359 1
    public function reverse()
360
    {
361 1
        return new static(array_reverse($this->items));
362
    }
363
364 1
    public function reduce(callable $callback, $initial = null)
365
    {
366 1
        return array_reduce($this->items, $callback, $initial);
367
    }
368
369 2
    public function slice($offset, $length = null, $preserveKeys = false)
370
    {
371 2
        return new static(array_slice($this->items, $offset, $length, $preserveKeys));
372
    }
373
374 1
    public function take($limit = null)
375
    {
376 1
        if ($limit < 0) {
377
            return $this->slice(abs($limit), $limit);
378
        }
379
380 1
        return $this->slice(0, $limit);
381
    }
382
383
    public function splice($offset, $length = null, $replacement = [])
384
    {
385
        return new static(array_splice($this->items, $offset, $length, $replacement));
386
    }
387
388
    public function chunk($size, $preserveKeys = false)
389
    {
390
        $result = new static;
391
        foreach (array_chunk($this->items, $size, $preserveKeys) as $chunk) {
392
            $result->push(new static($chunk));
393
        }
394
        return $result;
395
    }
396
}
397