Passed
Pull Request — master (#12)
by Misha
06:35 queued 03:22
created

DataRemover::removeByPath()   B

Complexity

Conditions 7
Paths 5

Size

Total Lines 29
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 14
nc 5
nop 2
dl 0
loc 29
rs 8.8333
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Communibase\DataBag;
6
7
final class DataRemover
8
{
9
    /**
10
     * @var array<string,array>
11
     */
12
    private $data;
13
14
    /**
15
     * Remove a property from the bag.
16
     *
17
     * @param string $path path to the target (see get() for examples)
18
     *
19
     * @throws InvalidDataBagPathException
20
     */
21
    public function removeByPath(array &$data, string $path): void
22
    {
23
        $this->data = &$data;
24
25
        [$entityType, $path] = explode('.', $path, 2);
26
27
        // Direct property
28
        if (strpos($path, '.') === false) {
29
            if (!isset($this->data[$entityType][$path])) {
30
                return;
31
            }
32
            $data[$entityType][$path] = null;
33
            return;
34
        }
35
36
        [$path, $index] = explode('.', $path);
37
38
        // Target doesn't exist, nothing to remove
39
        if (empty($this->data[$entityType][$path])) {
40
            return;
41
        }
42
43
        // Sub-path
44
        if (isset($this->data[$entityType][$path][$index]) && !is_numeric($index) && strpos($index, '.') === false) {
45
            $this->data[$entityType][$path][$index] = null;
46
            return;
47
        }
48
49
        $this->removeIndexed($entityType, $path, $index);
50
    }
51
52
    private function removeIndexed(string $entityType, string $path, string $index): void
53
    {
54
        if (is_numeric($index)) {
55
            // Remove all (higher) values to prevent a new value after re-indexing
56
            if ((int)$index === 0) {
57
                $this->data[$entityType][$path] = null;
58
                return;
59
            }
60
            $this->data[$entityType][$path] = \array_slice($this->data[$entityType][$path], 0, (int)$index);
61
            return;
62
        }
63
64
        // Filter out all nodes of the specified type
65
        $this->data[$entityType][$path] = array_filter(
66
            $this->data[$entityType][$path],
67
            static function ($node) use ($index) {
68
                return empty($node['type']) || $node['type'] !== $index;
69
            }
70
        );
71
72
        // If we end up with an empty array make it NULL
73
        if (empty($this->data[$entityType][$path])) {
74
            $this->data[$entityType][$path] = null;
75
            return;
76
        }
77
78
        // Re-index
79
        $this->data[$entityType][$path] = array_values($this->data[$entityType][$path]);
80
    }
81
}
82