Completed
Push — master ( 3eacba...3b6a73 )
by stéphane
02:25
created

NodeFactory::get()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 22
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 7.116

Importance

Changes 0
Metric Value
eloc 16
dl 0
loc 22
ccs 13
cts 15
cp 0.8667
rs 8.8333
c 0
b 0
f 0
cc 7
nc 7
nop 2
crap 7.116
1
<?php
2
3
namespace Dallgoot\Yaml;
4
5
/**
6
 * TODO
7
 *
8
 * @author  Stéphane Rebai <[email protected]>
9
 * @license Apache 2.0
10
 * @link    TODO : url to specific online doc
11
 */
12
final class NodeFactory
13
{
14
    private const JSON_OPTIONS = \JSON_PARTIAL_OUTPUT_ON_ERROR|\JSON_UNESCAPED_SLASHES;
15
16 5
    final public static function get($nodeString = null, $line = 0):Node
17
    {
18 5
        $trimmed = ltrim($nodeString);
19 5
        if ($trimmed === '')                                return new NodeBlank($nodeString, $line);
20 5
        elseif (substr($trimmed, 0, 3) === '...')           return new NodeDocEnd($nodeString, $line);
21 5
        elseif ((bool) preg_match(Regex::KEY, $trimmed, $matches)) return new NodeKey($nodeString, $line, $matches);
22
        else {
23 5
            $first = $trimmed[0];
24 5
            $stringGroups = ["-" ,'>|' ,'"\'',"#%" ,"{[" ,":?" ,'*&!'];
25 5
            $methodGroups = ['Hyphen','Literal','Quoted','Special','Compact','SetElement','NodeAction'];
26 5
            foreach ($stringGroups as $groupIndex => $stringRef) {
27 5
                if (is_int(strpos($stringRef, $first))) {
28 1
                    $methodName = 'on'.$methodGroups[$groupIndex];
29
                    try {
30 1
                        return self::$methodName($first, $nodeString, $line);
31
                    } catch (\Exception|\Error|\ParseError $e) {
32
                        throw new \Exception(" could not create a Node, ", 1, $e);
33
                    }
34
                }
35
            }
36
        }
37 5
        return new NodeScalar($nodeString, $line);
38
    }
39
40
    /**
41
     * Return the correct Node Object between NodeComment OR NodeDirective
42
     *
43
     * @param      string   $nodeString  The node string
44
     * @param      integer  $line         The line
45
     *
46
     * @return     Node
47
     */
48 1
    final private static function onSpecial(string $first, string $nodeString, int $line):Node
49
    {
50 1
        return $first === "#" ? new NodeComment(ltrim($nodeString), $line)
51 1
                              : new NodeDirective(ltrim($nodeString), $line);
52
    }
53
54
    /**
55
     * Set $node type and value when $nodevalue starts with a quote (simple or double)
56
     *
57
     * @param string $nodeString The node value
58
     * @param int    $line       The line
59
     *
60
     * @return     Node
61
     */
62 1
    final private static function onQuoted(string $first, string $nodeString, int $line):Node
63
    {
64 1
        return Regex::isProperlyQuoted(trim($nodeString)) ? new NodeQuoted($nodeString, $line)
65 1
                                                          : new NodePartial($nodeString, $line);
66
    }
67
68
    /**
69
     * Set $node type and value when NodeValue starts with a Set characters "?:"
70
     *
71
     * @param string $nodeString The node value
72
     * @param int    $line       The line
73
     *
74
     * @return     Node
75
     */
76 1
    final private static function onSetElement(string $first, string $nodeString, int $line):Node
77
    {
78 1
        return $first === '?' ? new NodeSetKey($nodeString, $line)
79 1
                              : new NodeSetValue($nodeString, $line);
80
    }
81
82
    /**
83
     * Determines the Node type and value when a compact object/array syntax is found
84
     *
85
     * @param string $nodeString The value assumed to start with { or [ or characters
86
     * @param int    $line       The line
87
     *
88
     * @return     Node
89
     */
90 2
    final private static function onCompact(string $first, string $nodeString, int $line):Node
91
    {
92 2
        json_decode($nodeString, false, 512, self::JSON_OPTIONS);
93 2
        if (json_last_error() === \JSON_ERROR_NONE)             return new NodeJSON($nodeString, $line);
94 1
        elseif ((bool) preg_match(Regex::MAPPING, trim($nodeString)))  return new NodeCompactMapping($nodeString, $line);
95 1
        elseif ((bool) preg_match(Regex::SEQUENCE, trim($nodeString))) return new NodeCompactSequence($nodeString, $line);
96
        else {
97 1
            return new NodePartial($nodeString, $line);
98
        }
99
    }
100
101
    /**
102
     * Determines Node type and value when an hyphen "-" is found
103
     *
104
     * @param string $nodeString The node string value
105
     * @param int    $line       The line
106
     *
107
     * @return     Node
108
     */
109 1
    final private static function onHyphen(string $first, string $nodeString, int $line):Node
110
    {
111 1
        if (substr($nodeString, 0, 3) === '---')              return new NodeDocStart($nodeString, $line);
112 1
        elseif ((bool) preg_match(Regex::ITEM, ltrim($nodeString)))  return new NodeItem($nodeString, $line);
113
        else {
114 1
            return new NodeScalar($nodeString, $line);
115
        }
116
    }
117
118
    /**
119
     * Sets Node type and value according to $nodeString when one of these characters is found : !,&,*
120
     *
121
     * @param string $nodeString The node value
122
     * @param int    $line       The line
123
     *
124
     */
125 1
    final private static function onNodeAction(string $first, string $nodeString, int $line):Node
126
    {
127 1
        if (!((bool) preg_match(Regex::NODE_ACTIONS, trim($nodeString), $matches))) {
128 1
            return new NodeScalar($nodeString, $line);
129
        }
130 1
        $action = trim($matches['action']);//var_dump($matches);
131 1
        switch ($action[0]) {
132 1
            case '!': return new NodeTag   ($nodeString, $line);
133 1
            case '&': return new NodeAnchor($nodeString, $line);
134 1
            case '*': return new NodeAnchor($nodeString, $line);
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return Dallgoot\Yaml\Node. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
135
            // default:
136
            //     throw new \ParseError("Not a action node !! '$action[0]' on line:$line".gettype($first));
137
        }
138
    }
139
140 2
    final private static function onLiteral(string $first, string $nodeString, int $line):Node
141
    {
142 2
        switch ($first) {
143 2
            case '>': return new NodeLitFolded($nodeString, $line);
144 2
            case '|': return new NodeLit($nodeString, $line);
145
            default:
146 1
                throw new \ParseError("Not a literal node !! '$first' on line:$line");
147
        }
148
    }
149
150
}