Passed
Push — master ( 3b6a73...d590ba )
by stéphane
02:55
created

Node::__debugInfo()   A

Complexity

Conditions 6
Paths 32

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 9
dl 0
loc 12
ccs 10
cts 10
cp 1
rs 9.2222
c 0
b 0
f 0
cc 6
nc 32
nop 0
crap 6
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
    protected $identifier;
15
    /** @var null|Node */
16
    protected $_parent;
17
18
    /** @var int */
19
    public $indent = -1;
20
    /** @var int */
21
    public $line;
22
    /** @var null|string */
23
    public $raw;
24
    /** @var null|Node|NodeList */
25
    public $value;
26
    /** @var string|null */
27
    public $anchor;
28
    /** @var string|null */
29
    public $tag;
30
31
    /**
32
     * Create the Node object and parses $nodeString
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 14
    public function __construct(string $nodeString, $line = 0)
39
    {
40 14
        $this->raw    = $nodeString;
41 14
        $this->line   = (int) $line;
42 14
        $nodeValue    = preg_replace("/^\t+/m", " ", $nodeString);
43 14
        $this->indent = strspn($nodeValue, ' ');
44 14
    }
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 8
    protected function setParent(Node $node):Node
54
    {
55 8
        $this->_parent = $node;
56 8
        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 4
    public function getParent(int $indent = null):Node
67
    {
68 4
        if (!is_int($indent)){
69 4
            if ($this->_parent instanceof Node) {
70 3
                return $this->_parent;
71
            } else {
72 1
                throw new \Exception("Cannnot find a parent for ".get_class($this), 1);
73
            }
74
        }
75 2
        $cursor = $this->getParent();
76 2
        while (!($cursor instanceof NodeRoot)
77 2
                && (is_null($cursor->indent)
78 2
                || $cursor->indent >= $indent)) {
79 1
            if ($cursor->_parent) {
80 1
                $cursor = $cursor->_parent;
81
            } else {
82
                break;
83
            }
84
        }
85 2
        return $cursor;
86
    }
87
88
    /**
89
     * Gets the root of the structure map (or current Yaml document)
90
     *
91
     * @throws     \Exception  (description)
92
     *
93
     * @return     Node|self   The root.
94
     */
95 2
    protected function getRoot():Node
96
    {
97 2
        if (is_null($this->_parent)) {
98 1
            throw new \Exception(__METHOD__.": can only be used when Node has a parent set", 1);
99
        }
100 1
        $cursor = $this;
101 1
        while (!($cursor instanceof NodeRoot) && $cursor->_parent instanceof Node) {
102 1
            $cursor = $cursor->_parent;
103
        }
104 1
        return $cursor;
105
    }
106
107
    /**
108
     * Set the value for the current Node :
109
     * - if value is null , then value = $child (Node)
110
     * - if value is Node, then value is a NodeList with (previous value AND $child)
111
     * - if value is a NodeList, push $child into
112
     *
113
     * @param Node $child The child
114
     *
115
     * @return Node
116
     */
117 7
    public function add(Node $child):Node
118
    {
119 7
        $child->setParent($this);
120 7
        if (is_null($this->value)) {
121 6
            $this->value = $child;
122
        } else {
123 5
            if ($this->value instanceof Node) {
124 3
                $this->value = new NodeList($this->value);
125
            }
126 5
            $this->value->push($child);
127
        }
128 7
        return $child;
129
    }
130
131
    /**
132
     * Gets the deepest node.
133
     *
134
     * @return Node|self  The deepest node.
135
     */
136 1
    public function getDeepestNode():Node
137
    {
138 1
        $cursor = $this;
139 1
        while ($cursor->value instanceof Node) {
140 1
            $cursor = $cursor->value;
141
        }
142 1
        return $cursor;
143
    }
144
145 1
    public function specialProcess(Node &$previous, array &$emptyLines):bool
0 ignored issues
show
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

145
    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...
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

145
    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...
146
    {
147 1
        return false;
148
    }
149
150
   /**
151
     * Find parent target when current Node indentation is lesser than previous node indentation
152
     *
153
     * @param Node $previous The previous
154
     *
155
     * @return Node
156
     */
157 1
    public function getTargetOnLessIndent(Node &$node):Node
158
    {
159 1
        $supposedParent = $this->getParent($node->indent);
160 1
        if ($node instanceof NodeItem && $supposedParent instanceof NodeRoot) {
161
            if ($supposedParent->value->has('NodeKey')) {
162
                $lastKey = null;
163
                foreach ($supposedParent->value as $key => $child) {
164
                    if ($child instanceof NodeKey) {
165
                        $lastKey = $child;
166
                    }
167
                }
168
                return $lastKey;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $lastKey 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...
169
            }
170
        }
171 1
        return $supposedParent;
172
    }
173
174
    /**
175
     * Find parent target when current Node indentation is equal to previous node indentation
176
     *
177
     * @param Node $previous The previous
178
     *
179
     * @return Node
180
     */
181 1
    public function getTargetOnEqualIndent(Node &$node):Node
182
    {
183 1
        return $this->getParent();
184
    }
185
186
   /**
187
     * Find parent target when current Node indentation is superior than previous node indentation
188
     *
189
     * @param Node $previous The previous
190
     *
191
     * @return Node
192
     */
193
    public function getTargetOnMoreIndent(Node &$node):Node
194
    {
195
        return $this->isAwaitingChild($node) ? $this : $this->getParent();
196
    }
197
198 1
    protected function isAwaitingChild(Node $node):bool
199
    {
200 1
        return false;
201
    }
202
203
    /**
204
     *
205
     * @param Array|Object|null         $parent The parent collector or NULL otherwise
206
     *
207
     * @return mixed  whatever the build process returns
208
     */
209
    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...
210
211
    /**
212
     * PHP internal function for debugging purpose : simplify output provided by 'var_dump'
213
     *
214
     * @return array  the Node properties and respective values displayed by 'var_dump'
215
     */
216 1
    public function __debugInfo():array
217
    {
218 1
        $props = [];
219 1
        $props['line->indent'] = "$this->line -> $this->indent";
220 1
        if ($this->identifier) $props['identifier'] = "($this->identifier)";
221 1
        if ($this->anchor)     $props['anchor']     = "($this->anchor)";
222 1
        if ($this->tag)        $props['tag']        = "($this->tag)";
223 1
        if ($this->value)      $props['value']      = $this->value;
224
        // $props['value'] = $this->value;
225 1
        $props['raw']   = $this->raw;
226 1
        if (!$this->_parent)  $props['parent'] = 'NO PARENT!!!';
227 1
        return $props;
228
    }
229
}
230