From e8cfb37b690c59d6a0478587dd9be531cbd6d2c8 Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Wed, 6 Dec 2023 09:03:15 +0000 Subject: [PATCH] DOMStringMap improvements with PHP 8.3 support (#450) * tweak: allow select disabled property * test: isolate bug #448 * test: fix numerical issue for #448 * test: test all camel case conversion fixes #448 * ci: php 8.3 support * feature: php 8.3 support --- .github/workflows/ci.yml | 10 +++--- composer.json | 2 +- src/DOMStringMap.php | 2 +- src/Document.php | 6 ++-- src/Element.php | 6 ++-- src/RegisteredNodeClass.php | 12 +++---- test/phpunit/DOMStringMapTest.php | 60 +++++++++++++++++++++++++++++-- 7 files changed, 76 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa84933f..d198ecd1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - php: [ 8.1, 8.2 ] + php: [ 8.1, 8.2, 8.3 ] steps: - uses: actions/checkout@v3 @@ -37,7 +37,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2 ] + php: [ 8.1, 8.2, 8.3 ] outputs: coverage: ${{ steps.store-coverage.outputs.coverage_text }} @@ -90,7 +90,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2 ] + php: [ 8.1, 8.2, 8.3 ] steps: - uses: actions/download-artifact@v3 @@ -112,7 +112,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2 ] + php: [ 8.1, 8.2, 8.3 ] steps: - uses: actions/download-artifact@v3 @@ -136,7 +136,7 @@ jobs: needs: [ composer ] strategy: matrix: - php: [ 8.1, 8.2 ] + php: [ 8.1, 8.2, 8.3 ] steps: - uses: actions/download-artifact@v3 diff --git a/composer.json b/composer.json index 995cf9a6..422a8ff9 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "name": "phpgt/dom", - "description": "The modern DOM API for PHP projects.", + "description": "Modern DOM API.", "type": "library", "require": { diff --git a/src/DOMStringMap.php b/src/DOMStringMap.php index 249ec643..48f2ae4f 100644 --- a/src/DOMStringMap.php +++ b/src/DOMStringMap.php @@ -52,7 +52,7 @@ public function count():int { private function correctCamelCase(string $name):string { preg_match_all( - '/((?:^|[A-Z])[a-z\-]+)/', + '/((?:^|[A-Z])[0-9a-z\-]+)/', $name, $matches ); diff --git a/src/Document.php b/src/Document.php index 6beefc8d..0251499b 100644 --- a/src/Document.php +++ b/src/Document.php @@ -335,10 +335,10 @@ public function getElementById(string $elementId):?Element { /** * @see Node::isEqualNode() - * @param Node|Element $otherNode - * @noinspection PhpParameterNameChangedDuringInheritanceInspection */ - public function isEqualNode(Node|Element|DOMNode $otherNode):bool { + public function isEqualNode( + null|Node|Element|Document|DocumentType|Attr|ProcessingInstruction|DOMNode $otherNode + ):bool { return $this->documentElement->isEqualNode($otherNode); } diff --git a/src/Element.php b/src/Element.php index d568c8c9..2daabb42 100644 --- a/src/Element.php +++ b/src/Element.php @@ -5,6 +5,7 @@ use Countable; use DOMElement; use DOMNamedNodeMap; +use DOMNode; use Gt\Dom\Exception\InvalidAdjacentPositionException; use Gt\Dom\Exception\XPathQueryException; use Gt\PropFunc\MagicProp; @@ -329,14 +330,11 @@ public function getAttributeNames():array { * 'beforeend': Just inside the targetElement, after its last child. * 'afterend': After the targetElement itself. * - * @param Node|Element $element The element to be inserted into the tree. - * @return ?Element The element that was inserted, or null, if the - * insertion failed. * @link https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentElement */ public function insertAdjacentElement( string $position, - Node|Element|DocumentFragment|Text $element + DOMElement|DOMNode|Element|Node|DocumentFragment|Text $element ):?Element { switch($position) { case "beforebegin": diff --git a/src/RegisteredNodeClass.php b/src/RegisteredNodeClass.php index 65302e0a..e87b992b 100644 --- a/src/RegisteredNodeClass.php +++ b/src/RegisteredNodeClass.php @@ -1,6 +1,7 @@ documentElement; } @@ -163,13 +165,11 @@ public function compareDocumentPosition(DOMNode|Node|Element $otherNode):int { * Returns a Boolean value indicating whether or not a node is a * descendant of the calling node. * - * @param Node $otherNode - * @return bool * @link https://developer.mozilla.org/en-US/docs/Web/API/Node/contains */ public function contains( Node|Element|Text|ProcessingInstruction|DocumentType|DocumentFragment - |Document|Comment|CdataSection|Attr $otherNode + |Document|Comment|CdataSection|Attr|DOMNode|DOMNameSpaceNode|null $otherNode ):bool { $context = $otherNode; diff --git a/test/phpunit/DOMStringMapTest.php b/test/phpunit/DOMStringMapTest.php index 7eb73756..def33f85 100644 --- a/test/phpunit/DOMStringMapTest.php +++ b/test/phpunit/DOMStringMapTest.php @@ -1,4 +1,4 @@ -example); } - public function testGetterCamelCaseConversion():void { + public function testGetter_fromCamelCase():void { $keyValuePairs = [ "this-is-camel-case" => uniqid("example-"), ]; @@ -34,6 +34,44 @@ public function testGetterCamelCaseConversion():void { self::assertSame($keyValuePairs["this-is-camel-case"], $sut->thisIsCamelCase); } + public function testGetter_fromHyphenated():void { + $keyValuePairs = [ + "this-is-camel-case" => uniqid("example-"), + ]; + $getter = function() use (&$keyValuePairs) { + return $keyValuePairs; + }; + $setter = function(array $kvp) use (&$keyValuePairs) { + $keyValuePairs = $kvp; + }; + $sut = new DOMStringMap($getter, $setter); + + self::assertSame($keyValuePairs["this-is-camel-case"], $sut->get("this-is-camel-case")); + self::assertSame($keyValuePairs["this-is-camel-case"], $sut->get("thisIsCamelCase")); + self::assertArrayNotHasKey("thisIsCamelCase", $keyValuePairs); + } + + public function testSetter_fromHyphenated():void { + $keyValuePairs = [ + "this-is-camel-case" => uniqid("example-"), + ]; + $getter = function() use (&$keyValuePairs) { + return $keyValuePairs; + }; + $setter = function(array $kvp) use (&$keyValuePairs) { + $keyValuePairs = $kvp; + }; + $sut = new DOMStringMap($getter, $setter); + + $sut->set("this-is-camel-case", "update1"); + $sut->set("thisIsCamelCase", "update2"); + $sut->set("other-key", "other-update"); + + self::assertCount(2, $keyValuePairs); + self::assertSame("update2", $sut->thisIsCamelCase); + self::assertSame("other-update", $sut->otherKey); + } + public function testSetterCamelCaseConversion():void { $keyValuePairs = []; $getter = function() use (&$keyValuePairs) { @@ -47,4 +85,22 @@ public function testSetterCamelCaseConversion():void { self::assertSame("example123", $sut->get("thisIsCamelCase")); self::assertSame("example123", $sut->get("this-is-camel-case")); } + + public function testSetter_withNumbers():void { + $keyValuePairs = []; + $getter = function() use (&$keyValuePairs) { + return $keyValuePairs; + }; + $setter = function(array $kvp) use (&$keyValuePairs) { + $keyValuePairs = $kvp; + }; + $sut = new DOMStringMap($getter, $setter); + $sut->example1 = "one"; + $sut->example2 = "two"; + $sut->example3 = "three"; + + self::assertSame("one", $sut->example1); + self::assertSame("two", $sut->example2); + self::assertSame("three", $sut->example3); + } }