Passed
Push — master ( d9f8e7...9b6b4f )
by Pierrick
07:21
created

ReferenceNode::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 4
nc 1
nop 4
dl 0
loc 6
ccs 5
cts 5
cp 1
crap 1
rs 10
c 1
b 0
f 0
1
<?php
2
/**
3
 * This file is part of NACL.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 *
8
 * @copyright 2019 Nuglif (2018) Inc.
9
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
10
 * @author    Pierrick Charron <[email protected]>
11
 * @author    Charle Demers <[email protected]>
12
 */
13
14
namespace Nuglif\Nacl;
15
16
class ReferenceNode extends Node
17
{
18
    const ROOT = '/';
19
20
    private $path;
21
    private $isResolving = false;
22
    private $isResolved  = false;
23
    private $file;
24
    private $line;
25
    private $value;
26
    private $options;
27
28 7
    public function __construct($path, $file, $line, ObjectNode $options)
29
    {
30 7
        $this->path = $path;
31 7
        $this->file = $file;
32 7
        $this->line = $line;
33 7
        $this->options = $options;
34 7
    }
35
36 7
    public function getNativeValue()
37
    {
38 7
        if (!$this->isResolved) {
39 7
            $this->resolve();
40 4
        }
41
42 4
        return $this->value;
43
    }
44
45 7
    private function resolve()
46
    {
47 7
        if ($this->isResolving) {
48 1
            throw new ReferenceException('Circular dependence detected.', $this->file, $this->line);
49
        }
50 7
        if ($this->path instanceof Node) {
51 2
            $this->path = $this->path->getNativeValue();
52 2
        }
53 7
        if (!is_string($this->path)) {
54 1
            throw new ReferenceException(sprintf('.ref expects parameter to be string, %s given.', gettype($this->path)), $this->file, $this->line);
55
        }
56
57 6
        $this->isResolving = true;
58 6
        $value             = $this->isAbsolute() ? $this->getRoot() : $this->getParent();
59
60 6
        foreach (explode('/', ltrim($this->path, self::ROOT)) as $path) {
61
            switch ($path) {
62 6
                case '.':
63 6
                case '':
64 2
                    break;
65 6
                case '..':
66 1
                    $value = $value->getParent();
67 1
                    break;
68 6
                default:
69 6
                    if (!isset($value[$path])) {
70 3
                        if ($this->options->has('default')) {
71 2
                            $value = $this->options['default'];
72 2
                            break 2;
73
                        } else {
74 1
                            throw new ReferenceException(sprintf('Undefined property: %s.', $this->path), $this->file, $this->line);
75
                        }
76
                    }
77 4
                    $value = $value[$path];
78 6
            }
79 5
        }
80
81 5
        if ($value instanceof Node) {
82 1
            $value = $value->getNativeValue();
83
        }
84
85 4
        $this->isResolving = false;
86 4
        $this->isResolved  = true;
87 4
        $this->value       = $value;
88 4
    }
89
90 6
    private function isAbsolute()
91
    {
92 6
        return self::ROOT === substr($this->path, 0, 1);
93
    }
94
}
95