OperationFactory::extractPathPointer()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
c 1
b 0
f 0
nc 3
nop 3
dl 0
loc 16
ccs 10
cts 10
cp 1
crap 3
rs 9.9
1
<?php
2
declare(strict_types=1);
3
4
namespace Remorhaz\JSON\Patch\Operation;
5
6
use Remorhaz\JSON\Data\Comparator\ComparatorInterface;
7
use Remorhaz\JSON\Data\Value\NodeValueInterface;
8
use Remorhaz\JSON\Pointer\Processor\ProcessorInterface as PointerProcessorInterface;
9
use Remorhaz\JSON\Pointer\Query\QueryFactoryInterface as PointerQueryFactoryInterface;
10
use Remorhaz\JSON\Pointer\Query\QueryInterface;
11
use function is_string;
12
13
final class OperationFactory implements OperationFactoryInterface
14
{
15
16
    private const OPERATION_ADD = 'add';
17
18
    private const OPERATION_REMOVE = 'remove';
19
20
    private const OPERATION_REPLACE = 'replace';
21
22
    private const OPERATION_TEST = 'test';
23
24
    private const OPERATION_COPY = 'copy';
25
26
    private const OPERATION_MOVE = 'move';
27
28
    private const POINTER_PATH = 'path';
29
30
    private const POINTER_FROM = 'from';
31
32
    private $pointerQueryFactory;
33
34
    private $pointerProcessor;
35
36
    private $equalComparator;
37
38 29
    public function __construct(
39
        PointerQueryFactoryInterface $pointerQueryFactory,
40
        PointerProcessorInterface $pointerProcessor,
41
        ComparatorInterface $equalComparator
42
    ) {
43 29
        $this->pointerQueryFactory = $pointerQueryFactory;
44 29
        $this->pointerProcessor = $pointerProcessor;
45 29
        $this->equalComparator = $equalComparator;
46 29
    }
47
48 29
    public function fromJson(NodeValueInterface $jsonValue, int $index): OperationInterface
49
    {
50 29
        $operationCode = $this->getOperationCode($jsonValue, $index);
51
        switch ($operationCode) {
52 27
            case self::OPERATION_ADD:
53 4
                return new AddOperation(
54 4
                    $index,
55 4
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
56 2
                    $this->extractValue($jsonValue, $index)
57
                );
58
59 23
            case self::OPERATION_REMOVE:
60 3
                return new RemoveOperation(
61 3
                    $index,
62 3
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index)
63
                );
64
65 20
            case self::OPERATION_REPLACE:
66 4
                return new ReplaceOperation(
67 4
                    $index,
68 4
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
69 2
                    $this->extractValue($jsonValue, $index)
70
                );
71
72 16
            case self::OPERATION_TEST:
73 5
                return new TestOperation(
74 5
                    $index,
75 5
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
76 3
                    $this->extractValue($jsonValue, $index),
77 2
                    $this->equalComparator
78
                );
79
80 11
            case self::OPERATION_COPY:
81 5
                return new CopyOperation(
82 5
                    $index,
83 5
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
84 3
                    $this->extractPathPointer($jsonValue, self::POINTER_FROM, $index)
85
                );
86
87 6
            case self::OPERATION_MOVE:
88 5
                return new MoveOperation(
89 5
                    $index,
90 5
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
91 3
                    $this->extractPathPointer($jsonValue, self::POINTER_FROM, $index)
92
                );
93
        }
94
95 1
        throw new Exception\UnknownOperationCodeException($index, $operationCode);
96
    }
97
98 29
    private function getOperationCode(NodeValueInterface $jsonValue, int $index): string
99
    {
100
        $result = $this
101 29
            ->pointerProcessor
102 29
            ->select($this->pointerQueryFactory->createQuery('/op'), $jsonValue);
103 29
        if (!$result->exists()) {
104 1
            throw new Exception\OperationCodeNotFoundException($index);
105
        }
106 28
        $operationCode = $result->decode();
107 28
        if (is_string($operationCode)) {
108 27
            return $operationCode;
109
        }
110
111 1
        throw new Exception\InvalidOperationCodeException($operationCode, $index);
112
    }
113
114 26
    private function extractPathPointer(NodeValueInterface $operation, string $property, int $index): QueryInterface
115
    {
116
        $result = $this
117 26
            ->pointerProcessor
118 26
            ->select($this->pointerQueryFactory->createQuery("/{$property}"), $operation);
119 26
        if (!$result->exists()) {
120 8
            throw new Exception\PathNotFoundException($index, $property);
121
        }
122 20
        $path = $result->decode();
123 20
        if (!is_string($path)) {
124 8
            throw new Exception\InvalidPathException($index, $property, $path);
125
        }
126
127
        return $this
128 14
            ->pointerQueryFactory
129 14
            ->createQuery($path);
130
    }
131
132 7
    private function extractValue(NodeValueInterface $operation, int $index): NodeValueInterface
133
    {
134
        $result = $this
135 7
            ->pointerProcessor
136 7
            ->select($this->pointerQueryFactory->createQuery('/value'), $operation);
137
138 7
        if ($result->exists()) {
139 4
            return $result->get();
140
        }
141
142 3
        throw new Exception\ValueNotFoundException($index);
143
    }
144
}
145