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

Node::setParent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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 1
    protected function getRoot():Node
89
    {
90 1
        if (is_null($this->_parent)) {
91
            throw new \Exception(__METHOD__.": can only be used when Node has a parent set", 1);
92
        }
93 1
        $cursor = $this;
94 1
        while (!($cursor instanceof NodeRoot) && $cursor->_parent instanceof Node) {
95 1
            $cursor = $cursor->_parent;
96
        }
97 1
        return $cursor;
98
    }
99
100
    /**
101
     * Set the value for the current Node :
102
     * - if value is null , then value = $child (Node)
103
     * - if value is Node, then value is a NodeList with (previous value AND $child)
104
     * - if value is a NodeList, push $child into
105
     *
106
     * @param Node $child The child
107
     *
108
     * @return Node
109
     */
110 7
    public function add(Node $child):Node
111
    {
112 7
        $child->setParent($this);
113 7
        if (is_null($this->value)) {
114 6
            $this->value = $child;
115
        } else {
116 5
            if ($this->value instanceof Node) {
117 3
                $this->value = new NodeList($this->value);
118
            }
119 5
            $this->value->push($child);
120
        }
121 7
        return $child;
122
    }
123
124
    /**
125
     * Gets the deepest node.
126
     *
127
     * @return Node|self  The deepest node.
128
     */
129 1
    public function getDeepestNode():Node
130
    {
131 1
        $cursor = $this;
132 1
        while ($cursor->value instanceof Node) {
133 1
            $cursor = $cursor->value;
134
        }
135 1
        return $cursor;
136
    }
137
138 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

138
    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

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