Completed
Push — master ( 61654e...7ad95f )
by Colin
02:55
created

Node::previous()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
crap 1
1
<?php
2
3
namespace League\CommonMark\Node;
4
5
use League\CommonMark\Util\ArrayCollection;
6
7
abstract class Node
8
{
9
    /**
10
     * @var int
11
     */
12
    protected $depth = 0;
13
14
    /**
15
     * @var Node|null
16
     */
17
    protected $parent;
18
19
    /**
20
     * @var Node|null
21
     */
22
    protected $previous;
23
24
    /**
25
     * @var Node|null
26
     */
27
    protected $next;
28
29
    /**
30
     * @var Node|null
31
     */
32
    protected $firstChild;
33
34
    /**
35
     * @var Node|null
36
     */
37
    protected $lastChild;
38
39
    /**
40
     * @return Node|null
41
     */
42 15
    public function previous()
43
    {
44 15
        return $this->previous;
45
    }
46
47
    /**
48
     * @return Node|null
49
     */
50 1947
    public function next()
51
    {
52 1947
        return $this->next;
53
    }
54
55
    /**
56
     * @return Node|null
57
     */
58 1962
    public function parent()
59
    {
60 1962
        return $this->parent;
61
    }
62
63
    /**
64
     * @param Node|null $node
65
     */
66 1986
    protected function setParent(Node $node = null)
67
    {
68 1986
        $this->parent = $node;
69 1986
        $this->depth = ($node === null) ? 0 : $node->depth + 1;
70 1986
    }
71
72
    /**
73
     * Inserts the $sibling node after $this
74
     *
75
     * @param Node $sibling
76
     */
77 1503
    public function insertAfter(Node $sibling)
78
    {
79 1503
        $sibling->detach();
80 1503
        $sibling->next = $this->next;
81
82 1503
        if ($sibling->next) {
83 618
            $sibling->next->previous = $sibling;
84 206
        }
85
86 1503
        $sibling->previous = $this;
87 1503
        $this->next = $sibling;
88 1503
        $sibling->setParent($this->parent);
89
90 1503
        if (!$sibling->next) {
91 1503
            $sibling->parent->lastChild = $sibling;
92 501
        }
93 1503
    }
94
95
    /**
96
     * Inserts the $sibling node before $this
97
     *
98
     * @param Node $sibling
99
     */
100 9
    public function insertBefore(Node $sibling)
101
    {
102 9
        $sibling->detach();
103 9
        $sibling->previous = $this->previous;
104
105 9
        if ($sibling->previous) {
106 3
            $sibling->previous->next = $sibling;
107 1
        }
108
109 9
        $sibling->next = $this;
110 9
        $this->previous = $sibling;
111 9
        $sibling->setParent($this->parent);
112
113 9
        if (!$sibling->previous) {
114 6
            $sibling->parent->firstChild = $sibling;
115 2
        }
116 9
    }
117
118 384
    public function replaceWith(Node $replacement)
119
    {
120 384
        $replacement->detach();
121 384
        $this->insertAfter($replacement);
122 384
        $this->detach();
123 384
    }
124
125 1986
    public function detach()
126
    {
127 1986
        if ($this->previous) {
128 657
            $this->previous->next = $this->next;
129 1986
        } elseif ($this->parent) {
130 534
            $this->parent->firstChild = $this->next;
131 178
        }
132
133 1986
        if ($this->next) {
134 666
            $this->next->previous = $this->previous;
135 1986
        } elseif ($this->parent) {
136 591
            $this->parent->lastChild = $this->previous;
137 197
        }
138
139 1986
        $this->parent = null;
140 1986
        $this->next = null;
141 1986
        $this->previous = null;
142 1986
        $this->depth = 0;
143 1986
    }
144
145
    /**
146
     * @return bool
147
     */
148
    abstract public function isContainer();
149
150
    /**
151
     * @return Node|null
152
     */
153 1953
    public function firstChild()
154
    {
155 1953
        return $this->firstChild;
156
    }
157
158
    /**
159
     * @return Node|null
160
     */
161 1812
    public function lastChild()
162
    {
163 1812
        return $this->lastChild;
164
    }
165
166
    /**
167
     * @return Node[]
168
     */
169 2040
    public function children()
170
    {
171 2040
        $children = [];
172 2040
        for ($current = $this->firstChild; null !== $current; $current = $current->next) {
173 1965
            $children[] = $current;
174 655
        }
175
176 2040
        return $children;
177
    }
178
179
    /**
180
     * @param Node $child
181
     */
182 1980
    public function appendChild(Node $child)
183
    {
184 1980
        if ($this->lastChild) {
185 1488
            $this->lastChild->insertAfter($child);
186 496
        } else {
187 1980
            $child->detach();
188 1980
            $child->setParent($this);
189 1980
            $this->lastChild = $this->firstChild = $child;
190
        }
191 1980
    }
192
193
    /**
194
     * Adds $child as the very first child of $this
195
     *
196
     * @param Node $child
197
     */
198 6
    public function prependChild(Node $child)
199
    {
200 6
        if ($this->firstChild) {
201 3
            $this->firstChild->insertBefore($child);
202 1
        } else {
203 6
            $child->detach();
204 6
            $child->setParent($this);
205 6
            $this->lastChild = $this->firstChild = $child;
206
        }
207 6
    }
208
209
    /**
210
     * Detaches all child nodes of given node
211
     */
212 6
    public function detachChildren()
213
    {
214 6
        foreach ($this->children() as $children) {
215 6
            $children->setParent(null);
216 2
        }
217 6
        $this->firstChild = $this->lastChild = null;
218 6
    }
219
220
    /**
221
     * Replace all children of given node with collection of another
222
     *
223
     * @param array $children
224
     *
225
     * @return $this
226
     */
227 3
    public function replaceChildren(array $children)
228
    {
229 3
        if (!is_array($children) && !(is_object($children) && $children instanceof ArrayCollection)) {
230
            throw new \InvalidArgumentException(sprintf('Expect iterable, got %s', get_class($children)));
231
        }
232
233 3
        $this->detachChildren();
234 3
        foreach ($children as $item) {
235 3
            $this->appendChild($item);
236 1
        }
237
238 3
        return $this;
239
    }
240
241
    /**
242
     * @return int
243
     */
244 396
    public function getDepth()
245
    {
246 396
        return $this->depth;
247
    }
248
249
    /**
250
     * @return NodeWalker
251
     */
252 1941
    public function walker()
253
    {
254 1941
        return new NodeWalker($this);
255
    }
256
}
257