Passed
Push — master ( aabc99...b9a6ed )
by Edward
02:33
created

OperationFactory::extractFromPointer()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 16
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 11
c 1
b 0
f 0
nc 3
nop 2
dl 0
loc 16
rs 9.9

1 Method

Rating   Name   Duplication   Size   Complexity  
A OperationFactory::extractValue() 0 11 2
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
    public function __construct(
39
        PointerQueryFactoryInterface $pointerQueryFactory,
40
        PointerProcessorInterface $pointerProcessor,
41
        ComparatorInterface $equalComparator
42
    ) {
43
        $this->pointerQueryFactory = $pointerQueryFactory;
44
        $this->pointerProcessor = $pointerProcessor;
45
        $this->equalComparator = $equalComparator;
46
    }
47
48
    public function fromJson(NodeValueInterface $jsonValue, int $index): OperationInterface
49
    {
50
        $operationCode = $this->getOperationCode($jsonValue, $index);
51
        switch ($operationCode) {
52
            case self::OPERATION_ADD:
53
                return new AddOperation(
54
                    $index,
55
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
56
                    $this->extractValue($jsonValue, $index)
57
                );
58
59
            case self::OPERATION_REMOVE:
60
                return new RemoveOperation(
61
                    $index,
62
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index)
63
                );
64
65
            case self::OPERATION_REPLACE:
66
                return new ReplaceOperation(
67
                    $index,
68
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
69
                    $this->extractValue($jsonValue, $index)
70
                );
71
72
            case self::OPERATION_TEST:
73
                return new TestOperation(
74
                    $index,
75
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
76
                    $this->extractValue($jsonValue, $index),
77
                    $this->equalComparator
78
                );
79
80
            case self::OPERATION_COPY:
81
                return new CopyOperation(
82
                    $index,
83
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
84
                    $this->extractPathPointer($jsonValue, self::POINTER_FROM, $index)
85
                );
86
87
            case self::OPERATION_MOVE:
88
                return new MoveOperation(
89
                    $index,
90
                    $this->extractPathPointer($jsonValue, self::POINTER_PATH, $index),
91
                    $this->extractPathPointer($jsonValue, self::POINTER_FROM, $index)
92
                );
93
        }
94
95
        throw new Exception\UnknownOperationCodeException($index, $operationCode);
96
    }
97
98
    private function getOperationCode(NodeValueInterface $jsonValue, int $index): string
99
    {
100
        $result = $this
101
            ->pointerProcessor
102
            ->select($this->pointerQueryFactory->createQuery('/op'), $jsonValue);
103
        if (!$result->exists()) {
104
            throw new Exception\OperationCodeNotFoundException($index);
105
        }
106
        $operationCode = $result->decode();
107
        if (is_string($operationCode)) {
108
            return $operationCode;
109
        }
110
111
        throw new Exception\InvalidOperationCodeException($operationCode, $index);
112
    }
113
114
    private function extractPathPointer(NodeValueInterface $operation, string $property, int $index): QueryInterface
115
    {
116
        $result = $this
117
            ->pointerProcessor
118
            ->select($this->pointerQueryFactory->createQuery("/{$property}"), $operation);
119
        if (!$result->exists()) {
120
            throw new Exception\PathNotFoundException($index, $property);
121
        }
122
        $path = $result->decode();
123
        if (!is_string($path)) {
124
            throw new Exception\InvalidPathException($index, $property, $path);
125
        }
126
127
        return $this
128
            ->pointerQueryFactory
129
            ->createQuery($path);
130
    }
131
132
    private function extractValue(NodeValueInterface $operation, int $index): NodeValueInterface
133
    {
134
        $result = $this
135
            ->pointerProcessor
136
            ->select($this->pointerQueryFactory->createQuery('/value'), $operation);
137
138
        if ($result->exists()) {
139
            return $result->get();
140
        }
141
142
        throw new Exception\ValueNotFoundException($index);
143
    }
144
}
145