Passed
Push — master ( f13532...bf7dba )
by Andrea Marco
02:44 queued 12s
created

Tree::original()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 1
rs 10
1
<?php
2
3
namespace Cerbero\JsonParser\ValueObjects;
4
5
use Cerbero\JsonParser\Pointers\Pointers;
6
use Cerbero\JsonParser\Tokens\Token;
7
8
use function count;
9
10
/**
11
 * The JSON tree.
12
 *
13
 */
14
final class Tree
15
{
16
    /**
17
     * The original JSON tree.
18
     *
19
     * @var array<int, string|int>
20
     */
21
    private array $original = [];
22
23
    /**
24
     * The wildcarded JSON tree.
25
     *
26
     * @var array<int, string|int>
27
     */
28
    private array $wildcarded = [];
29
30
    /**
31
     * Whether a depth is within an object.
32
     *
33
     * @var array<int, bool>
34
     */
35
    private array $inObjectByDepth = [];
36
37
    /**
38
     * The JSON tree depth.
39
     *
40
     * @var int
41
     */
42
    private int $depth = -1;
43
44
    /**
45
     * Instantiate the class.
46
     *
47
     * @param Pointers $pointers
48
     */
49 359
    public function __construct(private readonly Pointers $pointers)
50
    {
51 359
    }
52
53
    /**
54
     * Retrieve the original JSON tree
55
     *
56
     * @return array<int, string|int>
57
     */
58 269
    public function original(): array
59
    {
60 269
        return $this->original;
61
    }
62
63
    /**
64
     * Retrieve the wildcarded JSON tree
65
     *
66
     * @return array<int, string|int>
67
     */
68 248
    public function wildcarded(): array
69
    {
70 248
        return $this->wildcarded;
71
    }
72
73
    /**
74
     * Determine whether the current depth is within an object
75
     *
76
     * @return bool
77
     */
78 355
    public function inObject(): bool
79
    {
80 355
        return $this->inObjectByDepth[$this->depth] ?? false;
81
    }
82
83
    /**
84
     * Retrieve the JSON tree depth
85
     *
86
     * @return int
87
     */
88 32
    public function depth(): int
89
    {
90 32
        return $this->depth;
91
    }
92
93
    /**
94
     * Increase the tree depth by entering an object or an array
95
     *
96
     * @param bool $inObject
97
     * @return void
98
     */
99 355
    public function deepen(bool $inObject): void
100
    {
101 355
        $this->depth++;
102 355
        $this->inObjectByDepth[$this->depth] = $inObject;
103
    }
104
105
    /**
106
     * Decrease the tree depth
107
     *
108
     * @return void
109
     */
110 264
    public function emerge(): void
111
    {
112 264
        $this->depth--;
113
    }
114
115
    /**
116
     * Determine whether the tree is deep
117
     *
118
     * @return bool
119
     */
120 353
    public function isDeep(): bool
121
    {
122 353
        $pointer = $this->pointers->matching();
123
124 353
        return $pointer == '' ? $this->depth > 0 : $this->depth >= $pointer->depth;
0 ignored issues
show
introduced by
The condition $pointer == '' is always false.
Loading history...
125
    }
126
127
    /**
128
     * Traverse the given token
129
     *
130
     * @param Token $token
131
     * @param bool $expectsKey
132
     * @return void
133
     */
134 355
    public function traverseToken(Token $token, bool $expectsKey): void
135
    {
136 355
        $pointer = $this->pointers->matching();
137
138 355
        if ($pointer != '' && $this->depth >= $pointer->depth) {
139 123
            return;
140 355
        } elseif ($expectsKey) {
141 261
            $this->traverseKey($token);
142 355
        } elseif ($token->isValue() && !$this->inObject()) {
143 355
            $this->traverseArray();
144
        }
145
    }
146
147
    /**
148
     * Determine whether the tree is matched by the JSON pointer
149
     *
150
     * @return bool
151
     */
152 355
    public function isMatched(): bool
153
    {
154 355
        return $this->depth >= 0 && $this->pointers->matching()->matchesTree($this);
155
    }
156
157
    /**
158
     * Traverse the given object key
159
     *
160
     * @param string $key
161
     * @return void
162
     */
163 261
    public function traverseKey(string $key): void
164
    {
165 261
        $trimmedKey = substr($key, 1, -1);
166
167 261
        $this->original[$this->depth] = $trimmedKey;
168 261
        $this->wildcarded[$this->depth] = $trimmedKey;
169
170 261
        if (count($this->original) > $offset = $this->depth + 1) {
171 78
            array_splice($this->original, $offset);
172 78
            array_splice($this->wildcarded, $offset);
173 78
            array_splice($this->inObjectByDepth, $offset);
174
        }
175
176 261
        $this->pointers->matchTree($this);
177
    }
178
179
    /**
180
     * Traverse an array
181
     *
182
     * @return void
183
     */
184 355
    public function traverseArray(): void
185
    {
186 355
        $index = $this->original[$this->depth] ?? null;
187 355
        $this->original[$this->depth] = $index = is_int($index) ? $index + 1 : 0;
188
189 355
        if (count($this->original) > $offset = $this->depth + 1) {
190 355
            array_splice($this->original, $offset);
191 355
            array_splice($this->inObjectByDepth, $offset);
192
        }
193
194 355
        $referenceTokens = $this->pointers->matchTree($this)->referenceTokens;
195 355
        $this->wildcarded[$this->depth] = ($referenceTokens[$this->depth] ?? null) == '-' ? '-' : $index;
196
197 355
        if (count($this->wildcarded) > $offset) {
198 355
            array_splice($this->wildcarded, $offset);
199
        }
200
    }
201
202
    /**
203
     * Retrieve the current key
204
     *
205
     * @return string|int
206
     */
207 263
    public function currentKey(): string|int
208
    {
209 263
        $key = $this->original[$this->depth];
210
211 263
        return is_string($key) ? "\"$key\"" : $key;
212
    }
213
}
214