Passed
Branch feature/first-release (5d23f8)
by Andrea Marco
10:49
created

Pointer::isLazy()   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 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
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\Pointers;
4
5
use Cerbero\JsonParser\Exceptions\InvalidPointerException;
6
use Cerbero\JsonParser\Tree;
7
use Closure;
8
use Stringable;
9
10
use function count;
11
use function is_int;
12
use function array_slice;
13
14
/**
15
 * The JSON pointer.
16
 *
17
 */
18
final class Pointer implements Stringable
19
{
20
    /**
21
     * The reference tokens.
22
     *
23
     * @var string[]
24
     */
25
    private array $referenceTokens;
26
27
    /**
28
     * The pointer depth.
29
     *
30
     * @var int
31
     */
32
    private int $depth;
33
34
    /**
35
     * The pointer callback.
36
     *
37
     * @var Closure
38
     */
39
    private ?Closure $callback;
40
41
    /**
42
     * Whether the pointer was found.
43
     *
44
     * @var bool
45
     */
46
    public bool $wasFound = false;
47
48
    /**
49
     * Instantiate the class.
50
     *
51
     * @param string $pointer
52
     * @param bool $isLazy
53
     * @param Closure|null $callback
54
     */
55 148
    public function __construct(private string $pointer, private bool $isLazy = false, Closure $callback = null)
56
    {
57 148
        $this->referenceTokens = $this->toReferenceTokens();
58 144
        $this->depth = count($this->referenceTokens);
59 144
        $this->callback = $callback;
60
    }
61
62
    /**
63
     * Turn the JSON pointer into reference tokens
64
     *
65
     * @return string[]
66
     */
67 148
    private function toReferenceTokens(): array
68
    {
69 148
        if (preg_match('#^(?:/(?:(?:[^/~])|(?:~[01]))*)*$#', $this->pointer) === 0) {
70 4
            throw new InvalidPointerException($this->pointer);
71
        }
72
73 144
        $tokens = explode('/', $this->pointer);
74 144
        $referenceTokens = array_map(fn (string $token) => str_replace(['~1', '~0'], ['/', '~'], $token), $tokens);
75
76 144
        return array_slice($referenceTokens, 1);
77
    }
78
79
    /**
80
     * Determine whether the pointer is lazy
81
     *
82
     * @return bool
83
     */
84 52
    public function isLazy(): bool
85
    {
86 52
        return $this->isLazy;
87
    }
88
89
    /**
90
     * Retrieve the reference tokens
91
     *
92
     * @return string[]
93
     */
94 136
    public function referenceTokens(): array
95
    {
96 136
        return $this->referenceTokens;
97
    }
98
99
    /**
100
     * Retrieve the JSON pointer depth
101
     *
102
     * @return int
103
     */
104 134
    public function depth(): int
105
    {
106 134
        return $this->depth;
107
    }
108
109
    /**
110
     * Call the pointer callback
111
     *
112
     * @param mixed $value
113
     * @param mixed $key
114
     * @return mixed
115
     */
116 101
    public function call(mixed $value, mixed $key): mixed
117
    {
118 101
        if ($this->callback === null) {
119 98
            return $value;
120
        }
121
122 3
        return ($this->callback)($value, $key) ?? $value;
123
    }
124
125
    /**
126
     * Determine whether the reference token at the given depth matches the provided key
127
     *
128
     * @param int $depth
129
     * @param string|int $key
130
     * @return bool
131
     */
132 31
    public function depthMatchesKey(int $depth, string|int $key): bool
133
    {
134 31
        $referenceToken = $this->referenceTokens[$depth] ?? null;
135
136 31
        return $referenceToken === (string) $key
137 31
            || (is_int($key) && $referenceToken === '-');
138
    }
139
140
    /**
141
     * Determine whether the pointer matches the given tree
142
     *
143
     * @param Tree $tree
144
     * @return bool
145
     */
146 134
    public function matchesTree(Tree $tree): bool
147
    {
148 134
        return $this->referenceTokens == []
149 134
            || $this->referenceTokens == $tree->original()
150 134
            || $this->referenceTokens == $tree->wildcarded();
151
    }
152
153
    /**
154
     * Determine whether the pointer includes the given tree
155
     *
156
     * @param Tree $tree
157
     * @return bool
158
     */
159 78
    public function includesTree(Tree $tree): bool
160
    {
161
        // if ($this->pointer == '' && !$this->isLazy) {
162 78
        if ($this->pointer == '') {
163 9
            return true;
164
        }
165
166 71
        return is_int($firstNest = array_search('-', $this->referenceTokens))
167 71
            && array_slice($this->referenceTokens, 0, $firstNest) === array_slice($tree->original(), 0, $firstNest);
168
    }
169
170
    /**
171
     * Retrieve the underlying JSON pointer
172
     *
173
     * @return string
174
     */
175 144
    public function __toString(): string
176
    {
177 144
        return $this->pointer;
178
    }
179
}
180