Passed
Push — master ( 844759...f0c5ab )
by stéphane
07:52
created

Node::getScalar()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 14
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 5
nop 1
dl 0
loc 14
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
namespace Dallgoot\Yaml;
4
5
/**
6
 *
7
 * @author  Stéphane Rebai <[email protected]>
8
 * @license Apache 2.0
9
 * @link    TODO : url to specific online doc
10
 */
11
abstract class Node
12
{
13
    /** @var null|string|boolean */
14
    public $identifier;
15
    /** @var int */
16
    public $indent = -1;
17
    /** @var int */
18
    public $line;
19
    /** @var null|string */
20
    public $raw;
21
    /** @var null|Node|NodeList */
22
    public $value;
23
24
    /** @var string|null */
25
    public $_anchor;
26
    /** @var null|Node */
27
    protected $_parent;
28
    /** @var string|null */
29
    public $_tag;
30
31
    /**
32
     * Create the Node object and parses $nodeString IF not null (else assume a root type Node)
33
     *
34
     * @param string|null $nodeString The node string
35
     * @param int|null    $line       The line
36
     * @todo make it more permissive to tabs but replacement
37
     */
38
    public function __construct(string $nodeString = null, $line = 0)
39
    {
40
        $this->raw = $nodeString;
41
        $this->line = (int) $line;
42
        $nodeValue = preg_replace("/^\t+/m", " ", $nodeString);
43
        $this->indent = strspn($nodeValue, ' ');
44
    }
45
46
    /**
47
     * Sets the parent of the current Node
48
     *
49
     * @param Node $node The node
50
     *
51
     * @return Node|self The currentNode
52
     */
53
    protected function setParent(Node $node):Node
54
    {
55
        $this->_parent = $node;
56
        return $this;
57
    }
58
59
    /**
60
     * Gets the ancestor with specified $indent or the direct $_parent
61
     *
62
     * @param int|null $indent The indent
63
     *
64
     * @return Node   The parent.
65
     */
66
    public function getParent(int $indent = null):Node
67
    {
68
        if (!is_int($indent)) return $this->_parent;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->_parent could return the type null which is incompatible with the type-hinted return Dallgoot\Yaml\Node. Consider adding an additional type-check to rule them out.
Loading history...
69
        $cursor = $this->getParent();
70
        while (!($cursor instanceof NodeRoot)
71
                && (is_null($cursor->indent)
72
                || $cursor->indent >= $indent)) {
73
            $cursor = $cursor->_parent;
74
        }
75
        return $cursor;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $cursor could return the type null which is incompatible with the type-hinted return Dallgoot\Yaml\Node. Consider adding an additional type-check to rule them out.
Loading history...
76
    }
77
78
    protected function getRoot():Node
79
    {
80
        if (is_null($this->_parent)) {
81
            throw new \Exception(__METHOD__.": can only be used when Node has a parent set", 1);
82
        }
83
        $cursor = $this;
84
        while (!($cursor instanceof NodeRoot) && $cursor->_parent instanceof Node) {
85
            $cursor = $cursor->_parent;
86
        }
87
        return $cursor;
88
    }
89
90
    /**
91
     * Set the value for the current Node :
92
     * - if value is null , then value = $child (Node)
93
     * - if value is Node, then value is a NodeList with (previous value AND $child)
94
     * - if value is a NodeList, push $child into
95
     *
96
     * @param Node $child The child
97
     *
98
     * @return Node
99
     */
100
    public function add(Node $child):Node
101
    {
102
        $child->setParent($this);
103
        if (is_null($this->value)) {
104
            $this->value = $child;
105
        } else {
106
            if ($this->value instanceof Node) {
107
                $this->value = new NodeList($this->value);
108
            }
109
            $this->value->push($child);
110
        }
111
        return $child;
112
    }
113
114
    /**
115
     * Gets the deepest node.
116
     *
117
     * @return Node|self  The deepest node.
118
     */
119
    public function getDeepestNode():Node
120
    {
121
        $cursor = $this;
122
        while ($cursor->value instanceof Node) {
123
            $cursor = $cursor->value;
124
        }
125
        return $cursor;
126
    }
127
128
    public function specialProcess(Node &$previous, array &$emptyLines):bool
0 ignored issues
show
Unused Code introduced by
The parameter $emptyLines is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

128
    public function specialProcess(Node &$previous, /** @scrutinizer ignore-unused */ array &$emptyLines):bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $previous is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

128
    public function specialProcess(/** @scrutinizer ignore-unused */ Node &$previous, array &$emptyLines):bool

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
129
    {
130
        return false;
131
    }
132
133
   /**
134
     * Find parent target when current Node indentation is lesser than previous node indentation
135
     *
136
     * @param Node $previous The previous
137
     *
138
     * @return Node
139
     */
140
    public function getTargetOnLessIndent(Node &$node):Node
141
    {
142
        $supposedParent = $this->getParent($node->indent);
143
        if ($node instanceof NodeItem && $supposedParent instanceof NodeRoot) {
144
            if ($supposedParent->value->has('NodeKey')) {
0 ignored issues
show
Bug introduced by
The method has() does not exist on Dallgoot\Yaml\Node. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

144
            if ($supposedParent->value->/** @scrutinizer ignore-call */ has('NodeKey')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method has() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

144
            if ($supposedParent->value->/** @scrutinizer ignore-call */ has('NodeKey')) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145
                $lastKey = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $lastKey is dead and can be removed.
Loading history...
146
                foreach ($supposedParent->value as $key => $child) {
147
                    if ($child instanceof NodeKey) {
148
                        $lastKey = $child;
149
                    }
150
                }
151
                return $child;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $child seems to be defined by a foreach iteration on line 146. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
152
            }
153
        }
154
        return $supposedParent;
155
    }
156
157
    /**
158
     * Find parent target when current Node indentation is equal to previous node indentation
159
     *
160
     * @param Node $previous The previous
161
     *
162
     * @return Node
163
     */
164
    public function getTargetOnEqualIndent(Node &$node):Node
165
    {
166
        return $this->getParent();
167
    }
168
169
   /**
170
     * Find parent target when current Node indentation is superior than previous node indentation
171
     *
172
     * @param Node $previous The previous
173
     *
174
     * @return Node
175
     */
176
    public function getTargetOnMoreIndent(Node &$node):Node
177
    {
178
        return $this->isAwaitingChild($node) ? $this : $this->getParent();
179
    }
180
181
    protected function isAwaitingChild(Node $node):bool
182
    {
183
        return false;
184
    }
185
186
    /**
187
     *
188
     * @param Array|Object|null         $parent The parent collector or NULL otherwise
189
     *
190
     * @return mixed  whatever the build process returns
191
     */
192
    abstract function build(&$parent = null);
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
193
194
    /**
195
     * PHP internal function for debugging purpose : simplify output provided by 'var_dump'
196
     *
197
     * @return array  the Node properties and respective values displayed by 'var_dump'
198
     */
199
    public function __debugInfo():array
200
    {
201
        $props = [];
202
        $props['line->indent'] = "$this->line -> $this->indent";
203
        if ($this->identifier) $props['identifier'] = "($this->identifier)";
204
        if ($this->_anchor)    $props['_anchor']    = "($this->_anchor)";
205
        if ($this->_tag)       $props['_tag']       = "($this->_tag)";
206
        if ($this->value)      $props['value']       = $this->value;
207
        // $props['value'] = $this->value;
208
        $props['raw']   = $this->raw;
209
        if (!$this->_parent)  $props['parent'] = 'NO PARENT!!!';
210
        return $props;
211
    }
212
}
213