Passed
Push — dev ( 0679fe...0efacf )
by Fike
05:23
created

Accessor::enumerateNodes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 16
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 16
ccs 12
cts 12
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 12
nc 2
nop 2
crap 2

1 Method

Rating   Name   Duplication   Size   Complexity  
A Accessor::findNode() 0 3 1
1
<?php
2
3
namespace AmaTeam\TreeAccess;
4
5
use AmaTeam\TreeAccess\API\AccessorInterface;
6
use AmaTeam\TreeAccess\API\ActiveNodeFactoryInterface;
7
use AmaTeam\TreeAccess\API\Exception\IllegalTargetException;
8
use AmaTeam\TreeAccess\API\NodeInterface;
9
use AmaTeam\TreeAccess\API\TypeAccessorInterface;
10
use AmaTeam\TreeAccess\Locator\Context;
11
use AmaTeam\TreeAccess\Type\Registry;
12
13
class Accessor implements AccessorInterface, ActiveNodeFactoryInterface
14
{
15
    /**
16
     * @var Locator
17
     */
18
    private $locator;
19
    /**
20
     * @var Registry
21
     */
22
    private $registry;
23
24
    /**
25
     * @param Registry $registry
26
     */
27 21
    public function __construct(Registry $registry)
28
    {
29 21
        $this->registry = $registry;
30 21
        $this->locator = new Locator($registry);
31 21
    }
32
33
    /**
34
     * @inheritDoc
35
     */
36 14
    public function getNode(&$root, $path)
37
    {
38 14
        return $this->traverse($root, $path, new Context(false, false));
39
    }
40
41
    /**
42
     * @inheritDoc
43
     */
44 5
    public function findNode(&$root, $path)
45
    {
46 5
        return $this->traverse($root, $path, new Context(true, true));
47
    }
48
49
    /**
50
     * @param mixed $root
51
     * @param string|string[] $path
52
     * @param Context $context
53
     * @return NodeInterface|null
54
     */
55 19
    private function traverse(&$root, $path, Context $context)
56
    {
57 19
        $node = new Node([], $root);
58 19
        return $this->locator->locate($node, Paths::normalize($path), $context);
59
    }
60
61
    /**
62
     * @inheritDoc
63
     */
64 7
    public function read(&$root, $path)
65
    {
66 7
        $path = Paths::normalize($path);
67 7
        $node = $this->getNode($root, $path);
68 5
        return $node->getValue();
69
    }
70
71
    /**
72
     * @inheritDoc
73
     */
74 3
    public function enumerate(&$root, $path)
75
    {
76 3
        $normalizedPath = Paths::normalize($path);
77 3
        $parent = $this->getNode($root, $normalizedPath);
78 3
        $accessor = $this->getAccessor($parent->getValue(), $normalizedPath);
79 2
        $target = [];
80 2
        foreach ($accessor->enumerate($parent->getValue()) as $name => $node) {
81 2
            $nodePath = array_merge($normalizedPath, $node->getPath());
82 2
            $target[$name] = Node::withPath($node, $nodePath);
83
        }
84 2
        return $target;
85
    }
86
87
    /**
88
     * @inheritDoc
89
     */
90 7
    public function write(&$root, $path, $value)
91
    {
92 7
        $normalizedPath = Paths::normalize($path);
93 7
        if (empty($normalizedPath)) {
94 2
            $root = $value;
95 2
            return;
96
        }
97 5
        $key = $normalizedPath[sizeof($normalizedPath) - 1];
98 5
        $parentPath = array_slice($normalizedPath, 0, -1);
99 5
        $parent = $this->getNode($root, $parentPath);
100 5
        $accessor = $this->getAccessor($parent->getValue(), $parentPath);
101 4
        $parentValue = &$parent->getValue();
102 4
        $accessor->write($parentValue, $key, $value);
103 4
    }
104
105
    /**
106
     * @inheritDoc
107
     */
108 5
    public function exists($root, $path)
109
    {
110 5
        $normalizedPath = Paths::normalize($path);
111 5
        return $this->findNode($root, $normalizedPath) !== null;
112
    }
113
114
    /**
115
     * @param $value
116
     * @param array $path
117
     *
118
     * @return TypeAccessorInterface
119
     *
120
     * @throws IllegalTargetException
121
     */
122 7
    private function getAccessor($value, array $path)
123
    {
124 7
        $accessor = $this->registry->getAccessor(gettype($value));
125 7
        if (!$accessor) {
126 2
            throw new IllegalTargetException($path);
127
        }
128 5
        return $accessor;
129
    }
130
131
    /**
132
     * @inheritDoc
133
     */
134 4
    public function wrap(&$structure)
135
    {
136 4
        return new ActiveNode($this, [], $structure);
137
    }
138
}
139