Passed
Push — master ( 7b7005...55ec05 )
by Brent
02:29
created

WalkableArray   A

Complexity

Total Complexity 34

Size/Duplication

Total Lines 138
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Importance

Changes 0
Metric Value
dl 0
loc 138
rs 9.2
c 0
b 0
f 0
wmc 34
lcom 1
cbo 0

14 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
A fromArray() 0 3 1
C get() 0 30 8
D set() 0 41 10
A toArray() 0 6 1
A current() 0 3 1
A offsetGet() 0 3 2
A offsetSet() 0 9 3
A offsetExists() 0 3 2
A offsetUnset() 0 3 1
A next() 0 3 1
A key() 0 3 1
A valid() 0 3 1
A rewind() 0 3 1
1
<?php
2
3
namespace Brendt\Stitcher\Lib;
4
5
class WalkableArray implements \ArrayAccess, \Iterator
6
{
7
    const TOKEN_NESTING = '.';
8
    const TOKEN_REPETITION = '*';
9
10
    private $array = [];
11
    private $position = 0;
12
13
    public function __construct(array $array = []) {
14
        $this->array = $array;
15
    }
16
17
    public static function fromArray(array $array): WalkableArray {
18
        return new self($array);
19
    }
20
21
    public function get($pathParts, array $element = null) {
22
        if (!is_array($pathParts)) {
23
            $pathParts = explode(self::TOKEN_NESTING, $pathParts);
24
        }
25
26
        if (!$element) {
27
            $element = $this->array;
28
        }
29
30
        foreach ($pathParts as $key => $pathPart) {
31
            if ($pathPart === self::TOKEN_REPETITION && is_array($element)) {
32
                $result = new self();
33
                $partialPath = array_splice($pathParts, $key + 1);
34
35
                foreach ($element as $items) {
36
                    $result[] = $this->get($partialPath, $items);
37
                }
38
39
                return $result;
40
            }
41
42
            if (!isset($element[$pathPart])) {
43
                return null;
44
            }
45
46
            $element = $element[$pathPart];
47
        }
48
49
        return $element;
50
    }
51
52
    public function set($pathParts, $value, &$element = null, array $callbackArguments = []): WalkableArray {
53
        if (!is_array($pathParts)) {
54
            $pathParts = explode(self::TOKEN_NESTING, $pathParts);
55
        }
56
57
        end($pathParts);
58
        $lastPathKey = key($pathParts);
59
        reset($pathParts);
60
61
        if (!$element) {
62
            $element = &$this->array;
63
        }
64
65
        foreach ($pathParts as $key => $pathPart) {
66
            if ($pathPart === self::TOKEN_REPETITION && is_array($element)) {
67
                $partialPath = array_splice($pathParts, $key + 1);
68
69
                foreach ($element as $itemKey => &$item) {
70
                    $this->set($partialPath, $value, $item, [new self($item), $itemKey]);
71
                }
72
73
                return $this;
74
            }
75
76
            if (!isset($element[$pathPart])) {
77
                $element[$pathPart] = $key === $lastPathKey ? null : [];
78
            }
79
80
            $element = &$element[$pathPart];
81
        }
82
83
        if ($value instanceof \Closure) {
84
            $element = call_user_func_array($value, $callbackArguments);
85
        } else {
86
            $element = $value;
87
        }
88
89
        unset($element);
90
91
        return $this;
92
    }
93
94
    public function toArray(): array {
95
        $array = $this->array;
96
        reset($array);
97
98
        return $array;
99
    }
100
101
    public function current() {
102
        return current($this->array);
103
    }
104
105
    public function offsetGet($offset) {
106
        return isset($this->array[$offset]) ? $this->array[$offset] : $this->get($offset);
107
    }
108
109
    public function offsetSet($offset, $value) {
110
        if (is_null($offset)) {
111
            $this->array[] = $value;
112
        } elseif (isset($this->array[$offset])) {
113
            $this->array[$offset] = $value;
114
        } else {
115
            $this->set($offset, $value);
116
        }
117
    }
118
119
    public function offsetExists($offset) {
120
        return isset($this->array[$offset]) || $this->get($offset) !== null;
121
    }
122
123
    public function offsetUnset($offset) {
124
        unset($this->array[$offset]);
125
    }
126
127
    public function next() {
128
        ++$this->position;
129
    }
130
131
    public function key() {
132
        return $this->position;
133
    }
134
135
    public function valid() {
136
        return isset($this->array[$this->position]);
137
    }
138
139
    public function rewind() {
140
        $this->position = 0;
141
    }
142
}
143