Completed
Push — master ( c91a90...e32b70 )
by Chris
02:54
created

Node::containsChild()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 0
cts 1
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
1
<?php declare(strict_types=1);
2
3
namespace DaveRandom\Jom;
4
5
use DaveRandom\Jom\Exceptions\InvalidNodeValueException;
6
use DaveRandom\Jom\Exceptions\InvalidReferenceNodeException;
7
8
\DaveRandom\Jom\initialize(Node::class);
9
10
abstract class Node implements \JsonSerializable, Taggable
11
{
12
    use TagData;
13
14
    public const IGNORE_INVALID_VALUES = 0b01;
15
    public const PERMIT_INCORRECT_REFERENCE_TYPE = 0b10;
16
17
    /** @var NodeFactory */
18
    private static $nodeFactory;
19
20
    /** @var Document|null */
21
    protected $ownerDocument;
22
23
    /** @var string|int|null */
24
    protected $key;
25
26
    /** @var VectorNode|null */
27
    protected $parent;
28
29
    /** @var Node|null */
30
    protected $previousSibling;
31
32
    /** @var Node|null */
33 37
    protected $nextSibling;
34
35 37
    /** @uses __init() */
36 37
    private static function __init(): void
37
    {
38
        self::$nodeFactory = new UnsafeNodeFactory();
39
    }
40
41
    /**
42
     * @param mixed $value
43
     * @throws InvalidNodeValueException
44
     */
45
    private static function validateCreatedNodeType(Node $node, string $expectedType, $value, ?int $flags): Node
46
    {
47
        if ($node instanceof $expectedType || ($flags & self::PERMIT_INCORRECT_REFERENCE_TYPE)) {
48
            return $node;
49
        }
50
51
        throw new InvalidNodeValueException(\sprintf(
52
            "Value of type %s parsed as instance of %s, instance of %s expected",
53 37
            describe($value),
54
            \get_class($node),
55 37
            $expectedType
56
        ));
57
    }
58 37
59 37
    /**
60
     * @param bool|int|float|string|array|object|null A value that can be encoded as JSON
61
     * @throws InvalidNodeValueException
62
     * @return static
63
     */
64
    public static function createFromValue($value, ?Document $ownerDocument = null, ?int $flags = 0): Node
65
    {
66
        try {
67
            $result = self::$nodeFactory->createNodeFromValue($value, $ownerDocument, $flags ?? 0);
68
        } catch (InvalidNodeValueException $e) {
69 37
            throw $e;
70
        //@codeCoverageIgnoreStart
71
        } catch (\Exception $e) {
72 165
            throw unexpected($e);
73
        }
74 165
        //@codeCoverageIgnoreEnd
75
76
        return self::validateCreatedNodeType($result, static::class, $value, $flags);
77
    }
78
79
    protected function __construct(?Document $ownerDocument)
80
    {
81
        $this->ownerDocument = $ownerDocument;
82 151
    }
83
84 151
    public function __clone()
85 151
    {
86 151
        $this->setReferences(null, null, null, null);
87 151
    }
88
89
    final protected function setReferences(?VectorNode $parent, $key, ?Node $previousSibling, ?Node $nextSibling): void
90 47
    {
91
        $this->parent = $parent;
92 47
        $this->key = $key;
93
        $this->previousSibling = $previousSibling;
94
        $this->nextSibling = $nextSibling;
95 7
    }
96
97 7
    final public function getParent(): ?VectorNode
98
    {
99
        return $this->parent;
100 7
    }
101
102 7
    final public function getPreviousSibling(): ?Node
103
    {
104
        return $this->previousSibling;
105
    }
106
107
    final public function getNextSibling(): ?Node
108
    {
109
        return $this->nextSibling;
110
    }
111
112
    public function hasChildren(): bool
113
    {
114
        return false;
115
    }
116
117
    public function containsChild(Node $child): bool
118
    {
119
        return $child !== $child;
120
    }
121
122
    public function getFirstChild(): ?Node
123
    {
124
        return null;
125 49
    }
126
127 49
    public function getLastChild(): ?Node
128
    {
129
        return null;
130
    }
131
132
    final public function getOwnerDocument(): ?Document
133 50
    {
134
        return $this->ownerDocument;
135 50
    }
136
137
    /**
138
     * @return string|int|null
139
     */
140
    final public function getKey()
141
    {
142 11
        return $this->key;
143
    }
144 11
145 11
    /**
146 11
     * @return Node[]
147 11
     * @throws InvalidReferenceNodeException
148 11
     */
149
    final public function getAncestors(?Node $root = null): array
150 11
    {
151 9
        $path = [$this];
152 9
        $current = $this->parent;
153
        $rootParent = $root !== null
154
            ? $root->parent
155 11
            : null;
156
157
        while ($current !== $rootParent && $current !== null) {
158
            $path[] = $current;
159 11
            $current = $current->parent;
160
        }
161
162
        if ($current !== $rootParent) {
163
            throw new InvalidReferenceNodeException('Path target node is not an ancestor of the subject node');
164
        }
165
166
        return $path;
167
    }
168
169
    abstract public function getValue();
170
    abstract public function jsonSerialize();
171
}
172