diff --git a/src/ExtendableAttributesTrait.php b/src/ExtendableAttributesTrait.php index 644cc6e..a43979f 100644 --- a/src/ExtendableAttributesTrait.php +++ b/src/ExtendableAttributesTrait.php @@ -96,6 +96,7 @@ public function getAttributesNS(): array protected static function getAttributesNSFromXML(DOMElement $xml, NS|array $namespace = null): array { $namespace = $namespace ?? static::XS_ANY_ATTR_NAMESPACE; + $exclusionList = static::getAttributeExclusions(); $attributes = []; // Validate namespace value @@ -103,28 +104,18 @@ protected static function getAttributesNSFromXML(DOMElement $xml, NS|array $name // Must be one of the predefined values Assert::oneOf($namespace, NS::cases()); - if ($namespace === NS::ANY) { - foreach ($xml->attributes as $a) { - $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); - } - } elseif ($namespace === NS::LOCAL) { - foreach ($xml->attributes as $a) { - if ($a->namespaceURI === null) { - $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); - } - } - } elseif ($namespace === NS::OTHER) { - foreach ($xml->attributes as $a) { - if (!in_array($a->namespaceURI, [static::NS, null], true)) { - $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); - } - } - } elseif ($namespace === NS::TARGET) { - foreach ($xml->attributes as $a) { - if ($a->namespaceURI === static::NS) { - $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); - } + foreach ($xml->attributes as $a) { + if (in_array([$a->namespaceURI, $a->localName], $exclusionList, true)) { + continue; + } elseif ($namespace === NS::OTHER && in_array($a->namespaceURI, [static::NS, null], true)) { + continue; + } elseif ($namespace === NS::TARGET && $a->namespaceURI !== static::NS) { + continue; + } elseif ($namespace === NS::LOCAL && $a->namespaceURI !== null) { + continue; } + + $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); } } else { // Array must be non-empty and cannot contain ##any or ##other @@ -144,9 +135,13 @@ protected static function getAttributesNSFromXML(DOMElement $xml, NS|array $name } foreach ($xml->attributes as $a) { - if (in_array($a->namespaceURI, $namespace, true)) { - $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); + if (in_array([$a->namespaceURI, $a->localName], $exclusionList, true)) { + continue; + } elseif (!in_array($a->namespaceURI, $namespace, true)) { + continue; } + + $attributes[] = new Attribute($a->namespaceURI, $a->prefix, $a->localName, $a->nodeValue); } } @@ -230,6 +225,13 @@ function (Attribute $attr) { } } + $exclusionList = static::getAttributeExclusions(); + foreach ($attributes as $i => $attr) { + if (in_array([$attr->getNamespaceURI(), $attr->getAttrName()], $exclusionList, true)) { + unset($attributes[$i]); + } + } + $this->namespacedAttributes = $attributes; } @@ -249,4 +251,19 @@ public function getAttributeNamespace(): array|NS return static::XS_ANY_ATTR_NAMESPACE; } + + + /** + * Get the exclusions list for getAttributeNSFromXML. + * + * @return array + */ + public static function getAttributeExclusions(): array + { + if (defined('static::XS_ANY_ATTR_EXCLUSIONS')) { + return static::XS_ANY_ATTR_EXCLUSIONS; + } + + return []; + } } diff --git a/tests/Utils/ExtendableAttributesElement.php b/tests/Utils/ExtendableAttributesElement.php index ff022e8..8502325 100644 --- a/tests/Utils/ExtendableAttributesElement.php +++ b/tests/Utils/ExtendableAttributesElement.php @@ -33,6 +33,11 @@ class ExtendableAttributesElement extends AbstractElement /** @var string|\SimpleSAML\XML\XsNamespace */ public const XS_ANY_ATTR_NAMESPACE = NS::ANY; + /** @var array{array{string, string}} */ + public const XS_ANY_ATTR_EXCLUSIONS = [ + ['urn:x-simplesamlphp:namespace', 'attr3'], + ]; + /** * Get the namespace for the element. diff --git a/tests/XML/ExtendableAttributesTest.php b/tests/XML/ExtendableAttributesTest.php index 17603f4..1b89cf6 100644 --- a/tests/XML/ExtendableAttributesTest.php +++ b/tests/XML/ExtendableAttributesTest.php @@ -49,6 +49,7 @@ public function testMarshalling(): void [ new Attribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr1', 'testval1'), new Attribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr2', 'testval2'), + new Attribute('urn:x-simplesamlphp:namespace', 'ssp', 'attr3', 'testval3'), ], ); @@ -57,4 +58,27 @@ public function testMarshalling(): void strval($extendableElement), ); } + + + /** + */ + public function testGetAttributesNSFromXML(): void + { + /** @var \DOMElement $element */ + $element = self::$xmlRepresentation->documentElement; + + $elt = ExtendableAttributesElement::fromXML($element); + $attributes = $elt->getAttributesNS(); + + $this->assertCount(2, $attributes); + $this->assertEquals($attributes[0]->getNamespaceURI(), 'urn:x-simplesamlphp:namespace'); + $this->assertEquals($attributes[0]->getNamespacePrefix(), 'ssp'); + $this->assertEquals($attributes[0]->getAttrName(), 'attr1'); + $this->assertEquals($attributes[0]->getAttrValue(), 'testval1'); + + $this->assertEquals($attributes[1]->getNamespaceURI(), 'urn:x-simplesamlphp:namespace'); + $this->assertEquals($attributes[1]->getNamespacePrefix(), 'ssp'); + $this->assertEquals($attributes[1]->getAttrName(), 'attr2'); + $this->assertEquals($attributes[1]->getAttrValue(), 'testval2'); + } }