Skip to content

Commit

Permalink
WiP
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshyPHP committed Dec 18, 2023
1 parent a285d94 commit c014ee2
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 18 deletions.
37 changes: 21 additions & 16 deletions src/NodeTraits/ChildNodeWorkarounds.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,48 @@
namespace s9e\SweetDOM\NodeTraits;

use DOMNode;
use function array_reverse;
use function in_array, is_string;

trait ChildNodeWorkarounds
{
// https://github.com/php/php-src/pull/11768 - fixed in ~8.1.23, ^8.2.10
// https://github.com/php/php-src/pull/11905 - behaviour changed in 8.3.0
public function after(...$nodes): void
{
if (isset($this->parentNode))
{
foreach (array_reverse($nodes) as $node)
{
parent::after($node);
}
}
$this->replaceWith($this, ...$nodes);
}

// https://github.com/php/php-src/pull/11905
public function before(...$nodes): void
{
if (isset($this->parentNode))
if (!in_array($this, $nodes, true))
{
foreach ($nodes as $node)
{
parent::before($node);
}
$nodes[] = $this;
}
$this->replaceWith(...$nodes);
}

// https://github.com/php/php-src/issues/11289 - introduced in 8.1.18, 8.2.6 - fixed in ~8.1.10, ^8.2.8
// https://github.com/php/php-src/pull/11888 - introduced in 8.2.8 - fixed in ^8.2.10
// https://github.com/php/php-src/pull/11905
public function replaceWith(...$nodes): void
{
if (isset($this->parentNode))
if (!isset($this->parentNode))
{
$this->before(...$nodes);
$this->remove();
return;
}

$contextNode = $this->ownerDocument->createTextNode('');
$parentNode = $this->parentNode;
$parentNode->replaceChild($contextNode, $this);
foreach ($nodes as $node)
{
if (is_string($node))
{
$node = $this->ownerDocument->createTextNode($node);
}
$parentNode->insertBefore($node, $contextNode);
}
$contextNode->remove();
}
}
4 changes: 2 additions & 2 deletions src/NodeTraits/ParentNodeWorkarounds.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function append(...$nodes): void
{
foreach ($nodes as $node)
{
parent::append($node);
$this->appendChild(is_string($node) ? $this->ownerDocument->createTextNode($node) : $node);
}
}

Expand All @@ -27,7 +27,7 @@ public function prepend(...$nodes): void
{
foreach (array_reverse($nodes) as $node)
{
parent::prepend($node);
$this->insertBefore(is_string($node) ? $this->ownerDocument->createTextNode($node) : $node, $this->firstChild);
}
}
}
147 changes: 147 additions & 0 deletions tests/ElementTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ public function testAfterNothing()
$this->assertXmlStringEqualsXmlString('<p><span>.<br/>.</span></p>', $dom->saveXML());
}

#[Group('workarounds')]
public function testAfterSelf()
{
$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->after($dom->firstOf('//y'));

$this->assertXmlStringEqualsXmlString('<x><y/></x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testAfterSelfAndOthers()
{
$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->after('x', $dom->firstOf('//y'), 'z');

$this->assertXmlStringEqualsXmlString('<x>x<y/>z</x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testAppendNothing()
{
Expand All @@ -114,6 +134,39 @@ public function testAppendNothing()
$this->assertXmlStringEqualsXmlString('<p><span>.<br/>.</span></p>', $dom->saveXML());
}

#[Group('workarounds')]
public function testAppendSelf()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->append($dom->firstOf('//y'));
}

#[Group('workarounds')]
public function testAppendSelfAndOthers()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->append('x', $dom->firstOf('//y'), 'z');
}

#[Group('workarounds')]
public function testAppendParent()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->append($dom->firstOf('//x'));
}

#[DoesNotPerformAssertions]
#[Group('workarounds')]
public function testBeforeNoParent()
Expand All @@ -133,6 +186,26 @@ public function testBeforeNothing()
$this->assertXmlStringEqualsXmlString('<p><span>.<br/>.</span></p>', $dom->saveXML());
}

#[Group('workarounds')]
public function testBeforeSelf()
{
$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->before($dom->firstOf('//y'));

$this->assertXmlStringEqualsXmlString('<x><y/></x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testBeforeSelfAndOthers()
{
$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->before('x', $dom->firstOf('//y'), 'z');

$this->assertXmlStringEqualsXmlString('<x>x<y/>z</x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testPrependNothing()
{
Expand All @@ -143,6 +216,39 @@ public function testPrependNothing()
$this->assertXmlStringEqualsXmlString('<p><span>.<br/>.</span></p>', $dom->saveXML());
}

#[Group('workarounds')]
public function testPrependSelf()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->prepend($dom->firstOf('//y'));
}

#[Group('workarounds')]
public function testPrependSelfAndOthers()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->prepend('x', $dom->firstOf('//y'), 'z');
}

#[Group('workarounds')]
public function testPrependParent()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->prepend($dom->firstOf('//x'));
}

#[Group('workarounds')]
public function testReplaceWithText()
{
Expand All @@ -163,6 +269,47 @@ public function testReplaceWithNothing()
$this->assertXmlStringEqualsXmlString('<p><span>..</span></p>', $dom->saveXML());
}

#[Group('workarounds')]
public function testReplaceWithNextSibling()
{
$dom = new Document;
$dom->loadXML('<x><y/><z/></x>');
$dom->firstOf('//y')->replaceWith($dom->firstOf('//z'));

$this->assertXmlStringEqualsXmlString('<x><z/></x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testReplaceWithOnlySelf()
{
$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->replaceWith($dom->firstOf('//y'));

$this->assertXmlStringEqualsXmlString('<x><y/></x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testReplaceWithSelfAndOthers()
{
$dom = new Document;
$dom->loadXML('<x><y/></x>');
$dom->firstOf('//y')->replaceWith('x', $dom->firstOf('//y'), 'z');

$this->assertXmlStringEqualsXmlString('<x>x<y/>z</x>', $dom->saveXML());
}

#[Group('workarounds')]
public function testReplaceWithParent()
{
$this->expectException('DOMException');
$this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR);

$dom = new Document;
$dom->loadXML('<x><y><z/></y></x>');
$dom->firstOf('//z')->replaceWith($dom->firstOf('//y'));
}

#[Group('workarounds')]
public function testAppendNamespace()
{
Expand Down

0 comments on commit c014ee2

Please sign in to comment.