Passed
Push — master ( 1b4865...c6e62a )
by Edward
02:24
created

Processor::selectValuePaths()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
c 0
b 0
f 0
dl 0
loc 16
rs 10
cc 4
nc 4
nop 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Remorhaz\JSON\Path\Processor;
5
6
use function array_map;
7
use Collator;
8
use Remorhaz\JSON\Data\Export\Decoder;
9
use Remorhaz\JSON\Data\Export\Encoder;
10
use Remorhaz\JSON\Data\Iterator\ValueIteratorFactory;
11
use Remorhaz\JSON\Data\Path\PathInterface;
12
use Remorhaz\JSON\Data\Value\NodeValueInterface;
13
use Remorhaz\JSON\Path\Query\QueryInterface;
14
use Remorhaz\JSON\Path\Runtime\Aggregator\AggregatorCollection;
15
use Remorhaz\JSON\Path\Runtime\Comparator\ComparatorCollection;
16
use Remorhaz\JSON\Path\Runtime\Evaluator;
17
use Remorhaz\JSON\Path\Runtime\Fetcher;
18
use Remorhaz\JSON\Path\Runtime\Runtime;
19
use Remorhaz\JSON\Path\Runtime\RuntimeInterface;
20
21
final class Processor implements ProcessorInterface
22
{
23
24
    private $runtime;
25
26
    private $resultFactory;
27
28
    private $pathEncoder;
29
30
    public static function create(): ProcessorInterface
31
    {
32
        $valueIteratorFactory = new ValueIteratorFactory;
33
        $runtime = new Runtime(
34
            new Fetcher($valueIteratorFactory),
35
            new Evaluator(
36
                new ComparatorCollection($valueIteratorFactory, new Collator('UTF-8')),
37
                new AggregatorCollection($valueIteratorFactory)
38
            )
39
        );
40
        $decoder = new Decoder($valueIteratorFactory);
41
        $encoder = new Encoder($decoder);
42
43
        return new self(
44
            $runtime,
45
            new ResultFactory($encoder, $decoder),
46
            new PathEncoder
47
        );
48
    }
49
50
    public function __construct(
51
        RuntimeInterface $runtime,
52
        ResultFactoryInterface $resultFactory,
53
        PathEncoderInterface $pathEncoder
54
    ) {
55
        $this->runtime = $runtime;
56
        $this->resultFactory = $resultFactory;
57
        $this->pathEncoder = $pathEncoder;
58
    }
59
60
    public function select(QueryInterface $query, NodeValueInterface $rootNode): SelectResultInterface
61
    {
62
        return $this
63
            ->resultFactory
64
            ->createResult($query($this->runtime, $rootNode));
65
    }
66
67
    public function selectPaths(QueryInterface $query, NodeValueInterface $rootNode): array
68
    {
69
        return array_map(
70
            [$this->pathEncoder, 'encodePath'],
71
            $this->selectValuePaths($query, $rootNode)
72
        );
73
    }
74
75
    /**
76
     * @param QueryInterface $query
77
     * @param NodeValueInterface $rootNode
78
     * @return PathInterface[]
79
     */
80
    private function selectValuePaths(QueryInterface $query, NodeValueInterface $rootNode): array
81
    {
82
        if (!$query->getProperties()->isPath()) {
83
            throw new Exception\PathNotSelectableException($query);
84
        }
85
86
        $results = [];
87
        foreach ($query($this->runtime, $rootNode)->getValues() as $value) {
88
            if (!$value instanceof NodeValueInterface) {
89
                throw new Exception\PathNotFoundInValueException($value);
90
            }
91
92
            $results[] = $value->getPath();
93
        }
94
95
        return $results;
96
    }
97
}
98