Passed
Push — master ( f0c5ab...d6277d )
by stéphane
01:45
created

Node::specialProcess()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
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)){
69
            if ($this->_parent instanceof Node) {
70
                return $this->_parent;
71
            } else {
72
                throw new \Exception("Cannnot find a parent for ".get_class($this), 1);
73
            }
74
        }
75
        $cursor = $this->getParent();
76
        while (!($cursor instanceof NodeRoot)
77
                && (is_null($cursor->indent)
78
                || $cursor->indent >= $indent)) {
79
            if ($cursor->_parent) {
80
                $cursor = $cursor->_parent;
81
            } else {
82
                break;
83
            }
84
        }
85
        return $cursor;
86
    }
87
88
    protected function getRoot():Node
89
    {
90
        if (is_null($this->_parent)) {
91
            throw new \Exception(__METHOD__.": can only be used when Node has a parent set", 1);
92
        }
93
        $cursor = $this;
94
        while (!($cursor instanceof NodeRoot) && $cursor->_parent instanceof Node) {
95
            $cursor = $cursor->_parent;
96
        }
97
        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
    public function add(Node $child):Node
111
    {
112
        $child->setParent($this);
113
        if (is_null($this->value)) {
114
            $this->value = $child;
115
        } else {
116
            if ($this->value instanceof Node) {
117
                $this->value = new NodeList($this->value);
118
            }
119
            $this->value->push($child);
120
        }
121
        return $child;
122
    }
123
124
    /**
125
     * Gets the deepest node.
126
     *
127
     * @return Node|self  The deepest node.
128
     */
129
    public function getDeepestNode():Node
130
    {
131
        $cursor = $this;
132
        while ($cursor->value instanceof Node) {
133
            $cursor = $cursor->value;
134
        }
135
        return $cursor;
136
    }
137
138
    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
        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
    public function getTargetOnLessIndent(Node &$node):Node
151
    {
152
        $supposedParent = $this->getParent($node->indent);
153
        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
        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
    public function getTargetOnEqualIndent(Node &$node):Node
175
    {
176
        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
    protected function isAwaitingChild(Node $node):bool
192
    {
193
        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
    public function __debugInfo():array
210
    {
211
        $props = [];
212
        $props['line->indent'] = "$this->line -> $this->indent";
213
        if ($this->identifier) $props['identifier'] = "($this->identifier)";
214
        if ($this->_anchor)    $props['_anchor']    = "($this->_anchor)";
215
        if ($this->_tag)       $props['_tag']       = "($this->_tag)";
216
        if ($this->value)      $props['value']       = $this->value;
217
        // $props['value'] = $this->value;
218
        $props['raw']   = $this->raw;
219
        if (!$this->_parent)  $props['parent'] = 'NO PARENT!!!';
220
        return $props;
221
    }
222
}
223