Completed
Push — master ( ff0b8c...0be603 )
by Daniel
30:07 queued 23:25
created

Transform::without()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 10
rs 9.4286
cc 3
eloc 5
nc 3
nop 2
1
<?php
2
namespace Narrowspark\Arr;
3
4
use Narrowspark\Arr\Traits\SplitPathTrait;
5
use Narrowspark\Arr\Traits\ValueTrait;
6
use Closure;
7
8
class Transform
9
{
10
    /**
11
     * Dotted array cache.
12
     *
13
     * @var array
14
     */
15
    protected $dotted = [];
16
17
    /**
18
     * A instance of Access
19
     *
20
     * @var \Narrowspark\Arr\Access
21
     */
22
    protected $access;
23
24
    /**
25
     * A instance of Access
26
     *
27
     * @var \Narrowspark\Arr\Enumerator
28
     */
29
    protected $enumerator;
30
31
    public function __construct()
32
    {
33
        $this->access     = new Access();
34
        $this->enumerator = new Enumerator();
35
    }
36
37
    /**
38
     * Pop value from sub array.
39
     *
40
     * @param array  $array
41
     * @param string $key
42
     *
43
     * @return mixed
44
     */
45
    public static function pop(array $array, $key)
46
    {
47
        $keys = explode('.', $key);
48
49
        foreach ($keys as $key) {
50
            if (!isset($array[$key])) {
51
                return;
52
            }
53
54
            $array = $array[$key];
55
        }
56
57
        if (!is_array($array)) {
58
            return;
59
        }
60
61
        return array_pop($array);
62
    }
63
64
    /**
65
     * Swap two elements between positions.
66
     *
67
     * @param array  $array array to swap
68
     * @param string $swapA
69
     * @param string $swapB
70
     *
71
     * @return array|null
72
     */
73
    public function swap(array $array, $swapA, $swapB)
74
    {
75
        list($array[$swapA], $array[$swapB]) = [$array[$swapB], $array[$swapA]];
76
77
        return $array;
78
    }
79
80
    /**
81
     * Create a new array consisting of every n-th element.
82
     *
83
     * @param array $array
84
     * @param int   $step
85
     * @param int   $offset
86
     *
87
     * @return array
88
     */
89
    public static function every($array, $step, $offset = 0)
90
    {
91
        $new = [];
92
93
        $position = 0;
94
95
        foreach ($array as $key => $item) {
96
            if ($position % $step === $offset) {
97
                $new[] = $item;
98
            }
99
100
            $position++;
101
        }
102
103
        return $new;
104
    }
105
106
    /**
107
     * Indexes an array depending on the values it contains.
108
     *
109
     * @param array    $array
110
     * @param callable $callback  Function to combine values.
111
     * @param bool     $overwrite Should duplicate keys be overwritten?
112
     *
113
     * @return array Indexed values.
114
     */
115
    public function combine(array $array, callable $callback, $overwrite = true)
116
    {
117
        $combined = [];
118
119
        foreach ($array as $key => $value) {
120
            $combinator = call_user_func($callback, $value, $key);
121
            $index      = $combinator->key();
122
123
            if ($overwrite || !isset($combined[$index])) {
124
                $combined[$index] = $combinator->current();
125
            }
126
        }
127
128
        return $combined;
129
    }
130
131
    /**
132
     * Collapse an array of arrays into a single array.
133
     *
134
     * @param array $array
135
     *
136
     * @return array
137
     */
138
    public function collapse(array $array)
139
    {
140
        $results = [];
141
142
        foreach ($array as $values) {
143
            if (!is_array($values)) {
144
                continue;
145
            }
146
147
            $results = array_merge($results, $values);
148
        }
149
150
        return $results;
151
    }
152
153
    /**
154
     * Divide an array into two arrays. One with keys and the other with values.
155
     *
156
     * @param array $array
157
     *
158
     * @return array[]
159
     */
160
    public function divide($array)
161
    {
162
        return [array_keys($array), array_values($array)];
163
    }
164
165
    /**
166
     * Remove duplicated values.
167
     *
168
     * @param array        $elements
169
     * @param Closure|null $iterator
170
     *
171
     * @return array
172
     */
173
    public function unique(array $elements, Closure $iterator = null)
174
    {
175
        if ($iterator !== null) {
176
            $elements = array_filter($elements, $iterator);
177
        } else {
178
            $elements = array_unique($elements);
179
        }
180
181
        return array_values($elements);
182
    }
183
184
    /**
185
     * Remove all instances of $ignore found in $elements (=== is used).
186
     *
187
     * @param array $elements
0 ignored issues
show
Bug introduced by
There is no parameter named $elements. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
188
     * @param array $ignore
189
     * @return array
190
     */
191
    public function without(array $array, array $ignore)
192
    {
193
        foreach ($array as $key => $node) {
194
            if (in_array($node, $ignore, true)) {
195
                unset($array[$key]);
196
            }
197
        }
198
199
        return array_values($array);
200
    }
201
202
    /**
203
     * Reindexes a list of values.
204
     *
205
     * @param array $array
206
     * @param array $map          An map of correspondances of the form
207
     *                            ['currentIndex' => 'newIndex'].
208
     * @param bool  $keepUnmapped Whether or not to keep keys that are not
209
     *                            remapped.
210
     *
211
     * @return array
212
     */
213
    public function reindex(array $array, array $map, $keepUnmapped = true)
214
    {
215
        $reindexed = $keepUnmapped
216
            ? $array
217
            : [];
218
219
        foreach ($map as $from => $to) {
220
            if (isset($array[$from])) {
221
                $reindexed[$to] = $array[$from];
222
            }
223
        }
224
225
        return $reindexed;
226
    }
227
228
    /**
229
     * Merges two arrays recursively.
230
     *
231
     * @param array $first  Original data.
232
     * @param array $second Data to be merged.
233
     *
234
     * @return array
235
     */
236
    public function merge(array $first, array $second)
237
    {
238
        foreach ($second as $key => $value) {
239
            $shouldBeMerged = (
240
                isset($first[$key])
241
                && is_array($first[$key])
242
                && is_array($value)
243
            );
244
245
            $first[$key] = $shouldBeMerged
246
                ? $this->merge($first[$key], $value)
247
                : $value;
248
        }
249
250
        return $first;
251
    }
252
253
    /**
254
     * Extend one array with another.
255
     *
256
     * @param array $arrays
257
     *
258
     * @return array
259
     */
260
    public function extend(array $arrays)
261
    {
262
        $merged = [];
263
264
        foreach (func_get_args() as $array) {
265
            foreach ($array as $key => $value) {
266
                if (is_array($value) && $this->access->has($merged, $key) && is_array($merged[$key])) {
267
                    $merged[$key] = $this->extend($merged[$key], $value);
268
                } else {
269
                    $merged[$key] = $value;
270
                }
271
            }
272
        }
273
274
        return $merged;
275
    }
276
277
    /**
278
     * Transforms a 1-dimensional array into a multi-dimensional one,
279
     * exploding keys according to a separator.
280
     *
281
     * @param array $array
282
     *
283
     * @return array
284
     */
285
    public function asHierarchy(array $array)
286
    {
287
        $hierarchy = [];
288
289
        foreach ($array as $key => $value) {
290
            $segments     = explode('.', $key);
291
            $valueSegment = array_pop($segments);
292
            $branch       = &$hierarchy;
293
294
            foreach ($segments as $segment) {
295
                if (!isset($branch[$segment])) {
296
                    $branch[$segment] = [];
297
                }
298
299
                $branch = &$branch[$segment];
300
            }
301
302
            $branch[$valueSegment] = $value;
303
        }
304
305
        return $hierarchy;
306
    }
307
308
    /**
309
     * Separates elements from an array into groups.
310
     * The function maps an element to the key that will be used for grouping.
311
     * If no function is passed, the element itself will be used as key.
312
     *
313
     * @param array         $array
314
     * @param callable|null $callback
315
     *
316
     * @return array
317
     */
318
    public function groupBy(array $array, callable $callback = null)
319
    {
320
        $callback = $callback ?: function ($value) {
321
            return $value;
322
        };
323
324
        return array_reduce(
325
            $array,
326
            function ($buckets, $value) use ($callback) {
327
                $key = call_user_func($callback, $value);
328
329
                if (!array_key_exists($key, $buckets)) {
330
                    $buckets[$key] = [];
331
                }
332
333
                $buckets[$key][] = $value;
334
335
                return $buckets;
336
            },
337
            []
338
        );
339
    }
340
341
    /**
342
     * Flatten a multi-dimensional associative array with dots.
343
     *
344
     * @param array  $array
345
     * @param string $prepend
346
     *
347
     * @return array
348
     */
349
    public function dot($array, $prepend = '')
350
    {
351
        $cache = serialize(['array' => $array, 'prepend' => $prepend]);
352
353
        if (array_key_exists($cache, $this->dotted)) {
354
            return $this->dotted[$cache];
355
        }
356
357
        $results = [];
358
359 View Code Duplication
        foreach ($array as $key => $value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
360
            if (is_array($value)) {
361
                $results = array_merge($results, $this->dot($value, $prepend . $key . '.'));
362
            } else {
363
                $results[$prepend . $key] = $value;
364
            }
365
        }
366
367
        return $this->dotted[$cache] = $results;
368
    }
369
370
    /**
371
     * Flatten a nested array to a separated key.
372
     *
373
     * @param array       $array
374
     * @param string|null $separator
375
     * @param string      $prepend
376
     *
377
     * @return array
378
     */
379
    public function flatten(array $array, $separator = null, $prepend = '')
380
    {
381
        $flattened = [];
382
383 View Code Duplication
        foreach ($array as $key => $value) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
384
            if (is_array($value)) {
385
                $flattened = array_merge($flattened, $this->flatten($value, $separator, $prepend . $key . $separator));
386
            } else {
387
                $flattened[$prepend . $key] = $value;
388
            }
389
        }
390
391
        return $flattened;
392
    }
