From c014ee291c375682248183aa85c255f811bfc8af Mon Sep 17 00:00:00 2001 From: JoshyPHP Date: Mon, 18 Dec 2023 22:17:17 +0100 Subject: [PATCH] WiP --- src/NodeTraits/ChildNodeWorkarounds.php | 37 +++--- src/NodeTraits/ParentNodeWorkarounds.php | 4 +- tests/ElementTest.php | 147 +++++++++++++++++++++++ 3 files changed, 170 insertions(+), 18 deletions(-) diff --git a/src/NodeTraits/ChildNodeWorkarounds.php b/src/NodeTraits/ChildNodeWorkarounds.php index 63da5c6..9a598d7 100644 --- a/src/NodeTraits/ChildNodeWorkarounds.php +++ b/src/NodeTraits/ChildNodeWorkarounds.php @@ -8,7 +8,7 @@ namespace s9e\SweetDOM\NodeTraits; use DOMNode; -use function array_reverse; +use function in_array, is_string; trait ChildNodeWorkarounds { @@ -16,35 +16,40 @@ trait ChildNodeWorkarounds // 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(); } } \ No newline at end of file diff --git a/src/NodeTraits/ParentNodeWorkarounds.php b/src/NodeTraits/ParentNodeWorkarounds.php index 83517c2..0920f7e 100644 --- a/src/NodeTraits/ParentNodeWorkarounds.php +++ b/src/NodeTraits/ParentNodeWorkarounds.php @@ -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); } } @@ -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); } } } \ No newline at end of file diff --git a/tests/ElementTest.php b/tests/ElementTest.php index 60b7676..f25076a 100644 --- a/tests/ElementTest.php +++ b/tests/ElementTest.php @@ -104,6 +104,26 @@ public function testAfterNothing() $this->assertXmlStringEqualsXmlString('

.
.

', $dom->saveXML()); } + #[Group('workarounds')] + public function testAfterSelf() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->after($dom->firstOf('//y')); + + $this->assertXmlStringEqualsXmlString('', $dom->saveXML()); + } + + #[Group('workarounds')] + public function testAfterSelfAndOthers() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->after('x', $dom->firstOf('//y'), 'z'); + + $this->assertXmlStringEqualsXmlString('xz', $dom->saveXML()); + } + #[Group('workarounds')] public function testAppendNothing() { @@ -114,6 +134,39 @@ public function testAppendNothing() $this->assertXmlStringEqualsXmlString('

.
.

', $dom->saveXML()); } + #[Group('workarounds')] + public function testAppendSelf() + { + $this->expectException('DOMException'); + $this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR); + + $dom = new Document; + $dom->loadXML(''); + $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(''); + $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(''); + $dom->firstOf('//y')->append($dom->firstOf('//x')); + } + #[DoesNotPerformAssertions] #[Group('workarounds')] public function testBeforeNoParent() @@ -133,6 +186,26 @@ public function testBeforeNothing() $this->assertXmlStringEqualsXmlString('

.
.

', $dom->saveXML()); } + #[Group('workarounds')] + public function testBeforeSelf() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->before($dom->firstOf('//y')); + + $this->assertXmlStringEqualsXmlString('', $dom->saveXML()); + } + + #[Group('workarounds')] + public function testBeforeSelfAndOthers() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->before('x', $dom->firstOf('//y'), 'z'); + + $this->assertXmlStringEqualsXmlString('xz', $dom->saveXML()); + } + #[Group('workarounds')] public function testPrependNothing() { @@ -143,6 +216,39 @@ public function testPrependNothing() $this->assertXmlStringEqualsXmlString('

.
.

', $dom->saveXML()); } + #[Group('workarounds')] + public function testPrependSelf() + { + $this->expectException('DOMException'); + $this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR); + + $dom = new Document; + $dom->loadXML(''); + $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(''); + $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(''); + $dom->firstOf('//y')->prepend($dom->firstOf('//x')); + } + #[Group('workarounds')] public function testReplaceWithText() { @@ -163,6 +269,47 @@ public function testReplaceWithNothing() $this->assertXmlStringEqualsXmlString('

..

', $dom->saveXML()); } + #[Group('workarounds')] + public function testReplaceWithNextSibling() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->replaceWith($dom->firstOf('//z')); + + $this->assertXmlStringEqualsXmlString('', $dom->saveXML()); + } + + #[Group('workarounds')] + public function testReplaceWithOnlySelf() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->replaceWith($dom->firstOf('//y')); + + $this->assertXmlStringEqualsXmlString('', $dom->saveXML()); + } + + #[Group('workarounds')] + public function testReplaceWithSelfAndOthers() + { + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//y')->replaceWith('x', $dom->firstOf('//y'), 'z'); + + $this->assertXmlStringEqualsXmlString('xz', $dom->saveXML()); + } + + #[Group('workarounds')] + public function testReplaceWithParent() + { + $this->expectException('DOMException'); + $this->expectExceptionCode(DOM_HIERARCHY_REQUEST_ERR); + + $dom = new Document; + $dom->loadXML(''); + $dom->firstOf('//z')->replaceWith($dom->firstOf('//y')); + } + #[Group('workarounds')] public function testAppendNamespace() {