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

ValueFetcher::createChildrenGenerator()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 8
c 0
b 0
f 0
nc 5
nop 2
dl 0
loc 18
ccs 0
cts 9
cp 0
crap 30
rs 9.6111
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