Pointers::add()   A
last analyzed

Complexity

Conditions 4
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 4
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 4
rs 10
1
<?php
2
3
namespace Cerbero\JsonParser\Pointers;
4
5
use Cerbero\JsonParser\Exceptions\IntersectingPointersException;
6
use Cerbero\JsonParser\ValueObjects\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 300
    public function add(Pointer $pointer): void
43
    {
44 300
        foreach ($this->pointers as $existingPointer) {
45 98
            if (str_starts_with($existingPointer, "$pointer/") || str_starts_with($pointer, "$existingPointer/")) {
46 8
                throw new IntersectingPointersException($existingPointer, $pointer);
47
            }
48
        }
49
50 300
        $this->pointers[] = $pointer;
51
    }
52
53
    /**
54
     * Retrieve the pointer matching the current tree
55
     *
56
     * @return Pointer
57
     */
58 357
    public function matching(): Pointer
59
    {
60 357
        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 357
    public function matchTree(Tree $tree): Pointer
70
    {
71 357
        if (count($this->pointers) < 2) {
72 272
            return $this->matching;
73
        }
74
75 90
        $pointers = [];
76 90
        $originalTree = $tree->original();
77
78 90
        foreach ($this->pointers as $pointer) {
79 90
            if ($pointer->referenceTokens == $originalTree) {
80 57
                return $this->matching = $pointer;
81
            }
82
83 90
            foreach ($originalTree as $depth => $key) {
84 84
                if (!$pointer->depthMatchesKey($depth, $key)) {
85 84
                    continue 2;
86 22
                } elseif (!isset($pointers[$depth])) {
87 22
                    $pointers[$depth] = $pointer;
88
                }
89
            }
90
        }
91
92 90
        return $this->matching = end($pointers) ?: $this->matching;
93
    }
94
95
    /**
96
     * Mark the given pointer as found
97
     *
98
     * @return Pointer
99
     */
100 265
    public function markAsFound(): Pointer
101
    {
102 265
        if (!$this->matching->wasFound) {
103 265
            $this->found[(string) $this->matching] = $this->matching->wasFound = true;
104
        }
105
106 265
        return $this->matching;
107
    }
108
109
    /**
110
     * Determine whether all pointers were found in the given tree
111
     *
112
     * @param Tree $tree
113
     * @return bool
114
     */
115 354
    public function wereFoundInTree(Tree $tree): bool
116
    {
117 354
        return count($this->pointers) == count($this->found)
118 354
            && !empty($this->pointers)
119 354
            && !$this->matching->includesTree($tree);
120
    }
121
}
122