Completed
Push — master ( 8662c2...fe2965 )
by ARCANEDEV
08:15
created

Collection::diffKeys()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 2
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php namespace Arcanedev\Support;
2
3
use Illuminate\Contracts\Support\Arrayable;
4
use Illuminate\Contracts\Support\Jsonable;
5
use Illuminate\Support\Arr;
6
use Illuminate\Support\Collection as IlluminateCollection;
7
use JsonSerializable;
8
9
/**
10
 * Class     Collection
11
 *
12
 * @package  Arcanedev\Support
13
 * @author   ARCANEDEV <[email protected]>
14
 */
15
class Collection extends IlluminateCollection
16
{
17
    /* ------------------------------------------------------------------------------------------------
18
     |  Constructor
19
     | ------------------------------------------------------------------------------------------------
20
     */
21
    /**
22
     * Create a new collection.
23
     *
24
     * @param  mixed  $items
25
     */
26 1136
    public function __construct($items = [])
27
    {
28 1136
        $this->items = $this->getArrayableItems($items);
29 1136
    }
30
31
    /* ------------------------------------------------------------------------------------------------
32
     |  Main Functions
33
     | ------------------------------------------------------------------------------------------------
34
     */
35
    /**
36
     * Get the median of a given key.
37
     *
38
     * @param  null $key
39
     * @return mixed|null
40
     */
41 40
    public function median($key = null)
42
    {
43 40
        $count = $this->count();
44
45 40
        if ($count == 0) return null;
46
47
        /** @var static $values */
48 32
        $values = with(isset($key) ? $this->pluck($key) : $this)
49 32
            ->sort()
50 32
            ->values();
51
52 32
        $middle = (int) floor($count / 2);
53
54 32
        if ($count % 2) {
55 8
            return $values->get($middle);
56
        }
57
58 24
        return (new static([
59 24
            $values->get($middle - 1), $values->get($middle),
60 24
        ]))->average();
61
    }
62
63
    /**
64
     * Get the mode of a given key.
65
     *
66
     * @param  null $key
67
     * @return array
68
     */
69 32
    public function mode($key = null)
70
    {
71 32
        $count = $this->count();
72
73 32
        if ($count == 0) return null;
74
75 24
        $collection = isset($key) ? $this->pluck($key) : $this;
76
77 24
        $counts = new self;
78
79
        $collection->each(function ($value) use ($counts) {
80 24
            $counts[$value] = isset($counts[$value]) ? $counts[$value] + 1 : 1;
81 24
        });
82
83 24
        $sorted = $counts->sort();
84
85 24
        $highestValue = $sorted->last();
86
87
        return $sorted->filter(function ($value) use ($highestValue) {
88 12
            return $value == $highestValue;
89 12
        })->sort()->keys()->all();
90
    }
91
92
    /**
93
     * Get the items in the collection whose keys are not present in the given items.
94
     *
95
     * @param  mixed  $items
96
     * @return static
97
     */
98 8
    public function diffKeys($items)
99
    {
100 8
        return new static(array_diff_key($this->items, $this->getArrayableItems($items)));
101
    }
102
103
    /**
104
     * Run a filter over each of the items.
105
     *
106
     * @param  callable|null  $callback
107
     * @return static
108
     */
109 80
    public function filter(callable $callback = null)
110
    {
111 80
        if ($callback) {
112 80
            $return = [];
113
114 80
            foreach ($this->items as $key => $value) {
115 80
                if ($callback($value, $key)) {
116 80
                    $return[$key] = $value;
117 60
                }
118 60
            }
119
120 80
            return new static($return);
121
        }
122
123 8
        return new static(array_filter($this->items));
124
    }
125
126
    /**
127
     * Get the first item from the collection.
128
     *
129
     * @param  callable|null  $callback
130
     * @param  mixed  $default
131
     * @return mixed
132
     */
133 64
    public function first(callable $callback = null, $default = null)
134
    {
135 64
        return Arr::first($this->items, $callback, $default);
136
    }
137
138
    /**
139
     * Filter items by the given key value pair.
140
     *
141
     * @param  string  $key
142
     * @param  array   $values
143
     * @param  bool    $strict
144
     *
145
     * @return static
146
     */
147 27
    public function whereIn($key, array $values, $strict = true)
148
    {
149
        return $this->filter(function ($item) use ($key, $values, $strict) {
150 27
            return in_array(data_get($item, $key), $values, $strict);
151 12
        });
152
    }
153
154
    /**
155
     * Group an associative array by a field or using a callback.
156
     *
157
     * @param  callable|string  $groupBy
158
     * @param  bool  $preserveKeys
159
     * @return static
160
     */
161 48
    public function groupBy($groupBy, $preserveKeys = false)
162
    {
163 48
        $groupBy = $this->valueRetriever($groupBy);
0 ignored issues
show
Documentation introduced by
$groupBy is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
164
165 48
        $results = [];
166
167 48
        foreach ($this->items as $key => $value) {
168 48
            $groupKeys = $groupBy($value, $key);
169
170 48
            if (! is_array($groupKeys)) {
171 32
                $groupKeys = [$groupKeys];
172 24
            }
173
174 48
            foreach ($groupKeys as $groupKey) {
175 48
                if (! array_key_exists($groupKey, $results)) {
176 48
                    $results[$groupKey] = new static;
177 36
                }
178
179 48
                $results[$groupKey]->offsetSet($preserveKeys ? $key : null, $value);
180 36
            }
181 36
        }
182
183 48
        return new static($results);
184
    }
185
186
    /**
187
     * Key an associative array by a field or using a callback.
188
     *
189
     * @param  callable|string  $keyBy
190
     * @return static
191
     */
192 16
    public function keyBy($keyBy)
193
    {
194 16
        $keyBy = $this->valueRetriever($keyBy);
0 ignored issues
show
Documentation introduced by
$keyBy is of type callable, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
195
196 16
        $results = [];
197
198 16
        foreach ($this->items as $key => $item) {
199 16
            $results[$keyBy($item, $key)] = $item;
200 12
        }
201
202 16
        return new static($results);
203
    }
204
205
    /**
206
     * Get the last item from the collection.
207
     *
208
     * @param  callable|null  $callback
209
     * @param  mixed  $default
210
     * @return mixed
211
     */
212 56
    public function last(callable $callback = null, $default = null)
213
    {
214 56
        return Arr::last($this->items, $callback, $default);
215
    }
216
217
    /**
218
     * Create a collection by using this collection for keys and another for its values.
219
     *
220
     * @param  mixed  $values
221
     * @return static
222
     */
223 16
    public function combine($values)
224
    {
225 16
        return new static(array_combine($this->all(), $this->getArrayableItems($values)));
226
    }
227
228
    /**
229
     * Union the collection with the given items.
230
     *
231
     * @param  mixed  $items
232
     * @return static
233
     */
234 24
    public function union($items)
235
    {
236 24
        return new static($this->items + $this->getArrayableItems($items));
237
    }
238
239
    /**
240
     * Pass the collection to the given callback and return the result.
241
     *
242
     * @param  callable $callback
243
     * @return mixed
244
     */
245 8
    public function pipe(callable $callback)
246
    {
247 8
        return $callback($this);
248
    }
249
250
    /**
251
     * Reverse items order.
252
     *
253
     * @return static
254
     */
255 8
    public function reverse()
256
    {
257 8
        return new static(array_reverse($this->items, true));
258
    }
259
260
    /**
261
     * Shuffle the items in the collection.
262
     *
263
     * @param int $seed
264
     * @return static
265
     */
266
    public function shuffle($seed = null)
267
    {
268
        $items = $this->items;
269
270
        if (is_null($seed)) {
271
            shuffle($items);
272
        } else {
273
            srand($seed);
274
275
            usort($items, function () {
276
                return rand(-1, 1);
277
            });
278
        }
279
280
        return new static($items);
281
    }
282
283
    /**
284
     * Convert the object into something JSON serializable.
285
     *
286
     * @return array
287
     */
288
    public function jsonSerialize()
289
    {
290 36
        return array_map(function ($value) {
291 36
            if ($value instanceof JsonSerializable) {
292 16
                return $value->jsonSerialize();
293 27
            } elseif ($value instanceof Jsonable) {
294 8
                return json_decode($value->toJson(), true);
295 27
            } elseif ($value instanceof Arrayable) {
296 16
                return $value->toArray();
297
            } else {
298 28
                return $value;
299
            }
300 36
        }, $this->items);
301
    }
302
303
    /**
304
     * Get the collection of items as JSON.
305
     *
306
     * @param  int  $options
307
     * @return string
308
     */
309 20
    public function toJson($options = 0)
310
    {
311 20
        return json_encode($this->jsonSerialize(), $options);
312
    }
313
314
    /**
315
     * Results array of items from Collection or Arrayable.
316
     *
317
     * @param  mixed  $items
318
     * @return array
319
     */
320 1136
    protected function getArrayableItems($items)
321
    {
322 1136
        if (is_array($items)) {
323 1088
            return $items;
324 184
        } elseif ($items instanceof self) {
325 80
            return $items->all();
326 84
        } elseif ($items instanceof Arrayable) {
327 8
            return $items->toArray();
328 84
        } elseif ($items instanceof Jsonable) {
329 8
            return json_decode($items->toJson(), true);
330 84
        } elseif ($items instanceof JsonSerializable) {
331 8
            return $items->jsonSerialize();
332
        }
333
334 104
        return (array) $items;
335
    }
336
337
    /* ------------------------------------------------------------------------------------------------
338
     |  Custom Functions
339
     | ------------------------------------------------------------------------------------------------
340
     */
341
    /**
342
     * Reset the collection.
343
     *
344
     * @return self
345
     */
346 8
    public function reset()
347
    {
348 8
        $this->items = [];
349
350 8
        return $this;
351
    }
352
}
353