Passed
Pull Request — master (#12)
by Misha
03:54 queued 01:55
created

DataMutator::isAssocativeArray()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 1
nc 2
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Communibase\DataBag;
6
7
final class DataMutator
8
{
9
    /**
10
     * @var array<string,array>
11
     */
12
    private $data;
13
14
    /**
15
     * @param mixed $value
16
     */
17
    public function setByPath(array &$data, string $path, $value): void
18
    {
19
        $this->data = &$data;
20
21
        [$entityType, $path] = explode('.', $path, 2);
22
23
        // Direct property
24
        if (strpos($path, '.') === false) {
25
            $data[$entityType][$path] = $value;
26
            return;
27
        }
28
29
        [$path, $index] = explode('.', $path, 2);
30
31
        // Sub-path
32
        if (!is_numeric($index) && strpos($index, '.') === false && !$this->isAssocativeArray($value)) {
33
            $this->data[$entityType][$path][$index] = $value;
34
            return;
35
        }
36
37
        $this->setIndexed($entityType, $path, $index, $value);
38
    }
39
40
    /**
41
     * @param mixed $value
42
     */
43
    private function setIndexed(string $entityType, string $path, string $index, $value): void
44
    {
45
        $field = null;
46
        if (strpos($index, '.') > 0) {
47
            [$index, $field] = explode('.', $index, 2);
48
        }
49
50
        $targetIndex = $index;
51
        if (!is_numeric($targetIndex)) {
52
            if (\is_array($value)) {
53
                $value['type'] = $targetIndex;
54
            }
55
            $targetIndex = null;
56
            if (isset($this->data[$entityType][$path])) {
57
                foreach ((array)$this->data[$entityType][$path] as $nodeIndex => $node) {
58
                    if (isset($node['type']) && $node['type'] === $index) {
59
                        $targetIndex = $nodeIndex;
60
                        break;
61
                    }
62
                }
63
            }
64
        }
65
66
        // No index found, new entry
67
        if ($targetIndex === null) {
68
            $this->addNewEntry($entityType, $path, $field, $index, $value);
69
            return;
70
        }
71
72
        // Use found index
73
        if ($field === null) {
74
            $this->data[$entityType][$path][$targetIndex] = $value;
75
            return;
76
        }
77
        $this->data[$entityType][$path][$targetIndex][$field] = $value;
78
    }
79
80
    /**
81
     * @param mixed $value
82
     */
83
    private function addNewEntry(string $entityType, string $path, ?string $field, string $target, $value): void
84
    {
85
        if ($field === null) {
86
            $this->data[$entityType][$path][] = $value;
87
            return;
88
        }
89
        $value = [
90
            $field => $value
91
        ];
92
        if (!is_numeric($target)) {
93
            $value['type'] = $target;
94
        }
95
        $this->data[$entityType][$path][] = $value;
96
    }
97
98
    /**
99
     * @param mixed $value
100
     */
101
    private function isAssocativeArray($value): bool
102
    {
103
        return \is_array($value) && (array_keys($value) !== range(0, \count($value) - 1));
104
    }
105
}
106