Arr   F
last analyzed

Complexity

Total Complexity 61

Size/Duplication

Total Lines 448
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 115
c 1
b 0
f 0
dl 0
loc 448
rs 3.52
wmc 61

20 Methods

Rating   Name   Duplication   Size   Complexity  
A dot() 0 13 4
A only() 0 3 1
A flatten() 0 13 4
A last() 0 7 3
A random() 0 15 3
A divide() 0 3 1
A exists() 0 3 1
A where() 0 3 1
A isAssoc() 0 5 1
A wrap() 0 3 2
A add() 0 7 2
A first() 0 19 6
A prepend() 0 9 2
B has() 0 33 8
A set() 0 20 4
A pull() 0 7 1
A crossJoin() 0 19 4
A get() 0 19 5
B forget() 0 34 7
A except() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Arr often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Arr, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Freyo\ApiGateway\Kernel\Support;
4
5
/**
6
 * Array helper from Illuminate\Support\Arr.
7
 */
8
class Arr
9
{
10
    /**
11
     * Add an element to an array using "dot" notation if it doesn't exist.
12
     *
13
     * @param array  $array
14
     * @param string $key
15
     * @param mixed  $value
16
     *
17
     * @return array
18
     */
19
    public static function add(array $array, $key, $value)
20
    {
21
        if (is_null(static::get($array, $key))) {
22
            static::set($array, $key, $value);
23
        }
24
25
        return $array;
26
    }
27
28
    /**
29
     * Cross join the given arrays, returning all possible permutations.
30
     *
31
     * @param array ...$arrays
32
     *
33
     * @return array
34
     */
35
    public static function crossJoin(...$arrays)
36
    {
37
        $results = [[]];
38
39
        foreach ($arrays as $index => $array) {
40
            $append = [];
41
42
            foreach ($results as $product) {
43
                foreach ($array as $item) {
44
                    $product[$index] = $item;
45
46
                    $append[] = $product;
47
                }
48
            }
49
50
            $results = $append;
51
        }
52
53
        return $results;
54
    }
55
56
    /**
57
     * Divide an array into two arrays. One with keys and the other with values.
58
     *
59
     * @param array $array
60
     *
61
     * @return array
62
     */
63
    public static function divide(array $array)
64
    {
65
        return [array_keys($array), array_values($array)];
66
    }
67
68
    /**
69
     * Flatten a multi-dimensional associative array with dots.
70
     *
71
     * @param array  $array
72
     * @param string $prepend
73
     *
74
     * @return array
75
     */
76
    public static function dot(array $array, $prepend = '')
77
    {
78
        $results = [];
79
80
        foreach ($array as $key => $value) {
81
            if (is_array($value) && !empty($value)) {
82
                $results = array_merge($results, static::dot($value, $prepend.$key.'.'));
83
            } else {
84
                $results[$prepend.$key] = $value;
85
            }
86
        }
87
88
        return $results;
89
    }
90
91
    /**
92
     * Get all of the given array except for a specified array of items.
93
     *
94
     * @param array        $array
95
     * @param array|string $keys
96
     *
97
     * @return array
98
     */
99
    public static function except(array $array, $keys)
100
    {
101
        static::forget($array, $keys);
102
103
        return $array;
104
    }
105
106
    /**
107
     * Determine if the given key exists in the provided array.
108
     *
109
     * @param \ArrayAccess|array $array
110
     * @param string|int         $key
111
     *
112
     * @return bool
113
     */
114
    public static function exists(array $array, $key)
115
    {
116
        return array_key_exists($key, $array);
117
    }
118
119
    /**
120
     * Return the first element in an array passing a given truth test.
121
     *
122
     * @param array         $array
123
     * @param callable|null $callback
124
     * @param mixed         $default
125
     *
126
     * @return mixed
127
     */
128
    public static function first(array $array, callable $callback = null, $default = null)
129
    {
130
        if (is_null($callback)) {
131
            if (empty($array)) {
132
                return $default;
133
            }
134
135
            foreach ($array as $item) {
136
                return $item;
137
            }
138
        }
139
140
        foreach ($array as $key => $value) {
141
            if (call_user_func($callback, $value, $key)) {
142
                return $value;
143
            }
144
        }
145
146
        return $default;
147
    }
148
149
    /**
150
     * Return the last element in an array passing a given truth test.
151
     *
152
     * @param array         $array
153
     * @param callable|null $callback
154
     * @param mixed         $default
155
     *
156
     * @return mixed
157
     */
158
    public static function last(array $array, callable $callback = null, $default = null)
159
    {
160
        if (is_null($callback)) {
161
            return empty($array) ? $default : end($array);
162
        }
163
164
        return static::first(array_reverse($array, true), $callback, $default);
165
    }
166
167
    /**
168
     * Flatten a multi-dimensional array into a single level.
169
     *
170
     * @param array $array
171
     * @param int   $depth
172
     *
173
     * @return array
174
     */
175
    public static function flatten(array $array, $depth = INF)
176
    {
177
        return array_reduce($array, function ($result, $item) use ($depth) {
178
            $item = $item instanceof Collection ? $item->all() : $item;
179
180
            if (!is_array($item)) {
181
                return array_merge($result, [$item]);
182
            } elseif (1 === $depth) {
183
                return array_merge($result, array_values($item));
184
            }
185
186
            return array_merge($result, static::flatten($item, $depth - 1));
0 ignored issues
show
Bug introduced by
$depth - 1 of type double is incompatible with the type integer expected by parameter $depth of Freyo\ApiGateway\Kernel\Support\Arr::flatten(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

186
            return array_merge($result, static::flatten($item, /** @scrutinizer ignore-type */ $depth - 1));
Loading history...
187
        }, []);
188
    }
189
190
    /**
191
     * Remove one or many array items from a given array using "dot" notation.
192
     *
193
     * @param array        $array
194
     * @param array|string $keys
195
     */
196
    public static function forget(array &$array, $keys)
197
    {
198
        $original = &$array;
199
200
        $keys = (array) $keys;
201
202
        if (0 === count($keys)) {
203
            return;
204
        }
205
206
        foreach ($keys as $key) {
207
            // if the exact key exists in the top-level, remove it
208
            if (static::exists($array, $key)) {
209
                unset($array[$key]);
210
211
                continue;
212
            }
213
214
            $parts = explode('.', $key);
215
216
            // clean up before each pass
217
            $array = &$original;
218
219
            while (count($parts) > 1) {
220
                $part = array_shift($parts);
221
222
                if (isset($array[$part]) && is_array($array[$part])) {
223
                    $array = &$array[$part];
224
                } else {
225
                    continue 2;
226
                }
227
            }
228
229
            unset($array[array_shift($parts)]);
230
        }
231
    }
232
233
    /**
234
     * Get an item from an array using "dot" notation.
235
     *
236
     * @param \ArrayAccess|array $array
237
     * @param string             $key
238
     * @param mixed              $default
239
     *
240
     * @return mixed
241
     */
242
    public static function get(array $array, $key, $default = null)
243
    {
244
        if (is_null($key)) {
0 ignored issues
show
introduced by
The condition is_null($key) is always false.
Loading history...
245
            return $array;
246
        }
247
248
        if (static::exists($array, $key)) {
249
            return $array[$key];
250
        }
251
252
        foreach (explode('.', $key) as $segment) {
253
            if (static::exists($array, $segment)) {
254
                $array = $array[$segment];
255
            } else {
256
                return $default;
257
            }
258
        }
259
260
        return $array;
261
    }
262
263
    /**
264
     * Check if an item or items exist in an array using "dot" notation.
265
     *
266
     * @param \ArrayAccess|array $array
267
     * @param string|array       $keys
268
     *
269
     * @return bool
270
     */
271
    public static function has(array $array, $keys)
272
    {
273
        if (is_null($keys)) {
0 ignored issues
show
introduced by
The condition is_null($keys) is always false.
Loading history...
274
            return false;
275
        }
276
277
        $keys = (array) $keys;
278
279
        if (empty($array)) {
280
            return false;
281
        }
282
283
        if ($keys === []) {
284
            return false;
285
        }
286
287
        foreach ($keys as $key) {
288
            $subKeyArray = $array;
289
290
            if (static::exists($array, $key)) {
291
                continue;
292
            }
293
294
            foreach (explode('.', $key) as $segment) {
295
                if (static::exists($subKeyArray, $segment)) {
296
                    $subKeyArray = $subKeyArray[$segment];
297
                } else {
298
                    return false;
299
                }
300
            }
301
        }
302
303
        return true;
304
    }
305
306
    /**
307
     * Determines if an array is associative.
308
     *
309
     * An array is "associative" if it doesn't have sequential numerical keys beginning with zero.
310
     *
311
     * @param array $array
312
     *
313
     * @return bool
314
     */
315
    public static function isAssoc(array $array)
316
    {
317
        $keys = array_keys($array);
318
319
        return array_keys($keys) !== $keys;
320
    }
321
322
    /**
323
     * Get a subset of the items from the given array.
324
     *
325
     * @param array        $array
326
     * @param array|string $keys
327
     *
328
     * @return array
329
     */
330
    public static function only(array $array, $keys)
331
    {
332
        return array_intersect_key($array, array_flip((array) $keys));
333
    }
334
335
    /**
336
     * Push an item onto the beginning of an array.
337
     *
338
     * @param array $array
339
     * @param mixed $value
340
     * @param mixed $key
341
     *
342
     * @return array
343
     */
344
    public static function prepend(array $array, $value, $key = null)
345
    {
346
        if (is_null($key)) {
347
            array_unshift($array, $value);
348
        } else {
349
            $array = [$key => $value] + $array;
350
        }
351
352
        return $array;
353
    }
354
355
    /**
356
     * Get a value from the array, and remove it.
357
     *
358
     * @param array  $array
359
     * @param string $key
360
     * @param mixed  $default
361
     *
362
     * @return mixed
363
     */
364
    public static function pull(array &$array, $key, $default = null)
365
    {
366
        $value = static::get($array, $key, $default);
367
368
        static::forget($array, $key);
369
370
        return $value;
371
    }
372
373
    /**
374
     * Get a 1 value from an array.
375
     *
376
     * @param array    $array
377
     * @param int|null $amount
378
     *
379
     * @return mixed
380
     *
381
     * @throws \InvalidArgumentException
382
     */
383
    public static function random(array $array, int $amount = null)
384
    {
385
        if (is_null($amount)) {
386
            return $array[array_rand($array)];
387
        }
388
389
        $keys = array_rand($array, $amount);
390
391
        $results = [];
392
393
        foreach ((array) $keys as $key) {
394
            $results[] = $array[$key];
395
        }
396
397
        return $results;
398
    }
399
400
    /**
401
     * Set an array item to a given value using "dot" notation.
402
     *
403
     * If no key is given to the method, the entire array will be replaced.
404
     *
405
     * @param array  $array
406
     * @param string $key
407
     * @param mixed  $value
408
     *
409
     * @return array
410
     */
411
    public static function set(array &$array, string $key, $value)
412
    {
413
        $keys = explode('.', $key);
414
415
        while (count($keys) > 1) {
416
            $key = array_shift($keys);
417
418
            // If the key doesn't exist at this depth, we will just create an empty array
419
            // to hold the next value, allowing us to create the arrays to hold final
420
            // values at the correct depth. Then we'll keep digging into the array.
421
            if (!isset($array[$key]) || !is_array($array[$key])) {
422
                $array[$key] = [];
423
            }
424
425
            $array = &$array[$key];
426
        }
427
428
        $array[array_shift($keys)] = $value;
429
430
        return $array;
431
    }
432
433
    /**
434
     * Filter the array using the given callback.
435
     *
436
     * @param array    $array
437
     * @param callable $callback
438
     *
439
     * @return array
440
     */
441
    public static function where(array $array, callable $callback)
442
    {
443
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
444
    }
445
446
    /**
447
     * If the given value is not an array, wrap it in one.
448
     *
449
     * @param mixed $value
450
     *
451
     * @return array
452
     */
453
    public static function wrap($value)
454
    {
455
        return !is_array($value) ? [$value] : $value;
456
    }
457
}
458