Completed
Push — master ( 0cdf45...d59ceb )
by Edward
04:37
created

ValueFetcher::fetchDeepProperties()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 8
nc 3
nop 2
dl 0
loc 14
ccs 0
cts 9
cp 0
crap 12
rs 10
c 1
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Remorhaz\JSON\Path\Runtime;
5
6
use function iterator_count;
7
use Remorhaz\JSON\Data\Iterator\ValueIteratorFactory;
8
use Remorhaz\JSON\Data\Value\ArrayValueInterface;
9
use Remorhaz\JSON\Data\Value\NodeValueInterface;
10
use Remorhaz\JSON\Data\Value\ObjectValueInterface;
11
use Remorhaz\JSON\Data\Value\ScalarValueInterface;
12
13
final class ValueFetcher implements ValueFetcherInterface
14
{
15
16
    private $valueIteratorFactory;
17
18
    public function __construct(ValueIteratorFactory $valueIteratorFactory)
19
    {
20
        $this->valueIteratorFactory = $valueIteratorFactory;
21
    }
22
23
    /**
24
     * @param Matcher\ChildMatcherInterface $matcher
25
     * @param NodeValueInterface $value
26
     * @return NodeValueInterface[]
27
     */
28
    public function fetchValueChildren(
29
        Matcher\ChildMatcherInterface $matcher,
30
        NodeValueInterface $value
31
    ): array {
32
        if ($value instanceof ScalarValueInterface) {
33
            return [];
34
        }
35
36
        if ($value instanceof ArrayValueInterface) {
37
            return $this->fetchElements($value, $matcher);
38
        }
39
40
        if ($value instanceof ObjectValueInterface) {
41
            return $this->fetchProperties($value, $matcher);
42
        }
43
44
        throw new Exception\UnexpectedNodeValueFetchedException($value);
45
    }
46
47
    public function fetchValueDeepChildren(
48
        Matcher\ChildMatcherInterface $matcher,
49
        NodeValueInterface $value
50
    ): array {
51
        if ($value instanceof ScalarValueInterface) {
52
            return [];
53
        }
54
55
        if ($value instanceof ArrayValueInterface) {
56
            return $this->fetchDeepElements($value, $matcher);
57
        }
58
59
        if ($value instanceof ObjectValueInterface) {
60
            return $this->fetchDeepProperties($value, $matcher);
61
        }
62
63
        throw new Exception\UnexpectedNodeValueFetchedException($value);
64
    }
65
66
    private function fetchElements(NodeValueInterface $value, Matcher\ChildMatcherInterface $matcher): array
67
    {
68
        $results = [];
69
        foreach ($this->valueIteratorFactory->createArrayIterator($value->createIterator()) as $index => $element) {
70
            if ($matcher->match($index, $element, $value)) {
71
                $results[] = $element;
72
            }
73
        }
74
75
        return $results;
76
    }
77
78
    private function fetchProperties(NodeValueInterface $value, Matcher\ChildMatcherInterface $matcher): array
79
    {
80
        $results = [];
81
        foreach ($this->valueIteratorFactory->createObjectIterator($value->createIterator()) as $name => $property) {
82
            if ($matcher->match($name, $property, $value)) {
83
                $results[] = $property;
84
            }
85
        }
86
87
        return $results;
88
    }
89
90
    private function fetchDeepElements(NodeValueInterface $value, Matcher\ChildMatcherInterface $matcher): array
91
    {
92
        $results = [];
93
        foreach ($this->valueIteratorFactory->createArrayIterator($value->createIterator()) as $index => $element) {
94
            if ($matcher->match($index, $element, $value)) {
95
                $results[] = $element;
96
            }
97
            array_push(
98
                $results,
99
                ...$this->fetchValueDeepChildren($matcher, $element)
100
            );
101
        }
102
103
        return $results;
104
    }
105
106
    private function fetchDeepProperties(NodeValueInterface $value, Matcher\ChildMatcherInterface $matcher): array
107
    {
108
        $results = [];
109
        foreach ($this->valueIteratorFactory->createObjectIterator($value->createIterator()) as $name => $property) {
110
            if ($matcher->match($name, $property, $value)) {
111
                $results[] = $property;
112
            }
113
            array_push(
114
                $results,
115
                ...$this->fetchValueDeepChildren($matcher, $property)
116
            );
117
        }
118
119
        return $results;
120
    }
121
122
    public function fetchArrayLength(NodeValueInterface $value): ?int
123
    {
124
        if (!$value instanceof ArrayValueInterface) {
125
            return null;
126
        }
127
        $elementIterator = $this->valueIteratorFactory->createArrayIterator($value->createIterator());
128
129
        return iterator_count($elementIterator);
130
    }
131
}
132