Completed
Push — master ( 3607c7...59cd47 )
by Chris
03:04
created

NodeFactory::createNodeFromValue()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
dl 0
loc 9
ccs 4
cts 5
cp 0.8
rs 9.6666
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 3
crap 2.032
1
<?php declare(strict_types=1);
2
3
namespace DaveRandom\Jom;
4
5
use DaveRandom\Jom\Exceptions\Exception;
6
use DaveRandom\Jom\Exceptions\InvalidNodeValueException;
7
8
abstract class NodeFactory
9
{
10
    private const ENABLE_INVALID_VALUE_IGNORE = 0x8000;
11
    private const IGNORE_INVALID_VALUES = Node::IGNORE_INVALID_VALUES | self::ENABLE_INVALID_VALUE_IGNORE;
12
13
    /**
14
     * @throws InvalidNodeValueException
15
     */
16
    private function throwInvalidValue($value): void
17
    {
18
        /** @noinspection PhpInternalEntityUsedInspection */
19
        throw new InvalidNodeValueException(\sprintf(
20
            "Failed to create node from value of type '%s'",
21
            describe($value)
22
        ));
23
    }
24
25
    /**
26
     * @throws InvalidNodeValueException
27
     * @throws Exception
28
     */
29 101
    final protected function tryCreateNodeFromValue($value, ?Document $ownerDoc, int $flags): ?Node
30
    {
31 101
        $type = \gettype($value);
32
33 101
        switch ($type) {
34
            case 'NULL': {
35 35
                return new NullNode($ownerDoc);
36
            }
37
38
            case 'boolean': case 'integer': case 'double': case 'string': {
39
                $className = [
40
                    'boolean' => BooleanNode::class,
41
                    'integer' => NumberNode::class,
42
                    'double' => NumberNode::class,
43
                    'string' => StringNode::class,
44 64
                ][$type];
45 64
                return new $className($value, $ownerDoc);
46
            }
47
48
            case 'array': {
49 94
                return $this->createNodeFromArrayValue($value, $ownerDoc, $flags);
50
            }
51
52
            case 'object': {
53 64
                $node = $this->createNodeFromObjectValue($value, $ownerDoc, $flags);
54
            }
55
        }
56
57 64
        if (isset($node)) {
58 64
            return $node;
59
        }
60
61
        if (!($flags & Node::IGNORE_INVALID_VALUES)) {
62
            $this->throwInvalidValue($value);
63
        }
64
65
        return null;
66
    }
67
68
    /**
69
     * @throws InvalidNodeValueException
70
     * @throws Exception
71
     */
72 94
    final protected function createArrayNodeFromPackedArray(array $values, ?Document $ownerDoc, int $flags): ArrayNode
73
    {
74 94
        $node = new ArrayNode([], $ownerDoc);
75
76 94
        foreach ($values as $value) {
77 89
            if (null !== $valueNode = $this->tryCreateNodeFromValue($value, $ownerDoc, $flags)) {
78 89
                $node->push($valueNode);
79
            }
80
        }
81
82 94
        return $node;
83
    }
84
85
    /**
86
     * @throws InvalidNodeValueException
87
     * @throws Exception
88
     */
89 64
    final protected function createObjectNodeFromPropertyMap($properties, ?Document $ownerDoc, int $flags): ObjectNode
90
    {
91 64
        $node = new ObjectNode([], $ownerDoc);
92
93 64
        foreach ($properties as $name => $value) {
94 64
            if (null !== $valueNode = $this->tryCreateNodeFromValue($value, $ownerDoc, $flags)) {
95 64
                $node->setProperty($name, $valueNode);
96
            }
97
        }
98
99 64
        return $node;
100
    }
101
102
    /**
103
     * @throws InvalidNodeValueException
104
     * @throws Exception
105
     */
106
    abstract protected function createNodeFromArrayValue(array $array, ?Document $ownerDoc, int $flags): VectorNode;
107
108
    /**
109
     * @throws InvalidNodeValueException
110
     * @throws Exception
111
     */
112
    abstract protected function createNodeFromObjectValue(object $object, ?Document $ownerDoc, int $flags): ?Node;
113
114
    /**
115
     * @throws InvalidNodeValueException
116
     * @throws Exception
117
     */
118 101
    final public function createNodeFromValue($value, ?Document $ownerDoc, int $flags): Node
119
    {
120 101
        $node = $this->tryCreateNodeFromValue($value, $ownerDoc, $flags);
121
122 101
        if ($node === null) {
123
            $this->throwInvalidValue($value);
124
        }
125
126 101
        return $node;
127
    }
128
}
129