Completed
Push — master ( 8e43ca...5e65e1 )
by Daniel
08:47
created

Transform::stripEmpty()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 16
rs 9.4286
cc 3
eloc 8
nc 1
nop 1
1
<?php
2
namespace Narrowspark\Arr;
3
4
use Closure;
5
use Narrowspark\Arr\Traits\SplitPathTrait;
6
use Narrowspark\Arr\Traits\ValueTrait;
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
     * Stripe all empty items.
167
     *
168
     * @param array $source
0 ignored issues
show
Bug introduced by
There is no parameter named $source. 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...
169
     *
170
     * @return array
171
     */
172
    public function stripEmpty(array $array)
173
    {
174
        return array_filter($array, function ($item) {
175
            if (is_null($item)) {
176
                return false;
177
            }
178
179
            $item = trim($item);
180
181
            if (!$item) {
0 ignored issues
show
Unused Code introduced by
This if statement, and the following return statement can be replaced with return (bool) $item;.
Loading history...
182
                return false;
183
            }
184
185
            return true;
186
        });
187
    }
188
189
    /**
190
     * Remove duplicated values.
191
     *
192
     * @param array        $elements
193
     * @param Closure|null $iterator
194
     *
195
     * @return array
196
     */
197
    public function unique(array $elements, Closure $iterator = null)
198
    {
199
        if ($iterator !== null) {
200
            $elements = array_filter($elements, $iterator);
201
        } else {
202
            $elements = array_unique($elements);
203
        }
204
205
        return array_values($elements);
206
    }
207
208
    /**
209
     * Remove all instances of $ignore found in $elements (=== is used).
210
     *
211
     * @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...
212
     * @param array $ignore
213
     *
214
     * @return array
215
     */
216
    public function without(array $array, array $ignore)
217
    {
218
        foreach ($array as $key => $node) {
219
            if (in_array($node, $ignore, true)) {
220
                unset($array[$key]);
221
            }
222
        }
223
224
        return array_values($array);
225
    }
226
227
    /**
228
     * Reindexes a list of values.
229
     *
230
     * @param array $array
231
     * @param array $map          An map of correspondances of the form
232
     *                            ['currentIndex' => 'newIndex'].
233
     * @param bool  $keepUnmapped Whether or not to keep keys that are not
234
     *                            remapped.
235
     *
236
     * @return array
237
     */
238
    public function reindex(array $array, array $map, $keepUnmapped = true)
239
    {
240
        $reindexed = $keepUnmapped
241
            ? $array
242
            : [];
243
244
        foreach ($map as $from => $to) {
245
            if (isset($array[$from])) {
246
                $reindexed[$to] = $array[$from];
247
            }
248
        }
249
250
        return $reindexed;
251
    }
252
253
    /**
254
     * Merges two arrays recursively.
255
     *
256
     * @param array $first  Original data.
257
     * @param array $second Data to be merged.
258
     *
259
     * @return array
260
     */
261
    public function merge(array $first, array $second)
262
    {
263
        foreach ($second as $key => $value) {
264
            $shouldBeMerged = (
265
                isset($first[$key])
266
                && is_array($first[$key])
267
                && is_array($value)
268
            );
269
270
            $first[$key] = $shouldBeMerged
271
                ? $this->merge($first[$key], $value)
272
                : $value;
273
        }
274
275
        return $first;
276
    }
277
278
    /**
279
     * Extend one array with another.
280
     *
281
     * @param array $arrays
282
     *
283
     * @return array
284
     */
285
    public function extend(array $arrays)
286
    {
287
        $merged = [];
288
289
        foreach (func_get_args() as $array) {
290
            foreach ($array as $key => $value) {
291
                if (is_array($value) && $this->access->has($merged, $key) && is_array($merged[$key])) {
292
                    $merged[$key] = $this->extend($merged[$key], $value);
293
                } else {
294
                    $merged[$key] = $value;
295
                }
296
            }
297
        }
298
299
        return $merged;
300
    }
301
302
    /**
303
     * Transforms a 1-dimensional array into a multi-dimensional one,
304
     * exploding keys according to a separator.
305
     *
306
     * @param array $array
307
     *
308
     * @return array
309
     */
310
    public function asHierarchy(array $array)
311
    {
312
        $hierarchy = [];
313
314
        foreach ($array as $key => $value) {
315
            $segments     = explode('.', $key);
316
            $valueSegment = array_pop($segments);
317
            $branch       = &$hierarchy;
318
319
            foreach ($segments as $segment) {
320
                if (!isset($branch[$segment])) {
321
                    $branch[$segment] = [];
322
                }
323
324
                $branch = &$branch[$segment];
325
            }
326
327
            $branch[$valueSegment] = $value;
328
        }
329
330
        return $hierarchy;
331
    }
332
333
    /**
334
     * Separates elements from an array into groups.
335
     * The function maps an element to the key that will be used for grouping.
336
     * If no function is passed, the element itself will be used as key.
337
     *
338
     * @param array         $array
339
     * @param callable|null $callback
340
     *
341
     * @return array
342
     */
343
    public function groupBy(array $array, callable $callback = null)