393
394
    /**
395
     * Expand a flattened array with dots to a multi-dimensional associative array.
396
     *
397
     * @param array  $array
398
     * @param string $prepend
399
     *
400
     * @return array
401
     */
402
    public function expand(array $array, $prepend = '')
403
    {
404
        $results = [];
405
406
        if ($prepend) {
407
            $prepend .= '.';
408
        }
409
410
        foreach ($array as $key => $value) {
411
            if ($prepend) {
412
                $pos = strpos($key, $prepend);
413
414
                if ($pos === 0) {
415
                    $key = substr($key, strlen($prepend));
416
                }
417
            }
418
419
            $results = $this->access->set($results, $key, $value);
420
        }
421
422
        return $results;
423
    }
424
425
    /**
426
     * Reset all numerical indexes of an array (start from zero).
427
     * Non-numerical indexes will stay untouched. Returns a new array.
428
     *
429
     * @param array      $array
430
     * @param bool|false $deep
431
     *
432
     * @return array
433
     */
434
    public function reset(array $array, $deep = false)
435
    {
436
        $target = [];
437
438
        foreach ($array as $key => $value) {
439
            if ($deep && is_array($value)) {
440
                $value = $this->reset($value);
441
            }
442
443
            if (is_numeric($key)) {
444
                $target[] = $value;
445
            } else {
446
                $target[$key] = $value;
447
            }
448
        }
449
450
        return $target;
451
    }
