Completed
Push — master ( 59cd47...9463bf )
by Chris
03:15
created

NodeFactory::createNodeFromScalarValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 10
ccs 3
cts 3
cp 1
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 7
nc 1
nop 2
crap 1
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
     * @uses createNullNode
27
     */
28 35
    private function createNullNode(?Document $ownerDoc): NullNode
29
    {
30 35
        return new NullNode($ownerDoc);
31
    }
32
33
    /**
34
     * @uses createNodeFromScalarValue
35
     */
36 64
    private function createNodeFromScalarValue(?Document $ownerDoc, $value): Node
37
    {
38
        $className = [
39
            'boolean' => BooleanNode::class,
40
            'integer' => NumberNode::class,
41
            'double' => NumberNode::class,
42
            'string' => StringNode::class,
43 64
        ][\gettype($value)];
44
45 64
        return new $className($value, $ownerDoc);
46
    }
47
48
    /**
49
     * @throws InvalidNodeValueException
50
     * @throws Exception
51
     */
52 101
    final protected function tryCreateNodeFromValue($value, ?Document $ownerDoc, int $flags): ?Node
53
    {
54 101
        $type = \gettype($value);
55
56
        $factory = [
57
            'NULL'    => 'createNullNode',
58
            'boolean' => 'createNodeFromScalarValue',
59
            'integer' => 'createNodeFromScalarValue',
60
            'double'  => 'createNodeFromScalarValue',
61
            'string'  => 'createNodeFromScalarValue',
62
            'array'   => 'createNodeFromArrayValue',
63
            'object'  => 'createNodeFromObjectValue',
64 101
        ][$type] ?? null;
65
66 101
        if ($factory !== null) {
67 101
            $node = $this->{$factory}($ownerDoc, $value, $flags);
68
        }
69
70 101
        if (isset($node)) {
71 101
            return $node;
72
        }
73
74
        if (!($flags & Node::IGNORE_INVALID_VALUES)) {
75
            $this->throwInvalidValue($value);
76
        }
77
78
        return null;
79
    }
80
81
    /**
82
     * @throws InvalidNodeValueException
83
     * @throws Exception
84
     */
85 94
    final protected function createArrayNodeFromPackedArray(array $values, ?Document $ownerDoc, int $flags): ArrayNode
86
    {
87 94
        $node = new ArrayNode([], $ownerDoc);
88
89 94
        foreach ($values as $value) {
90 89
            if (null !== $valueNode = $this->tryCreateNodeFromValue($value, $ownerDoc, $flags)) {
91 89
                $node->push($valueNode);
92
            }
93
        }
94
95 94
        return $node;
96
    }
97
98
    /**
99
     * @throws InvalidNodeValueException
100
     * @throws Exception
101
     */
102 64
    final protected function createObjectNodeFromPropertyMap($properties, ?Document $ownerDoc, int $flags): ObjectNode
103
    {
104 64
        $node = new ObjectNode([], $ownerDoc);
105
106 64
        foreach ($properties as $name => $value) {
107 64
            if (null !== $valueNode = $this->tryCreateNodeFromValue($value, $ownerDoc, $flags)) {
108 64
                $node->setProperty($name, $valueNode);
109
            }
110
        }
111
112 64
        return $node;
113
    }
114
115
    /**
116
     * @throws InvalidNodeValueException
117
     * @throws Exception
118
     */
119
    abstract protected function createNodeFromArrayValue(?Document $ownerDoc, array $array, int $flags): VectorNode;
120
121
    /**
122
     * @throws InvalidNodeValueException
123
     * @throws Exception
124
     */
125
    abstract protected function createNodeFromObjectValue(?Document $ownerDoc, object $object, int $flags): ?Node;
126
127
    /**
128
     * @throws InvalidNodeValueException
129
     * @throws Exception
130
     */
131 101
    final public function createNodeFromValue($value, ?Document $ownerDoc, int $flags): Node
132
    {
133 101
        $node = $this->tryCreateNodeFromValue($value, $ownerDoc, $flags);
134
135 101
        if ($node === null) {
136
            $this->throwInvalidValue($value);
137
        }
138
139 101
        return $node;
140
    }
141
}
142