344
    {
345
        $callback = $callback ?: function ($value) {
346
            return $value;
347
        };
348
349
        return array_reduce(
350
            $array,
351
            function ($buckets, $value) use ($callback) {
352
                $key = call_user_func($callback, $value);
353
354
                if (!array_key_exists($key, $buckets)) {
355
                    $buckets[$key] = [];
356
                }
357
358
                $buckets[$key][] = $value;
359
360
                return $buckets;
361
            },
362
            []
363
        );
364
    }
365
366
    /**
367
     * Flatten a multi-dimensional associative array with dots.
368
     *
369
     * @param array  $array
370
     * @param string $prepend
371
     *
372
     * @return array
373
     */
374
    public function dot($array, $prepend = '')
375
    {
376
        $cache = serialize(['array' => $array, 'prepend' => $prepend]);
377
378
        if (array_key_exists($cache, $this->dotted)) {
379
            return $this->dotted[$cache];
380
        }
381
382
        $results = [];
383
384 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...
385
            if (is_array($value)) {
386
                $results = array_merge($results, $this->dot($value, $prepend . $key . '.'));
387
            } else {
388
                $results[$prepend . $key] = $value;
389
            }
390
        }
391
392
        return $this->dotted[$cache] = $results;
393
    }
394
395
    /**
396
     * Flatten a nested array to a separated key.
397
     *
398
     * @param array       $array
399
     * @param string|null $separator
400
     * @param string      $prepend
401
     *
402
     * @return array
403
     */
404
    public function flatten(array $array, $separator = null, $prepend = '')
405
    {
406
        $flattened = [];
407
408 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...
409
            if (is_array($value)) {
410
                $flattened = array_merge($flattened, $this->flatten($value, $separator, $prepend . $key . $separator));
411
            } else {
412
                $flattened[$prepend . $key] = $value;
413
            }
414
        }
415
416
        return $flattened;
417
    }
418
419
    /**
420
     * Expand a flattened array with dots to a multi-dimensional associative array.
421
     *
422
     * @param array  $array
423
     * @param string $prepend
424
     *
425
     * @return array
426
     */
427
    public function expand(array $array, $prepend = '')
428
    {
429
        $results = [];
430
431
        if ($prepend) {
432
            $prepend .= '.';
433
        }
434
435
        foreach ($array as $key => $value) {
436
            if ($prepend) {
437
                $pos = strpos($key, $prepend);
438
439
                if ($pos === 0) {
440
                    $key = substr($key, strlen($prepend));
441
                }
442
            }
443
444
            $results = $this->access->set($results, $key, $value);
445
        }
446
447
        return $results;
448
    }
449
450
    /**
451
     * Reset all numerical indexes of an array (start from zero).
452
     * Non-numerical indexes will stay untouched. Returns a new array.
453
     *
454
     * @param array      $array
455
     * @param bool|false $deep
456
     *
457
     * @return array
458
     */
459
    public function reset(array $array, $deep = false)
460
    {
461
        $target = [];
462
463
        foreach ($array as $key => $value) {
464
            if ($deep && is_array($value)) {
465
                $value = $this->reset($value);
466
            }
467
468
            if (is_numeric($key)) {
469
                $target[] = $value;
470
            } else {
471
                $target[$key] = $value;
472
            }
473
        }
474
475
        return $target;
476
    }
477
478
    /**
479
     * Extend one array with another. Non associative arrays will not be merged
480
     * but rather replaced.
481
     *
482
     * @param array $arrays
483
     *
484
     * @return array
485
     */
486
    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...
487
    {
488
        $merged     = [];
489
490
        foreach (func_get_args() as $array) {
491
            foreach ($array as $key => $value) {
492
                if (is_array($value) && $this->access->has($merged, $key) && is_array($merged[$key])) {
493
                    if ($this->enumerator->isAssoc($value) && $this->enumerator->isAssoc($merged[$key])) {
494
                        $merged[$key] = $this->extendDistinct($merged[$key], $value);
495
496
                        continue;
497
                    }
498
                }
499
500
                $merged[$key] = $value;
501
            }
502
        }
503
504
        return $merged;
505
    }
506
507
    /**
508
     * Recursively sort an array by keys and values.
509
     *
510
     * @param array $array
511
     *
512
     * @return array
513
     */
514
    public function sortRecursive(array $array)
515
    {
516
        foreach ($array as &$value) {
517
            if (is_array($value)) {
518
                $value = $this->sortRecursive($value);
519
            }
520
        }
521
522
        // sort associative array
523
        if ($this->enumerator->isAssoc($array)) {
524
            ksort($array);
525
            // sort regular array
526
        } else {
527
            sort($array);
528
        }
529
530
        return $array;
531
    }
532
533
    /**
534
     * Will turn each element in $arr into an array then appending
535
     * the associated indexs from the other arrays into this array as well.
536
     *
537
     * @param array $array
538
     * @param array $arrays
539
     *
540
     * @return array
541
     */
542
    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...
543
    {
544
        $args = func_get_args();
545
        array_shift($args);
546
547
        foreach ($array as $key => $value) {
548
            $array[$key] = [$value];
549
550
            foreach ($args as $k => $v) {
551
                $array[$key][] = current($args[$k]);
552
553
                if (next($args[$k]) === false && $args[$k] !== [null]) {
554
                    $args[$k] = [null];
555
                }
556
            }
557
        }
558
559
        return $array;
560
    }
561
}
562