Passed
Push — master ( fc0629...9e5c60 )
by Edward
05:11
created

ValueFetcher   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 31
dl 0
loc 81
ccs 0
cts 37
cp 0
rs 10
c 2
b 0
f 0
wmc 17

4 Methods

Rating   Name   Duplication   Size   Complexity  
A createSortedChildStructIterator() 0 17 4
A createChildrenIterator() 0 17 4
A createDeepChildrenIterator() 0 20 5
A createUnsortedChildStructIterator() 0 11 4
1
<?php
2
declare(strict_types=1);
3
4
namespace Remorhaz\JSON\Path\Runtime;
5
6
use Iterator;
7
use Remorhaz\JSON\Data\Value\StructValueInterface;
8
use Remorhaz\JSON\Data\Value\NodeValueInterface;
9
use Remorhaz\JSON\Data\Value\ScalarValueInterface;
10
use Remorhaz\JSON\Path\Runtime\Matcher\SortedChildMatcherInterface;
11
12
use function ksort;
13
use const SORT_ASC;
14
use const SORT_NUMERIC;
15
16
final class ValueFetcher implements ValueFetcherInterface
17
{
18
19
    /**
20
     * @param Matcher\ChildMatcherInterface $matcher
21
     * @param NodeValueInterface            $value
22
     * @return NodeValueInterface[]|Iterator
23
     */
24
    public function createChildrenIterator(
25
        Matcher\ChildMatcherInterface $matcher,
26
        NodeValueInterface $value
27
    ): Iterator {
28
        if ($value instanceof ScalarValueInterface) {
29
            return;
30
        }
31
32
        if ($value instanceof StructValueInterface) {
33
            yield from $matcher instanceof SortedChildMatcherInterface
34
                ? $this->createSortedChildStructIterator($matcher, $value)
35
                : $this->createUnsortedChildStructIterator($matcher, $value);
36
37
            return;
38
        }
39
40
        throw new Exception\UnexpectedNodeValueFetchedException($value);
41
    }
42
43
    private function createUnsortedChildStructIterator(
44
        Matcher\ChildMatcherInterface $matcher,
45
        NodeValueInterface $value
46
    ): Iterator {
47
        if (!$value instanceof StructValueInterface) {
48
            return;
49
        }
50
51
        foreach ($value->createChildIterator() as $index => $element) {
52
            if ($matcher->match($index, $element, $value)) {
53
                yield $element;
54
            }
55
        }
56
    }
57
58
    private function createSortedChildStructIterator(
59
        Matcher\SortedChildMatcherInterface $matcher,
60
        NodeValueInterface $value
61
    ): Iterator {
62
        if (!$value instanceof StructValueInterface) {
63
            return;
64
        }
65
66
        $sortableElements = [];
67
        foreach ($value->createChildIterator() as $index => $element) {
68
            if ($matcher->match($index, $element, $value)) {
69
                $sortIndex = $matcher->getSortIndex($index, $element, $value);
70
                $sortableElements[$sortIndex] = $element;
71
            }
72
        }
73
        ksort($sortableElements, SORT_ASC | SORT_NUMERIC);
74
        yield from $sortableElements;
75
    }
76
77
    public function createDeepChildrenIterator(
78
        Matcher\ChildMatcherInterface $matcher,
79
        NodeValueInterface $value
80
    ): Iterator {
81
        if ($value instanceof ScalarValueInterface) {
82
            return;
83
        }
84
85
        if ($value instanceof StructValueInterface) {
86
            foreach ($value->createChildIterator() as $index => $element) {
87
                if ($matcher->match($index, $element, $value)) {
88
                    yield $element;
89
                }
90
                yield from $this->createDeepChildrenIterator($matcher, $element);
91
            }
92
93
            return;
94
        }
95
96
        throw new Exception\UnexpectedNodeValueFetchedException($value);
97
    }
98
}
99