Completed
Push — master ( 8ba9dc...a25acc )
by Tristan
02:09
created

Collection::sort()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 13
rs 9.4285
cc 2
eloc 7
nc 2
nop 1
1
<?php
2
3
namespace Enzyme\Collection;
4
5
use Closure;
6
7
class Collection extends BaseCollection
8
{
9
    /**
10
     * Get a PHP style array from the current collection.
11
     *
12
     * @return array
13
     */
14
    public function toArray()
15
    {
16
        return $this->items;
17
    }
18
19
    /**
20
     * Whether the collection has the specified key, and/or value associated
21
     * with the specified key.
22
     *
23
     * @param string $key
24
     * @param mixed  $value
25
     *
26
     * @return bool
27
     */
28
    public function has($key, $value = null)
29
    {
30
        $key_exists = self::keyExists($key, $this->items);
31
32
        return null !== $value
33
            ? $value === $this->get($key)
34
            : $key_exists;
35
    }
36
37
    /**
38
     * Get the value associated with the specified key.
39
     *
40
     * @param string $key
41
     *
42
     * @throws \Enzyme\Collection\CollectionException If the key does not exist.
43
     *
44
     * @return mixed
45
     */
46
    public function get($key)
47
    {
48
        if (false === self::keyExists($key, $this->items)) {
49
            throw new CollectionException(
50
                "An element with the key [${key}] does not exist."
51
            );
52
        }
53
54
        return $this->items[$key];
55
    }
56
57
    /**
58
     * Get the value associated with the specified key or return a default value
59
     * instead if it does not exist.
60
     *
61
     * @param string $key
62
     * @param mixed  $default
63
     *
64
     * @return mixed
65
     */
66
    public function getOrDefault($key, $default = null)
67
    {
68
        try {
69
            return $this->get($key);
70
        } catch (CollectionException $e) {
71
            return $default;
72
        }
73
    }
74
75
    /**
76
     * Execute the given callback function for each element in this collection.
77
     *
78
     * @param Closure $fn
79
     */
80
    public function each(Closure $fn)
81
    {
82
        foreach ($this->items as $key => $value) {
83
            if (false === $fn($value, $key)) {
84
                break;
85
            }
86
        }
87
    }
88
89
    /**
90
     * Execute the given callback function for each element in this collection
91
     * and save the results to a new collection.
92
     *
93
     * @param Closure $fn
94
     *
95
     * @return \Enzyme\Collection\Collection
96
     */
97 View Code Duplication
    public function map(Closure $fn)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
98
    {
99
        $results = [];
100
        foreach ($this->items as $key => $value) {
101
            $results[] = $fn($value, $key);
102
        }
103
104
        return new static($results);
105
    }
106
107
    /**
108
     * Pluck out all values in this collection which have the specified key.
109
     *
110
     * @param string $pluck_key
111
     * @param bool   $deep      Whether to traverse into sub-arrays.
112
     *
113
     * @return \Enzyme\Collection\Collection
114
     */
115
    public function pluck($pluck_key, $deep = true)
116
    {
117
        return self::pluckKey($this->items, $pluck_key, $deep);
118
    }
119
120
    /**
121
     * Get the number of elements in this collection.
122
     *
123
     * @return int
124
     */
125
    public function count()
126
    {
127
        return count($this->items);
128
    }
129
130
    /**
131
     * Whether this collection is empty.
132
     *
133
     * @return bool
134
     */
135
    public function isEmpty()
136
    {
137
        return $this->count() < 1;
138
    }
139
140
    /**
141
     * Get the value of the first element in this collection.
142
     *
143
     * @throws \Enzyme\Collection\CollectionException If the collection is empty.
144
     *
145
     * @return mixed
146
     */
147
    public function first()
148
    {
149
        if (true === $this->isEmpty()) {
150
            throw new CollectionException(
151
                'Cannot get first item as the collection is empty.'
152
            );
153
        }
154
155
        return reset($this->items);
156
    }
157
158
    /**
159
     * Get the value of the first element in this collection or return the
160
     * default value specified if the collection is empty.
161
     *
162
     * @param mixed $default
163
     *
164
     * @return mixed
165
     */
166
    public function firstOrDefault($default = null)
167
    {
168
        try {
169
            return $this->first();
170
        } catch (CollectionException $e) {
171
            return $default;
172
        }
173
    }
174
175
    /**
176
     * Get the value of the last element in this collection.
177
     *
178
     * @throws \Enzyme\Collection\CollectionException If the collection is empty.
179
     *
180
     * @return mixed
181
     */
182
    public function last()
183
    {
184
        if (true === $this->isEmpty()) {
185
            throw new CollectionException(
186
                'Cannot get last element as collection is empty.'
187
            );
188
        }
189
190
        end($this->items);
191
        $key = key($this->items);
192
        reset($this->items);
193
194
        return $this->items[$key];
195
    }
196
197
    /**
198
     * Get the value of the last element in this collection or return the
199
     * default value specified if the collection is empty.
200
     *
201
     * @param mixed $default
202
     *
203
     * @return mixed
204
     */
205
    public function lastOrDefault($default = null)
206
    {
207
        try {
208
            return $this->first();
209
        } catch (CollectionException $e) {
210
            return $default;
211
        }
212
    }
213
214
    /**
215
     * Get a new collection of only the elements in the current collection
216
     * that have the specified keys.
217
     *
218
     * @param array $keys
219
     *
220
     * @return \Enzyme\Collection\Collection
221
     */
222
    public function only(array $keys)
223
    {
224
        return $this->filter(function ($value, $key) use ($keys) {
225
            return true === self::keyExists($key, array_flip($keys));
226
        });
227
    }
228
229
    /**
230
     * Get a new collection of all the elements in the current collection
231
     * except those that have the specified keys.
232
     *
233
     * @param array $keys
234
     *
235
     * @return \Enzyme\Collection\Collection
236
     */
237
    public function except(array $keys)
238
    {
239
        return $this->filter(function ($value, $key) use ($keys) {
240
            return false === self::keyExists($key, array_flip($keys));
241
        });
242
    }
243
244
    /**
245
     * Return a new collection with the current collection's elements plus the
246
     * given value pushed onto the end of the array.
247
     *
248
     * @param mixed $value
249
     *
250
     * @return \Enzyme\Collection\Collection
251
     */
252
    public function push($value)
253
    {
254
        $items = $this->items;
255
        $items[] = $value;
256
257
        return new static($items);
258
    }
259
260
    /**
261
     * Return a new collection with the current collection's elements plus the
262
     * given key and value pushed onto the end of the array.
263
     *
264
     * @param string $key
265
     * @param mixed  $value
266
     *
267
     * @return \Enzyme\Collection\Collection
268
     */
269
    public function pushWithKey($key, $value)
270
    {
271
        $items = $this->items;
272
        $items[$key] = $value;
273
274
        return new static($items);
275
    }
276
277
    /**
278
     * Return a new collection with the current collection's elements plus the
279
     * given array pushed onto the end of the array.
280
     *
281
     * @param array $data
282
     *
283
     * @return \Enzyme\Collection\Collection
284
     */
285
    public function pushArray(array $data)
286
    {
287
        $items = $this->items;
288
        foreach ($data as $key => $value) {
289
            if (true === is_int($key)) {
290
                $items[] = $value;
291
            } else {
292
                $items[$key] = $value;
293
            }
294
        }
295
296
        return new static($items);
297
    }
298
299
    /**
300
     * Return a new collection with a subset of all the current collection's
301
     * elements that pass the given callback functions truth test.
302
     *
303
     * @param Closure $fn
304
     *
305
     * @return \Enzyme\Collection\Collection
306
     */
307 View Code Duplication
    public function filter(Closure $fn)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
308
    {
309
        $results = [];
310
        foreach ($this->items as $key => $value) {
311
            if (true === $fn($value, $key)) {
312
                $results[$key] = $value;
313
            }
314
        }
315
316
        // Pushing this new array will normalize numeric keys if they exist.
317
        // After filtering, they may not start at zero and sequentially
318
        // go upwards, which is generally not expected.
319
        return (new static())->pushArray($results);
320
    }
321
322
    /**
323
     * Sort the collection using the provided callback function. Same expected
324
     * parameters and the PHP usort function.
325
     *
326
     * @param Closure $fn
327
     *
328
     * @return \Enzyme\Collection\Collection
329
     */
330
    public function sort(Closure $fn)
331
    {
332
        $sorted = $this->items;
333
        $result = usort($sorted, $fn);
334
335
        if (false === $result) {
336
            throw new CollectionException(
337
                'The collection could be not sorted.'
338
            );
339
        }
340
341
        return new static($sorted);
342
    }
343
344
    /**
345
     * Checks whether the specified key exists in the given collection.
346
     *
347
     * @param string $key
348
     * @param array  $collection
349
     *
350
     * @return bool
351
     */
352
    protected static function keyExists($key, array $collection)
353
    {
354
        return true === isset($collection[$key]);
355
    }
356
357
    /**
358
     * Pluck all the values that have the specified key from the given
359
     * collection.
360
     *
361
     * @param array  $collection
362
     * @param string $pluck_key
363
     * @param bool   $deep       Whether to traverse into sub-arrays.
364
     *
365
     * @return \Enzyme\Collection\Collection
366
     */
367
    protected static function pluckKey(array $collection, $pluck_key, $deep)
368
    {
369
        $results = [];
370
        foreach ($collection as $key => $value) {
371
            if (true === $deep && true === is_array($value)) {
372
                $deeper_results = self::pluckKey(
373
                    $value,
374
                    $pluck_key,
375
                    $deep
376
                )->toArray();
377
378
                foreach ($deeper_results as $deep_value) {
379
                    $results[] = $deep_value;
380
                }
381
382
                continue;
383
            }
384
385
            if ($key === $pluck_key) {
386
                $results[] = $value;
387
            }
388
        }
389
390
        return new static($results);
391
    }
392
}
393