ValueFetcher::createSortedChildStructIterator()   A
last analyzed

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

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