Arr::lastKey()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 2
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the Phalcon.
5
 *
6
 * (c) Phalcon Team <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace Phalcon\Helper;
15
16
use function array_chunk;
17
use function array_diff_key;
18
use function array_filter;
19
use function array_flip;
20
use function array_intersect_key;
21
use function array_key_exists;
22
use function array_key_first;
23
use function array_key_last;
24
use function array_keys;
25
use function array_merge;
26
use function array_slice;
27
use function array_unique;
28
use function array_values;
29
use function call_user_func;
30
use function end;
31
use function function_exists;
32
use function is_array;
33
use function is_callable;
34
use function is_int;
35
use function is_object;
36
use function is_string;
37
use function krsort;
38
use function ksort;
39
use function reset;
40
use function settype;
41
42
/**
43
 * This class offers quick array functions throughout the framework
44
 */
45
class Arr
46
{
47
    /**
48
     * Black list filter by key: exclude elements of an array
49
     * by the keys obtained from the elements of a blacklist
50
     *
51
     * @param array $collection
52
     * @param array $blackList
53
     *
54
     * @return array
55
     */
56 1
    final public static function blackList(
57
        array $collection,
58
        array $blackList
59
    ): array {
60 1
        $blackList = array_filter(
61 1
            $blackList,
62
            function ($element) {
63 1
                return is_int($element) || is_string($element);
64 1
            }
65
        );
66
67 1
        return array_diff_key(
68 1
            $collection,
69 1
            array_flip($blackList)
70
        );
71
    }
72
73
    /**
74
     * Chunks an array into smaller arrays of a specified size.
75
     *
76
     * @param array $collection
77
     * @param int   $size
78
     * @param bool  $preserveKeys
79
     *
80
     * @return array
81
     */
82 2
    final public static function chunk(
83
        array $collection,
84
        int $size,
85
        bool $preserveKeys = false
86
    ): array {
87 2
        return array_chunk($collection, $size, $preserveKeys);
88
    }
89
90
    /**
91
     * Helper method to filter the collection
92
     *
93
     * @param array    $collection
94
     * @param callable $method
95
     *
96
     * @return array
97
     */
98 20
    final public static function filter(
99
        array $collection,
100
        $method = null
101
    ): array {
102 20
        if (null === $method || !is_callable($method)) {
103 13
            return $collection;
104
        }
105
106 7
        return array_filter($collection, $method);
107
    }
108
109
    /**
110
     * Returns the first element of the collection. If a callable is passed, the
111
     * element returned is the first that validates true
112
     *
113
     * @param array    $collection
114
     * @param callable $method
115
     *
116
     * @return mixed
117
     */
118 3
    final public static function first(array $collection, $method = null)
119
    {
120 3
        $filtered = self::filter($collection, $method);
121
122 3
        return reset($filtered);
123
    }
124
125
    /**
126
     * Returns the key of the first element of the collection. If a callable
127
     * is passed, the element returned is the first that validates true
128
     *
129
     * @param array    $collection
130
     * @param callable $method
131
     *
132
     * @return mixed
133
     */
134 2
    final public static function firstKey(array $collection, $method = null)
135
    {
136 2
        $filtered = self::filter($collection, $method);
137
138 2
        return array_key_first($filtered);
139
    }
140
141
    /**
142
     * Flattens an array up to the one level depth, unless `$deep` is set to
143
     * `true`
144
     *
145
     * @param array $collection
146
     * @param bool  $deep
147
     *
148
     * @return array
149
     */
150 2
    final public static function flatten(
151
        array $collection,
152
        bool $deep = false
153
    ): array {
154 2
        $data = [];
155
156 2
        foreach ($collection as $item) {
157 2
            if (!is_array($item)) {
158 2
                $data[] = $item;
159
            } else {
160 2
                if ($deep) {
161 1
                    $data = array_merge(
162 1
                        $data,
163 1
                        self::flatten($item, true)
164
                    );
165
                } else {
166 1
                    $data = array_merge(
167 1
                        $data,
168 1
                        array_values($item)
169
                    );
170
                }
171
            }
172
        }
173
174 2
        return $data;
175
    }
176
177
    /**
178
     * Helper method to get an array element or a default
179
     *
180
     * @param array       $collection
181
     * @param mixed       $index
182
     * @param mixed|null  $defaultValue
183
     * @param string|null $cast
184
     *
185
     * @return mixed|null
186
     */
187 528
    final public static function get(
188
        array $collection,
189
        $index,
190
        $defaultValue = null,
191
        string $cast = null
192
    ) {
193 528
        $value = $collection[$index] ?? $defaultValue;
194
195 528
        if (is_string($cast)) {
196 49
            settype($value, $cast);
197
        }
198
199 528
        return $value;
200
    }
201
202
    /**
203
     * Groups the elements of an array based on the passed callable
204
     *
205
     * @param array           $collection
206
     * @param callable|string $method
207
     *
208
     * @return array
209
     */
210 3
    final public static function group(array $collection, $method): array
211
    {
212 3
        $filtered = [];
213 3
        foreach ($collection as $element) {
214
            if (
215 3
                is_callable($method) ||
216 3
                (is_string($method) && function_exists($method))
217
            ) {
218 1
                $key              = call_user_func($method, $element);
219 1
                $filtered[$key][] = $element;
220 2
            } elseif (is_object($element)) {
221 1
                $key              = $element->{$method};
222 1
                $filtered[$key][] = $element;
223 1
            } elseif (isset($element[$method])) {
224 1
                $key              = $element[$method];
225 1
                $filtered[$key][] = $element;
226
            }
227
        }
228
229 3
        return $filtered;
230
    }
231
232
    /**
233
     * Helper method to get an array element or a default
234
     *
235
     * @param array $collection
236
     * @param mixed $index
237
     *
238
     * @return bool
239
     */
240 6
    final public static function has(array $collection, $index): bool
241
    {
242 6
        return array_key_exists($index, $collection);
243
    }
244
245
    /**
246
     * Checks a flat list for duplicate values. Returns true if duplicate
247
     * values exist and false if values are all unique.
248
     *
249
     * @param array $collection
250
     *
251
     * @return bool
252
     */
253 1
    final public static function isUnique(array $collection): bool
254
    {
255 1
        return count($collection) === count(array_unique($collection));
256
    }
257
258
    /**
259
     * Returns the last element of the collection. If a callable is passed, the
260
     * element returned is the first that validates true
261
     *
262
     * @param array         $collection
263
     * @param callable|null $method
264
     *
265
     * @return mixed
266
     */
267 3
    final public static function last(array $collection, $method = null)
268
    {
269 3
        $filtered = self::filter($collection, $method);
270
271 3
        return end($filtered);
272
    }
273
274
    /**
275
     * Returns the key of the last element of the collection. If a callable is
276
     * passed, the element returned is the first that validates true
277
     *
278
     * @param array    $collection
279
     * @param callable $method
280
     *
281
     * @return mixed
282
     */
283 10
    final public static function lastKey(array $collection, $method = null)
284
    {
285 10
        $filtered = self::filter($collection, $method);
286
287 10
        return array_key_last($filtered);
288
    }
289
290
    /**
291
     * Sorts a collection of arrays or objects by key
292
     *
293
     * @param array  $collection
294
     * @param mixed  $attribute
295
     * @param string $order
296
     *
297
     * @return array
298
     */
299 1
    final public static function order(
300
        array $collection,
301
        $attribute,
302
        string $order = 'asc'
303
    ): array {
304 1
        $sorted = [];
305 1
        foreach ($collection as $item) {
306 1
            if (is_object($item)) {
307 1
                $key = $item->{$attribute};
308
            } else {
309 1
                $key = $item[$attribute];
310
            }
311
312 1
            $sorted[$key] = $item;
313
        }
314
315 1
        if ('asc' === $order) {
316 1
            ksort($sorted);
317
        } else {
318 1
            krsort($sorted);
319
        }
320
321 1
        return array_values($sorted);
322
    }
323
324
    /**
325
     * Retrieves all of the values for a given key:
326
     *
327
     * @param array  $collection
328
     * @param string $element
329
     *
330
     * @return array
331
     */
332 2
    final public static function pluck(
333
        array $collection,
334
        string $element
335
    ): array {
336 2
        $filtered = [];
337 2
        foreach ($collection as $item) {
338 2
            if (is_object($item) && isset($item->{$element})) {
339 1
                $filtered[] = $item->{$element};
340 1
            } elseif (is_array($item) && isset($item[$element])) {
341 1
                $filtered[] = $item[$element];
342
            }
343
        }
344
345 2
        return $filtered;
346
    }
347
348
    /**
349
     * Helper method to set an array element
350
     *
351
     * @param array $collection
352
     * @param mixed $value
353
     * @param mixed $index
354
     *
355
     * @return array
356
     */
357 4
    final public static function set(
358
        array $collection,
359
        $value,
360
        $index = null
361
    ): array {
362 4
        if (null === $index) {
363 1
            $collection[] = $value;
364
        } else {
365 3
            $collection[$index] = $value;
366
        }
367
368 4
        return $collection;
369
    }
370
371
    /**
372
     * Returns a new array with n elements removed from the right.
373
     *
374
     * @param array $collection
375
     * @param int   $elements
376
     *
377
     * @return array
378
     */
379 1
    final public static function sliceLeft(
380
        array $collection,
381
        int $elements = 1
382
    ): array {
383 1
        return array_slice($collection, 0, $elements);
384
    }
385
386
    /**
387
     * Returns a new array with the X elements from the right
388
     *
389
     * @param array $collection
390
     * @param int   $elements
391
     *
392
     * @return array
393
     */
394 2
    final public static function sliceRight(
395
        array $collection,
396
        int $elements = 1
397
    ): array {
398 2
        return array_slice($collection, $elements);
399
    }
400
401
    /**
402
     * Returns a new array with keys of the passed array as one element and
403
     * values as another
404
     *
405
     * @param array $collection
406
     *
407
     * @return array
408
     */
409 1
    final public static function split(array $collection): array
410
    {
411
        return [
412 1
            array_keys($collection),
413 1
            array_values($collection),
414
        ];
415
    }
416
417
    /**
418
     * Returns the passed array as an object
419
     *
420
     * @param array $collection
421
     *
422
     * @return object
423
     */
424 2
    final public static function toObject(array $collection)
425
    {
426 2
        return (object) $collection;
427
    }
428
429
    /**
430
     * Returns true if the provided function returns true for all elements of
431
     * the collection, false otherwise.
432
     *
433
     * @param array    $collection
434
     * @param callable $method
435
     *
436
     * @return bool
437
     */
438 1
    final public static function validateAll(array $collection, $method): bool
439
    {
440 1
        return count(self::filter($collection, $method)) === count($collection);
441
    }
442
443
    /**
444
     * Returns true if the provided function returns true for at least one
445
     * element fo the collection, false otherwise.
446
     *
447
     * @param array    $collection
448
     * @param callable $method
449
     *
450
     * @return bool
451
     */
452 1
    final public static function validateAny(array $collection, $method): bool
453
    {
454 1
        return count(self::filter($collection, $method)) > 0;
455
    }
456
457
    /**
458
     * White list filter by key: obtain elements of an array filtering
459
     * by the keys obtained from the elements of a whitelist
460
     *
461
     * @param array $collection
462
     * @param array $whiteList
463
     *
464
     * @return array
465
     */
466 1
    final public static function whiteList(
467
        array $collection,
468
        array $whiteList
469
    ): array {
470
        /**
471
         * Clean whitelist, just strings and integers
472
         */
473 1
        $whiteList = self::filter(
474 1
            $whiteList,
475
            function ($element) {
476 1
                return is_int($element) || is_string($element);
477 1
            }
478
        );
479
480 1
        return array_intersect_key(
481 1
            $collection,
482 1
            array_flip($whiteList)
483
        );
484
    }
485
}
486