Passed
Push — master ( e343f8...43624f )
by Edward
05:18
created

ReplaceMutation::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 0
dl 0
loc 2
ccs 0
cts 1
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
declare(strict_types=1);
3
4
namespace Remorhaz\JSON\Path\Processor\Mutator;
5
6
use Generator;
7
use Iterator;
8
use Remorhaz\JSON\Data\Event\AfterElementEventInterface;
9
use Remorhaz\JSON\Data\Event\AfterPropertyEventInterface;
10
use Remorhaz\JSON\Data\Event\BeforeArrayEventInterface;
11
use Remorhaz\JSON\Data\Event\BeforeElementEventInterface;
12
use Remorhaz\JSON\Data\Event\BeforeObjectEventInterface;
13
use Remorhaz\JSON\Data\Event\BeforePropertyEventInterface;
14
use Remorhaz\JSON\Data\Event\EventInterface;
15
use Remorhaz\JSON\Data\Event\ScalarEventInterface;
16
use Remorhaz\JSON\Data\Path\PathInterface;
17
use Remorhaz\JSON\Data\Value\NodeValueInterface;
18
use Remorhaz\JSON\Data\Walker\MutationInterface;
19
use Remorhaz\JSON\Data\Walker\ValueWalkerInterface;
20
use function array_reverse;
21
use function count;
22
23
final class ReplaceMutation implements MutationInterface
24
{
25
26
    private $newNode;
27
28
    private $paths;
29
30
    public function __construct(NodeValueInterface $newNode, PathInterface ...$paths)
31
    {
32
        $this->newNode = $newNode;
33
        $this->paths = $this->getNonNestedPaths(...$paths);
34
    }
35
36
    private function getNonNestedPaths(PathInterface ...$paths): array
37
    {
38
        foreach ($this->createPathPairIterator(...$paths) as $pathPair) {
39
            [$parentPath, $nestedPath] = $pathPair;
40
            if ($parentPath->contains($nestedPath)) {
41
                throw new Exception\ReplaceAtNestedPathsException($parentPath, $nestedPath);
42
            }
43
        }
44
45
        return $paths;
46
    }
47
48
    /**
49
     * @param PathInterface ...$paths
50
     * @return Generator|PathInterface[][]
51
     */
52
    private function createPathPairIterator(PathInterface ...$paths): Generator
53
    {
54
        $pathsCount = count($paths);
55
        for ($i = 0; $i < $pathsCount; $i++) {
56
            for ($j = $i + 1; $j < $pathsCount; $j++) {
57
                $pathPair = [$paths[$i], $paths[$j]];
58
                yield $pathPair;
59
                yield array_reverse($pathPair);
60
            }
61
        }
62
    }
63
64
    public function __invoke(EventInterface $event, ValueWalkerInterface $valueWalker): Iterator
65
    {
66
        return $this->createEventGenerator($event, $valueWalker);
67
    }
68
69
    public function reset(): void
70
    {
71
    }
72
73
    private function createEventGenerator(EventInterface $event, ValueWalkerInterface $valueWalker): Generator
74
    {
75
        foreach ($this->paths as $path) {
76
            if ($path->equals($event->getPath())) {
77
                yield from $this->createReplaceEventGenerator($event, $valueWalker);
78
79
                return;
80
            }
81
            if ($path->contains($event->getPath())) {
82
                return;
83
            }
84
        }
85
        yield $event;
86
    }
87
88
    private function createReplaceEventGenerator(EventInterface $event, ValueWalkerInterface $valueWalker): Generator
89
    {
90
        switch (true) {
91
            case $event instanceof BeforeElementEventInterface:
92
            case $event instanceof BeforePropertyEventInterface:
93
            case $event instanceof AfterElementEventInterface:
94
            case $event instanceof AfterPropertyEventInterface:
95
                yield $event;
96
                break;
97
98
            case $event instanceof ScalarEventInterface:
99
            case $event instanceof BeforeArrayEventInterface:
100
            case $event instanceof BeforeObjectEventInterface:
101
                yield from $valueWalker
102
                    ->createEventIterator($this->newNode, $event->getPath());
103
                break;
104
        }
105
    }
106
}
107