Skip to content

Commit 23df5a4

Browse files
committed
Merge branch 'insertBeforeAfter' of git://github.com/parisholley/php-html-parser into parisholley-insertBeforeAfter
2 parents 75bca86 + 4128266 commit 23df5a4

File tree

4 files changed

+151
-20
lines changed

4 files changed

+151
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
composer.phar
22
composer.lock
33
/vendor/
4+
.idea/

src/PHPHtmlParser/Dom/InnerNode.php

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ public function countChildren()
104104
* @return bool
105105
* @throws CircularException
106106
*/
107-
public function addChild(AbstractNode $child)
107+
public function addChild(AbstractNode $child, $before = null)
108108
{
109109
$key = null;
110110

@@ -118,22 +118,51 @@ public function addChild(AbstractNode $child)
118118
throw new CircularException('Can not set itself as a child.');
119119
}
120120

121+
$next = null;
122+
121123
if ($this->hasChildren()) {
122-
if (isset($this->children[$child->id()])) {
123-
// we already have this child
124-
return false;
125-
}
126-
$sibling = $this->lastChild();
127-
$key = $sibling->id();
128-
$this->children[$key]['next'] = $child->id();
124+
if (isset($this->children[$child->id()])) {
125+
// we already have this child
126+
return false;
127+
}
128+
129+
if ($before) {
130+
if (!isset($this->children[$before])) {
131+
return false;
132+
}
133+
134+
$key = $this->children[$before]['prev'];
135+
136+
if($key){
137+
$this->children[$key]['next'] = $child->id();
138+
}
139+
140+
$this->children[$before]['prev'] = $child->id();
141+
$next = $before;
142+
} else {
143+
$sibling = $this->lastChild();
144+
$key = $sibling->id();
145+
146+
$this->children[$key]['next'] = $child->id();
147+
}
129148
}
130149

131-
// add the child
132-
$this->children[$child->id()] = [
133-
'node' => $child,
134-
'next' => null,
135-
'prev' => $key,
136-
];
150+
$keys = array_keys($this->children);
151+
152+
$insert = [
153+
'node' => $child,
154+
'next' => $next,
155+
'prev' => $key,
156+
];
157+
158+
$index = $key ? (array_search($key, $keys, true) + 1) : 0;
159+
array_splice($keys, $index, 0, $child->id());
160+
161+
$children = array_values($this->children);
162+
array_splice($children, $index, 0, [$insert]);
163+
164+
// add the child
165+
$this->children = array_combine($keys, $children);
137166

138167
// tell child I am the new parent
139168
$child->setParent($this);
@@ -144,6 +173,36 @@ public function addChild(AbstractNode $child)
144173
return true;
145174
}
146175

176+
/**
177+
* Insert element before child with provided id
178+
*
179+
* @param AbstractNode $child
180+
* @return bool
181+
* @param int $id
182+
*/
183+
public function insertBefore(AbstractNode $child, $id){
184+
$this->addChild($child, $id);
185+
}
186+
187+
/**
188+
* Insert element before after with provided id
189+
*
190+
* @param AbstractNode $child
191+
* @return bool
192+
* @param int $id
193+
*/
194+
public function insertAfter(AbstractNode $child, $id){
195+
if (!isset($this->children[$id])) {
196+
return false;
197+
}
198+
199+
if ($this->children[$id]['next']) {
200+
return $this->addChild($child, $this->children[$id]['next']);
201+
}
202+
203+
return $this->addChild($child);
204+
}
205+
147206
/**
148207
* Removes the child by id.
149208
*

src/PHPHtmlParser/Dom/TextNode.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,14 +121,13 @@ protected function clear()
121121
$this->convertedText = null;
122122
}
123123

124+
/**
125+
* Checks if the current node is a text node.
126+
*
127+
* @return bool
128+
*/
124129
public function isTextNode()
125130
{
126131
return true;
127132
}
128-
129-
public function setText($text)
130-
{
131-
$this->text = $text;
132-
}
133-
134133
}

tests/Node/ParentTest.php

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,78 @@ public function testLastChild()
157157
$this->assertEquals($child3->id(), $parent->lastChild()->id());
158158
}
159159

160+
public function testInsertBeforeFirst()
161+
{
162+
$parent = new Node;
163+
$child = new Node;
164+
$child2 = new Node;
165+
$child3 = new Node;
166+
$parent->addChild($child2);
167+
$parent->addChild($child3);
168+
169+
$parent->insertBefore($child, $child2->id());
170+
171+
$this->assertTrue($parent->isChild($child->id()));
172+
$this->assertEquals($parent->firstChild()->id(), $child->id());
173+
$this->assertEquals($child->nextSibling()->id(), $child2->id());
174+
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
175+
$this->assertEquals($parent->lastChild()->id(), $child3->id());
176+
}
177+
178+
public function testInsertBeforeLast()
179+
{
180+
$parent = new Node;
181+
$child = new Node;
182+
$child2 = new Node;
183+
$child3 = new Node;
184+
$parent->addChild($child);
185+
$parent->addChild($child3);
186+
187+
$parent->insertBefore($child2, $child3->id());
188+
189+
$this->assertTrue($parent->isChild($child2->id()));
190+
$this->assertEquals($parent->firstChild()->id(), $child->id());
191+
$this->assertEquals($child->nextSibling()->id(), $child2->id());
192+
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
193+
$this->assertEquals($parent->lastChild()->id(), $child3->id());
194+
}
195+
196+
public function testInsertAfterFirst()
197+
{
198+
$parent = new Node;
199+
$child = new Node;
200+
$child2 = new Node;
201+
$child3 = new Node;
202+
$parent->addChild($child);
203+
$parent->addChild($child3);
204+
205+
$parent->insertAfter($child2, $child->id());
206+
207+
$this->assertTrue($parent->isChild($child2->id()));
208+
$this->assertEquals($parent->firstChild()->id(), $child->id());
209+
$this->assertEquals($child->nextSibling()->id(), $child2->id());
210+
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
211+
$this->assertEquals($parent->lastChild()->id(), $child3->id());
212+
}
213+
214+
public function testInsertAfterLast()
215+
{
216+
$parent = new Node;
217+
$child = new Node;
218+
$child2 = new Node;
219+
$child3 = new Node;
220+
$parent->addChild($child);
221+
$parent->addChild($child2);
222+
223+
$parent->insertAfter($child3, $child2->id());
224+
225+
$this->assertTrue($parent->isChild($child2->id()));
226+
$this->assertEquals($parent->firstChild()->id(), $child->id());
227+
$this->assertEquals($child->nextSibling()->id(), $child2->id());
228+
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
229+
$this->assertEquals($parent->lastChild()->id(), $child3->id());
230+
}
231+
160232
public function testReplaceChild()
161233
{
162234
$parent = new Node;

0 commit comments

Comments
 (0)