Skip to content

Commit

Permalink
Merge 4128266 into 9663472
Browse files Browse the repository at this point in the history
  • Loading branch information
parisholley committed May 16, 2016
2 parents 9663472 + 4128266 commit cd37bee
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 14 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
composer.lock
vendor
.idea/
87 changes: 73 additions & 14 deletions src/PHPHtmlParser/Dom/InnerNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public function countChildren()
* @return bool
* @throws CircularException
*/
public function addChild(AbstractNode $child)
public function addChild(AbstractNode $child, $before = null)
{
$key = null;

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

$next = null;

if ($this->hasChildren()) {
if (isset($this->children[$child->id()])) {
// we already have this child
return false;
}
$sibling = $this->lastChild();
$key = $sibling->id();
$this->children[$key]['next'] = $child->id();
if (isset($this->children[$child->id()])) {
// we already have this child
return false;
}

if ($before) {
if (!isset($this->children[$before])) {
return false;
}

$key = $this->children[$before]['prev'];

if($key){
$this->children[$key]['next'] = $child->id();
}

$this->children[$before]['prev'] = $child->id();
$next = $before;
} else {
$sibling = $this->lastChild();
$key = $sibling->id();

$this->children[$key]['next'] = $child->id();
}
}

// add the child
$this->children[$child->id()] = [
'node' => $child,
'next' => null,
'prev' => $key,
];
$keys = array_keys($this->children);

$insert = [
'node' => $child,
'next' => $next,
'prev' => $key,
];

$index = $key ? (array_search($key, $keys, true) + 1) : 0;
array_splice($keys, $index, 0, $child->id());

$children = array_values($this->children);
array_splice($children, $index, 0, [$insert]);

// add the child
$this->children = array_combine($keys, $children);

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

/**
* Insert element before child with provided id
*
* @param AbstractNode $child
* @return bool
* @param int $id
*/
public function insertBefore(AbstractNode $child, $id){
$this->addChild($child, $id);
}

/**
* Insert element before after with provided id
*
* @param AbstractNode $child
* @return bool
* @param int $id
*/
public function insertAfter(AbstractNode $child, $id){
if (!isset($this->children[$id])) {
return false;
}

if ($this->children[$id]['next']) {
return $this->addChild($child, $this->children[$id]['next']);
}

return $this->addChild($child);
}

/**
* Removes the child by id.
*
Expand Down
72 changes: 72 additions & 0 deletions tests/Node/ParentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,78 @@ public function testLastChild()
$this->assertEquals($child3->id(), $parent->lastChild()->id());
}

public function testInsertBeforeFirst()
{
$parent = new Node;
$child = new Node;
$child2 = new Node;
$child3 = new Node;
$parent->addChild($child2);
$parent->addChild($child3);

$parent->insertBefore($child, $child2->id());

$this->assertTrue($parent->isChild($child->id()));
$this->assertEquals($parent->firstChild()->id(), $child->id());
$this->assertEquals($child->nextSibling()->id(), $child2->id());
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
$this->assertEquals($parent->lastChild()->id(), $child3->id());
}

public function testInsertBeforeLast()
{
$parent = new Node;
$child = new Node;
$child2 = new Node;
$child3 = new Node;
$parent->addChild($child);
$parent->addChild($child3);

$parent->insertBefore($child2, $child3->id());

$this->assertTrue($parent->isChild($child2->id()));
$this->assertEquals($parent->firstChild()->id(), $child->id());
$this->assertEquals($child->nextSibling()->id(), $child2->id());
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
$this->assertEquals($parent->lastChild()->id(), $child3->id());
}

public function testInsertAfterFirst()
{
$parent = new Node;
$child = new Node;
$child2 = new Node;
$child3 = new Node;
$parent->addChild($child);
$parent->addChild($child3);

$parent->insertAfter($child2, $child->id());

$this->assertTrue($parent->isChild($child2->id()));
$this->assertEquals($parent->firstChild()->id(), $child->id());
$this->assertEquals($child->nextSibling()->id(), $child2->id());
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
$this->assertEquals($parent->lastChild()->id(), $child3->id());
}

public function testInsertAfterLast()
{
$parent = new Node;
$child = new Node;
$child2 = new Node;
$child3 = new Node;
$parent->addChild($child);
$parent->addChild($child2);

$parent->insertAfter($child3, $child2->id());

$this->assertTrue($parent->isChild($child2->id()));
$this->assertEquals($parent->firstChild()->id(), $child->id());
$this->assertEquals($child->nextSibling()->id(), $child2->id());
$this->assertEquals($child2->nextSibling()->id(), $child3->id());
$this->assertEquals($parent->lastChild()->id(), $child3->id());
}

public function testReplaceChild()
{
$parent = new Node;
Expand Down

0 comments on commit cd37bee

Please sign in to comment.