452
453
    /**
454
     * Extend one array with another. Non associative arrays will not be merged
455
     * but rather replaced.
456
     *
457
     * @param array $arrays
458
     *
459
     * @return array
460
     */
461
    public function extendDistinct(array $arrays)
0 ignored issues
show
Unused Code introduced by
The parameter $arrays is not used and could be removed.

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

Loading history...
462
    {
463
        $merged     = [];
464
465
        foreach (func_get_args() as $array) {
466
            foreach ($array as $key => $value) {
467
                if (is_array($value) && $this->access->has($merged, $key) && is_array($merged[$key])) {
468
                    if ($this->enumerator->isAssoc($value) && $this->enumerator->isAssoc($merged[$key])) {
469
                        $merged[$key] = $this->extendDistinct($merged[$key], $value);
470
471
                        continue;
472
                    }
473
                }
474
475
                $merged[$key] = $value;
476
            }
477
        }
478
479
        return $merged;
480
    }
481
482
    /**
483
     * Recursively sort an array by keys and values.
484
     *
485
     * @param array $array
486
     *
487
     * @return array
488
     */
489
    public function sortRecursive(array $array)
490
    {
491
        foreach ($array as &$value) {
492
            if (is_array($value)) {
493
                $value = $this->sortRecursive($value);
494
            }
495
        }
496
497
        // sort associative array
498
        if ($this->enumerator->isAssoc($array)) {
499
            ksort($array);
500
            // sort regular array
501
        } else {
502
            sort($array);
503
        }
504
505
        return $array;
506
    }
507
508
    /**
509
     * Will turn each element in $arr into an array then appending
510
     * the associated indexs from the other arrays into this array as well.
511
     *
512
     * @param array $array
513
     * @param array $arrays
514
     *
515
     * @return array
516
     */
517
    public function zip(array $array, array $arrays)
0 ignored issues
show
Unused Code introduced by
The parameter $arrays is not used and could be removed.

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

Loading history...
518
    {
519
        $args = func_get_args();
520
        array_shift($args);
521
522
        foreach ($array as $key => $value) {
523
            $array[$key] = [$value];
524
525
            foreach ($args as $k => $v) {
526
                $array[$key][] = current($args[$k]);
527
528
                if (next($args[$k]) === false && $args[$k] !== [null]) {
529
                    $args[$k] = [null];
530
                }
531
            }
532
        }
533
534
        return $array;
535
    }
536
}
537