Completed
Push — master ( a58449...cb2784 )
by Zeeshan
01:32
created

Arrays::patch()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 20
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 20
ccs 11
cts 11
cp 1
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 10
nc 6
nop 3
crap 5
1
<?php
2
3
namespace __\Traits;
4
5
use __;
6
use Closure;
7
8
trait Arrays
9
{
10
    /**
11
     * Append item to array
12
     *
13
     * @usage __::append([1, 2, 3], 4);
14
     *        >> [1, 2, 3, 4]
15
     *
16
     * @param array $array original array
17
     * @param mixed $value new item or value to append
18
     *
19
     * @return array
20
     */
21 1
    public static function append(array $array = [], $value = null): array
22
    {
23 1
        $array[] = $value;
24
25 1
        return $array;
26
    }
27
28
    /**
29
     * Creates  an  array  with  all  falsey  values removed. The values false, null, 0, "", undefined, and NaN are all
30
     * falsey.
31
     *
32
     * @usage __::compact([0, 1, false, 2, '', 3]);
33
     *        >> [1, 2, 3]
34
     *
35
     * @param array $array array to compact
36
     *
37
     * @return array
38
     */
39 3
    public static function compact(array $array = []): array
40
    {
41 3
        $result = [];
42
43 3
        foreach ($array as $value) {
44 3
            if ($value) {
45 3
                $result[] = $value;
46
            }
47
        }
48
49 3
        return $result;
50
    }
51
52
53
    /**
54
     * base flatten
55
     *
56
     * @param array $array
57
     * @param bool  $shallow
58
     * @param bool  $strict
59
     * @param int   $startIndex
60
     *
61
     * @return array
62
     */
63 1
    public static function baseFlatten(
64
        array $array,
65
        bool $shallow = false,
66
        bool $strict = true,
67
        int $startIndex = 0
0 ignored issues
show
Unused Code introduced by
The parameter $startIndex is not used and could be removed. ( Ignorable by Annotation )

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

67
        /** @scrutinizer ignore-unused */ int $startIndex = 0

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
68
    ): array {
69 1
        $idx    = 0;
70 1
        $output = [];
71
72 1
        foreach ($array as $index => $value) {
73 1
            if (is_array($value)) {
74 1
                if (!$shallow) {
75 1
                    $value = static::baseFlatten($value, $shallow, $strict);
76
                }
77 1
                $j   = 0;
78 1
                $len = count($value);
79 1
                while ($j < $len) {
80 1
                    $output[$idx++] = $value[$j++];
81
                }
82
            } else {
83 1
                if (!$strict) {
84 1
                    $output[$idx++] = $value;
85
                }
86
            }
87
        }
88
89 1
        return $output;
90
    }
91
92
    /**
93
     * Flattens a multidimensional array. If you pass shallow, the array will only be flattened a single level.
94
     *
95
     * @usage __::flatten([1, 2, [3, [4]]], [flatten]);
96
     *        >> [1, 2, 3, 4]
97
     *
98
     * @param array $array
99
     * @param bool  $shallow
100
     *
101
     * @return array
102
     */
103 1
    public static function flatten(array $array, bool $shallow = false): array
104
    {
105 1
        return static::baseFlatten($array, $shallow, false);
106
    }
107
108
    /**
109
     *  Patches array by xpath.
110
     *
111
     * @usage __::patch(
112
     *               ['addr' => ['country' => 'US', 'zip' => 12345]],
113
     *               ['/addr/country' => 'CA','/addr/zip' => 54321]
114
     *           );
115
     **       >> ['addr' => ['country' => 'CA', 'zip' => 54321]]
116
     *
117
     * @param array  $array   The array to patch
118
     * @param array  $patches List of new xpath-value pairs
119
     * @param string $parent
120
     *
121
     * @return array Returns patched array
122
     */
123 1
    public static function patch(array $array, array $patches, string $parent = ''): array
124
    {
125 1
        foreach ($array as $key => $value) {
126 1
            $z = $parent . '/' . $key;
127
128 1
            if (isset($patches[$z])) {
129 1
                $array[$key] = $patches[$z];
130 1
                unset($patches[$z]);
131
132 1
                if (!count($patches)) {
133 1
                    break;
134
                }
135
            }
136
137 1
            if (is_array($value)) {
138 1
                $array[$key] = static::patch($value, $patches, $z);
139
            }
140
        }
141
142 1
        return $array;
143
    }
144
145
    /**
146
     * Prepend item or value to an array
147
     *
148
     * @usage __::prepend([1, 2, 3], 4);
149
     *        >> [4, 1, 2, 3]
150
     *
151
     * @param array $array
152
     * @param mixed $value
153
     *
154
     * @return array
155
     */
156 2
    public static function prepend(array $array = [], $value = null): array
157
    {
158 2
        array_unshift($array, $value);
159
160 2
        return $array;
161
    }
162
163
    /**
164
     * Generate range of values based on start , end and step
165
     *
166
     * @usage __::range(1, 10, 2);
167
     **       >> [1, 3, 5, 7, 9]
168
     *
169
     * @param int|null $start range start
170
     * @param int|null $stop  range end
171
     * @param int      $step  range step value
172
     *
173
     * @return array range of values
174
     */
175 1
    public static function range($start = null, $stop = null, int $step = 1): array
176
    {
177 1
        if ($stop == null && $start != null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $start of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison !== instead.
Loading history...
Bug Best Practice introduced by
It seems like you are loosely comparing $stop of type null|integer against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
178 1
            $stop  = $start;
179 1
            $start = 1;
180
        }
181
182 1
        return range($start, $stop, $step);
183
    }
184
185
    /**
186
     * Generate array of repeated values
187
     *
188
     * @usage __::repeat('foo', 3);
189
     **       >> ['foo', 'foo', 'foo']
190
     *
191
     * @param string $object The object to repeat.
192
     * @param null   $times  ow many times has to be repeated.
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $times is correct as it would always require null to be passed?
Loading history...
193
     *
194
     * @return array Returns a new array of filled values.
195
     *
196
     */
197 1
    public static function repeat(string $object = '', $times = null): array
198
    {
199 1
        $times = abs($times);
200 1
        if ($times == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $times of type integer|double against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
201 1
            return [];
202
        }
203
204 1
        return array_fill(0, $times, $object);
0 ignored issues
show
Bug introduced by
It seems like $times can also be of type double; however, parameter $num of array_fill() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

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

204
        return array_fill(0, /** @scrutinizer ignore-type */ $times, $object);
Loading history...
205
    }
206
207
    /**
208
     * Creates an array of elements split into groups the length of size. If array can't be split evenly, the final
209
     * chunk will be the remaining elements.
210
     *
211
     * @usage __::chunk([1, 2, 3, 4, 5], 3);
212
     *        >> [[1, 2, 3], [4, 5]]
213
     *
214
     * @param array $array          original array
215
     * @param int   $size           the chunk size
216
     * @param bool  $preserveKeys   When set to TRUE keys will be preserved. Default is FALSE which will reindex the
217
     *                              chunk numerically
218
     *
219
     * @return array
220
     */
221 1
    public static function chunk(array $array, int $size = 1, bool $preserveKeys = false): array
222
    {
223 1
        return array_chunk($array, $size, $preserveKeys);
224
    }
225
226
    /**
227
     * Creates a slice of array with n elements dropped from the beginning.
228
     *
229
     * @usage __::drop([0, 1, 3], 2);
230
     *        >> [3]
231
     *
232
     * @param array $input  The array to query.
233
     * @param int   $number The number of elements to drop.
234
     *
235
     * @return array
236
     */
237 1
    public static function drop(array $input, int $number = 1): array
238
    {
239 1
        return array_slice($input, $number);
240
    }
241
242
    /**
243
     * Shuffle an array ensuring no item remains in the same position.
244
     *
245
     * @usage __::randomize([1, 2, 3]);
246
     *        >> [2, 3, 1]
247
     *
248
     * @param array $array original array
249
     *
250
     * @return array
251
     */
252 1
    public static function randomize(array $array): array
253
    {
254 1
        for ($i = 0, $c = count($array); $i < $c - 1; $i++) {
255 1
            $j = rand($i + 1, $c - 1);
256 1
            list($array[$i], $array[$j]) = [$array[$j], $array[$i]];
257
        }
258
259 1
        return $array;
260
    }
261
262
    /**
263
     * Search for the index of a value in an array.
264
     *
265
     * @usage __::search(['a', 'b', 'c'], 'b')
266
     *        >> 1
267
     *
268
     * @param array  $array
269
     * @param string $value
270
     *
271
     * @return mixed
272
     */
273 1
    public static function search(array $array, string $value)
274
    {
275 1
        return array_search($value, $array, true);
276
    }
277
278
    /**
279
     * Check if an item is in an array.
280
     *
281
     * @usage __::contains(['a', 'b', 'c'], 'b')
282
     *        >> true
283
     *
284
     * @param array $array
285
     * @param string $value
286
     *
287
     * @return bool
288
     */
289 1
    public static function contains(array $array, string $value): bool
290
    {
291 1
        return in_array($value, $array, true);
292
    }
293
294
    /**
295
     * Returns the average value of an array.
296
     *
297
     * @usage __::average([1, 2, 3])
298
     *        >> 2
299
     *
300
     * @param array $array    The source array
301
     * @param int   $decimals The number of decimals to return
302
     *
303
     * @return int The average value
304
     */
305 1
    public static function average(array $array, int $decimals = 0): int
306
    {
307 1
        return round((array_sum($array) / count($array)), $decimals);
0 ignored issues
show
Bug Best Practice introduced by
The expression return round(array_sum($...unt($array), $decimals) returns the type double which is incompatible with the type-hinted return integer.
Loading history...
308
    }
309
310
    /**
311
     * Get the size of an array.
312
     *
313
     * @usage __::size([1, 2, 3])
314
     *        >> 3
315
     *
316
     * @param $array
317
     *
318
     * @return int
319
     */
320 1
    public static function size(array $array)
321
    {
322 1
        return count($array);
323
    }
324
325
    /**
326
     * Clean all falsy values from an array.
327
     *
328
     * @usage __::clean([true, false, 0, 1, 'string', ''])
329
     *        >> [true, 1, 'string']
330
     *
331
     * @param array $array
332
     *
333
     * @return mixed
334
     */
335
    public static function clean(array $array)
336
    {
337 1
        return __::filter($array, function ($value) {
338 1
            return (bool) $value;
339 1
        });
340
    }
341
342
    /**
343
     * Get a random string from an array.
344
     *
345
     * @usage __::random([1, 2, 3])
346
     *        >> Returns 1, 2 or 3
347
     *
348
     * @param array $array
349
     * @param null  $take
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $take is correct as it would always require null to be passed?
Loading history...
350
     *
351
     * @return mixed
352
     */
353 1
    public static function random(array $array, $take = null)
354
    {
355 1
        if (!$take) {
356 1
            return $array[array_rand($array)];
357
        }
358
        shuffle($array);
359
360
        return __::first($array, $take);
361
    }
362
363
364
    /**
365
     * Return an array with all elements found in both input arrays.
366
     *
367
     * @usage __::intersection(["green", "red", "blue"], ["green", "yellow", "red"])
368
     *        >> ["green", "red"]
369
     *
370
     * @param array $a
371
     * @param array $b
372
     *
373
     * @return array
374
     */
375 2
    public static function intersection(array $a, array $b): array
376
    {
377 2
        $a = (array) $a;
378 2
        $b = (array) $b;
379
380 2
        return array_values(array_intersect($a, $b));
381
    }
382
383
    /**
384
     * Return a boolean flag which indicates whether the two input arrays have any common elements.
385
     *
386
     * @usage __::intersects(["green", "red", "blue"], ["green", "yellow", "red"])
387
     *        >> true
388
     *
389
     * @param array $a
390
     * @param array $b
391
     *
392
     * @return bool
393
     */
394 1
    public static function intersects(array $a, array $b): bool
395
    {
396 1
        $a = (array) $a;
397 1
        $b = (array) $b;
398
399 1
        return count(self::intersection($a, $b)) > 0;
400
    }
401
402
    /**
403
     * Exclude the last X elements from an array
404
     *
405
     * @usage __::initial([1, 2, 3], 1);
406
     *        >> [1, 2]
407
     *
408
     * @param array $array
409
     * @param int   $to
410
     *
411
     * @return mixed
412
     */
413 1
    public static function initial(array $array, int $to = 1)
414
    {
415 1
        $slice = count($array) - $to;
416
417 1
        return __::first($array, $slice);
418
    }
419
420
    /**
421
     * Exclude the first X elements from an array
422
     *
423
     * @usage __::rest([1, 2, 3], 2);
424
     *        >> [3]
425
     *
426
     * @param array $array
427
     * @param int   $from
428
     *
429
     * @return array
430
     */
431 1
    public static function rest(array $array, int $from = 1): array
432
    {
433 1
        return array_splice($array, $from);
434
    }
435
436
    /**
437
     * Sort an array by key.
438
     *
439
     * @usage __::sortKeys(['z' => 0, 'b' => 1, 'r' => 2])
440
     *        >> ['b' => 1, 'r' => 2, 'z' => 0]
441
     *
442
     * @param array  $array
443
     * @param string $direction
444
     *
445
     * @return mixed
446
     */
447 1
    public static function sortKeys(array $array, string $direction = 'ASC')
448
    {
449 1
        $direction = (strtolower($direction) === 'desc') ? SORT_DESC : SORT_ASC;
450 1
        if ($direction === SORT_ASC) {
451 1
            ksort($array);
452
        } else {
453
            krsort($array);
454
        }
455
456 1
        return $array;
457
    }
458
}
459