Passed
Pull Request — master (#62)
by Sergei
12:01
created

ArrayCollectionHelper::merge()   B

Complexity

Conditions 7
Paths 21

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 12
c 1
b 0
f 0
dl 0
loc 21
rs 8.8333
cc 7
nc 21
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Arrays\Collection;
6
7
use InvalidArgumentException;
8
use Yiisoft\Arrays\Collection\Modifier\BeforeMergeModifierInterface;
9
10
final class ArrayCollectionHelper
11
{
12
    public static function merge(...$args): ArrayCollection
13
    {
14
        $arrays = [];
15
        foreach ($args as $arg) {
16
            $arrays[] = $arg instanceof ArrayCollection ? $arg->getData() : $arg;
17
        }
18
19
        $collections = [];
20
        foreach ($args as $arg) {
21
            $collection = $arg instanceof ArrayCollection ? $arg : new ArrayCollection($arg);
22
            foreach ($collection->getModifiers() as $modifier) {
23
                if ($modifier instanceof BeforeMergeModifierInterface) {
24
                    $collection->setData(
25
                        $modifier->beforeMerge($arg->getData(), $arrays)
26
                    );
27
                }
28
            }
29
            $collections[] = $collection;
30
        }
31
32
        return static::mergeBase(...$args);
33
    }
34
35
    private static function mergeBase(...$args): ArrayCollection
36
    {
37
        $collection = new ArrayCollection();
38
39
        while (!empty($args)) {
40
            $array = array_shift($args);
41
42
            if ($array instanceof ArrayCollection) {
43
                $collection->pullCollectionArgs($array);
44
                $collection->setData(
45
                    static::mergeBase($collection->getData(), $array->getData())->getData()
46
                );
47
                continue;
48
            } elseif (!is_array($array)) {
49
                throw new InvalidArgumentException();
50
            }
51
52
            foreach ($array as $k => $v) {
53
                if (is_int($k)) {
54
                    if ($collection->keyExists($k)) {
55
                        if ($collection[$k] !== $v) {
56
                            $collection[] = $v;
57
                        }
58
                    } else {
59
                        $collection[$k] = $v;
60
                    }
61
                } elseif (static::isMergable($v) && isset($collection[$k]) && static::isMergable($collection[$k])) {
62
                    $collection[$k] = static::mergeBase($collection[$k], $v)->getData();
63
                } else {
64
                    $collection[$k] = $v;
65
                }
66
            }
67
        }
68
69
        return $collection;
70
    }
71
72
    private static function isMergable($value): bool
73
    {
74
        return is_array($value) || $value instanceof ArrayCollection;
75
    }
76
}
77