Passed
Branch feature/first-release (4212f2)
by Andrea Marco
10:46
created

Pointers::matching()   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\Pointers;
4
5
use Cerbero\JsonParser\Exceptions\IntersectingPointersException;
6
use Cerbero\JsonParser\Tree;
7
8
use function count;
9
10
/**
11
 * The JSON pointers aggregate.
12
 *
13
 */
14
final class Pointers
15
{
16
    /**
17
     * The JSON pointers.
18
     *
19
     * @var Pointer[]
20
     */
21
    private array $pointers = [];
22
23
    /**
24
     * The JSON pointer matching with the current tree.
25
     *
26
     * @var Pointer
27
     */
28
    private Pointer $matching;
29
30
    /**
31
     * The list of pointers that were found within the JSON.
32
     *
33
     * @var array<string, bool>
34
     */
35
    private array $found = [];
36
37
    /**
38
     * Add the given pointer
39
     *
40
     * @param Pointer $pointer
41
     */
42 101
    public function add(Pointer $pointer): void
43
    {
44 101
        foreach ($this->pointers as $existingPointer) {
45 37
            if (str_starts_with($existingPointer, "$pointer/") || str_starts_with($pointer, "$existingPointer/")) {
46 8
                throw new IntersectingPointersException($existingPointer, $pointer);
47
            }
48
        }
49
50 101
        $this->pointers[] = $pointer;
51
    }
52
53
    /**
54
     * Retrieve the pointer matching the current tree
55
     *
56
     * @return Pointer
57
     */
58 127
    public function matching(): Pointer
59
    {
60 127
        return $this->matching ??= $this->pointers[0] ?? new Pointer('');
61
    }
62
63
    /**
64
     * Retrieve the pointer matching the given tree
65
     *
66
     * @param Tree $tree
67
     * @return Pointer
68
     */
69 127
    public function matchTree(Tree $tree): Pointer
70
    {
71 127
        if (count($this->pointers) < 2) {
72 98
            return $this->matching;
73
        }
74
75 29
        $pointers = [];
76 29
        $originalTree = $tree->original();
77
78 29
        foreach ($this->pointers as $pointer) {
79 29
            $referenceTokens = $pointer->referenceTokens();
80
81 29
            foreach ($originalTree as $depth => $key) {
82 27
                if (!$pointer->depthMatchesKey($depth, $key)) {
83 27
                    continue 2;
84 21
                } elseif (!isset($pointers[$depth]) || $referenceTokens == $originalTree) {
85 21
                    $pointers[$depth] = $pointer;
86
                }
87
            }
88
        }
89
90 29
        return $this->matching = end($pointers) ?: $this->matching;
91
    }
92
93
    /**
94
     * Mark the given pointer as found
95
     *
96
     * @return void
97
     */
98 93
    public function markAsFound(): void
99
    {
100 93
        if (!$this->matching->wasFound) {
101 93
            $this->found[(string) $this->matching] = $this->matching->wasFound = true;
102
        }
103
    }
104
105
    /**
106
     * Determine whether all pointers were found in the given tree
107
     *
108
     * @param Tree $tree
109
     * @return bool
110
     */
111 124
    public function wereFoundInTree(Tree $tree): bool
112
    {
113 124
        return count($this->pointers) == count($this->found)
114 124
            && !empty($this->pointers)
115 124
            && !$this->matching->includesTree($tree);
116
    }
117
}
118