Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
4b48f4b
Migrate DOM-classes to PHP 8.4's new DOM-API
tvdijen May 28, 2026
2b37da9
Solve PHPstan-dev
tvdijen May 29, 2026
2bb60e5
Bugfix: skip non-elements
tvdijen May 29, 2026
4819753
fix phpstan.failing tests.
ioigoume May 29, 2026
2d35606
Fix phpstan-dev execution issues
ioigoume May 29, 2026
b93a3de
use assertXmlStringEqualsXmlString to compare xml strings
ioigoume May 30, 2026
af10c61
use C::NS_XMLNS constant instead of the actual XMLNS namespace URI
ioigoume May 30, 2026
8685e5e
Merge pull request #90 from ioigoume/feature/dom-migration-php84-ioig…
tvdijen May 30, 2026
8ab3e55
Merge branch 'release-3.x' into feature/dom-migration-php84
tvdijen May 30, 2026
68e205e
Use constant
tvdijen May 31, 2026
8128ec4
Prevent Attribute::toXML from setting xmlns:xmlns attributes
tvdijen May 31, 2026
9882e35
Cleaning up
tvdijen May 31, 2026
cf8d29d
Use XML Attribute-class to set namespace attribute
tvdijen Jun 2, 2026
b21a8cf
fix SchemaValidatableElementTrait::schemaValidate inconsistent behavi…
ioigoume Jun 2, 2026
675c339
improve DOMDocument phpdoc usage reasoning
ioigoume Jun 2, 2026
3b127f8
fix review suggestions/comments
ioigoume Jun 2, 2026
e07679f
revert SchemaValidatableElementTrait change
ioigoume Jun 3, 2026
71d3e0d
Merge pull request #91 from ioigoume/feature/dom-migration-php84-ioig…
tvdijen Jun 3, 2026
84042a4
Use DOMDocument for schema validation. Remove insignificant whitespac…
ioigoume Jun 4, 2026
0a4fe44
Merge pull request #92 from ioigoume/feature/dom-migration-php84-ioig…
tvdijen Jun 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
"scripts": {
"pre-commit": [
"vendor/bin/phpcs -p",
"vendor/bin/composer-require-checker check --config-file=tools/composer-require-checker.json composer.json",
"vendor/bin/phpstan analyze -c phpstan.neon",
"vendor/bin/phpstan analyze -c phpstan-dev.neon",
"vendor/bin/composer-unused --excludePackage=simplesamlphp/composer-xmlprovider-installer",
Expand Down
20 changes: 10 additions & 10 deletions src/XML/AbstractElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace SimpleSAML\XML;

use DOMElement;
use Dom;
use RuntimeException;
use SimpleSAML\XML\Assert\Assert;
use SimpleSAML\XML\SerializableElementTrait;
Expand Down Expand Up @@ -35,9 +35,9 @@ abstract class AbstractElement implements
/**
* Create a document structure for this element
*
* @param \DOMElement|null $parent The element we should append to.
* @param \Dom\Element|null $parent The element we should append to.
*/
public function instantiateParentElement(?DOMElement $parent = null): DOMElement
public function instantiateParentElement(?Dom\Element $parent = null): Dom\Element
{
$qualifiedName = $this->getQualifiedName();
$namespace = static::getNamespaceURI();
Expand All @@ -59,15 +59,15 @@ public function instantiateParentElement(?DOMElement $parent = null): DOMElement

/**
* @template T of \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
* @param \DOMElement $xml The element where we should search for the attribute.
* @param \Dom\Element $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param class-string<T> $type The type of the attribute value.
* @return T
*
* @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException if the attribute is missing from the element
*/
public static function getAttribute(
DOMElement $xml,
Dom\Element $xml,
string $name,
string $type = StringValue::class,
): ValueTypeInterface {
Expand All @@ -91,15 +91,15 @@ public static function getAttribute(
* Get the value of an attribute from a given element.
*
* @template T of \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
* @param \DOMElement $xml The element where we should search for the attribute.
* @param \Dom\Element $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param class-string<T> $type The type of the attribute value.
* @param \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface|null $default
* The default to return in case the attribute does not exist and it is optional.
* @return ($default is \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface ? T : T|null)
*/
public static function getOptionalAttribute(
DOMElement $xml,
Dom\Element $xml,
string $name,
string $type = StringValue::class,
?ValueTypeInterface $default = null,
Expand Down Expand Up @@ -142,15 +142,15 @@ public function getQualifiedName(): string
/**
* Extract localized names from the children of a given element.
*
* @param \DOMElement $parent The element we want to search.
* @param \Dom\Element $parent The element we want to search.
* @return list<static> An array of objects of this class.
*/
public static function getChildrenOfClass(DOMElement $parent): array
public static function getChildrenOfClass(Dom\Element $parent): array
{
$ret = [];
foreach ($parent->childNodes as $node) {
if (
$node instanceof DOMElement
$node instanceof Dom\Element
&& $node->namespaceURI === static::getNamespaceURI()
&& $node->localName === static::getLocalName()
) {
Expand Down
29 changes: 13 additions & 16 deletions src/XML/Attribute.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

namespace SimpleSAML\XML;

use DOMAttr;
use DOMElement;
use Dom;
use SimpleSAML\XML\Assert\Assert;
use SimpleSAML\XML\Constants as C;
use SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface;
use SimpleSAML\XMLSchema\Type\StringValue;

Expand Down Expand Up @@ -83,9 +83,9 @@ public function getAttrValue(): ValueTypeInterface
/**
* Create a class from XML
*
* @param \DOMAttr $attr
* @param \Dom\Attr $attr
*/
public static function fromXML(DOMAttr $attr): static
public static function fromXML(Dom\Attr $attr): static
{
return new static($attr->namespaceURI, $attr->prefix, $attr->localName, StringValue::fromString($attr->value));
}
Expand All @@ -94,23 +94,20 @@ public static function fromXML(DOMAttr $attr): static
/**
* Create XML from this class
*
* @param \DOMElement $parent
* @param \Dom\Element $parent
*/
public function toXML(DOMElement $parent): DOMElement
public function toXML(Dom\Element $parent): Dom\Element
{
if ($this->getNamespaceURI() !== null && !$parent->lookupPrefix($this->getNamespacePrefix())) {
$parent->setAttributeNS(
'http://www.w3.org/2000/xmlns/',
'xmlns:' . $this->getNamespacePrefix(),
$this->getNamespaceURI(),
);
$prefix = $this->getNamespacePrefix();
$namespaceURI = $this->getNamespaceURI();

if ($namespaceURI !== null && !in_array($prefix, ['xml', 'xmlns']) && !$parent->lookupPrefix($prefix)) {
$parent->setAttributeNS(C::NS_XMLNS, 'xmlns:' . $prefix, $namespaceURI);
}

$parent->setAttributeNS(
$this->getNamespaceURI(),
!in_array($this->getNamespacePrefix(), ['', null])
? ($this->getNamespacePrefix() . ':' . $this->getAttrName())
: $this->getAttrName(),
$namespaceURI,
!in_array($prefix, ['', null]) ? ($prefix . ':' . $this->getAttrName()) : $this->getAttrName(),
strval($this->getAttrValue()),
);

Expand Down
30 changes: 15 additions & 15 deletions src/XML/Chunk.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace SimpleSAML\XML;

use DOMElement;
use Dom;
use SimpleSAML\XML\Assert\Assert;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XML\SerializableElementTrait;
Expand Down Expand Up @@ -57,10 +57,10 @@ final class Chunk implements
/**
* Create an XML Chunk from a copy of the given \DOMElement.
*
* @param \DOMElement $xml The element we should copy.
* @param \Dom\Element $xml The element we should copy.
*/
public function __construct(
protected DOMElement $xml,
protected Dom\Element $xml,
) {
$this->setLocalName($xml->localName);
$this->setNamespaceURI($xml->namespaceURI);
Expand Down Expand Up @@ -132,9 +132,9 @@ protected function setNamespaceURI(?string $namespaceURI = null): void


/**
* Get this \DOMElement.
* Get this \Dom\Element.
*/
public function getXML(): DOMElement
public function getXML(): Dom\Element
{
return $this->xml;
}
Expand Down Expand Up @@ -180,15 +180,15 @@ public function getQualifiedName(): string
* Get the value of an attribute from a given element.
*
* @template T of \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
* @param \DOMElement $xml The element where we should search for the attribute.
* @param \Dom\Element $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param class-string<T> $type The type of the attribute value.
* @return T
*
* @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException if the attribute is missing from the element
*/
public static function getAttribute(
DOMElement $xml,
Dom\Element $xml,
string $name,
string $type = StringValue::class,
): ValueTypeInterface {
Expand All @@ -209,15 +209,15 @@ public static function getAttribute(
* Get the value of an attribute from a given element.
*
* @template T of \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface
* @param \DOMElement $xml The element where we should search for the attribute.
* @param \Dom\Element $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param class-string<T> $type The type of the attribute value.
* @param \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface|null $default
* The default to return in case the attribute does not exist and it is optional.
* @return ($default is \SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface ? T : T|null)
*/
public static function getOptionalAttribute(
DOMElement $xml,
Dom\Element $xml,
string $name,
string $type = StringValue::class,
?ValueTypeInterface $default = null,
Expand All @@ -235,16 +235,16 @@ public static function getOptionalAttribute(
*/
public function isEmptyElement(): bool
{
/** @var \DOMElement $xml */
/** @var \Dom\Element $xml */
$xml = $this->getXML();
return ($xml->childNodes->length === 0) && ($xml->attributes->count() === 0);
}


/**
* @param \DOMElement $xml
* @param \Dom\Element $xml
*/
public static function fromXML(DOMElement $xml): static
public static function fromXML(Dom\Element $xml): static
{
return new static($xml);
}
Expand All @@ -253,10 +253,10 @@ public static function fromXML(DOMElement $xml): static
/**
* Append this XML element to a different XML element.
*
* @param \DOMElement|null $parent The element we should append this element to.
* @return \DOMElement The new element.
* @param \Dom\Element|null $parent The element we should append this element to.
* @return \Dom\Element The new element.
*/
public function toXML(?DOMElement $parent = null): DOMElement
public function toXML(?Dom\Element $parent = null): Dom\Element
{
if ($parent === null) {
$doc = DOMDocumentFactory::create();
Expand Down
8 changes: 8 additions & 0 deletions src/XML/Container/AbstractTestContainer.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace SimpleSAML\XML\Container;

use Dom;
use SimpleSAML\XML\Attribute as XMLAttribute;
use SimpleSAML\XML\Chunk;
use SimpleSAML\XML\Type\LangValue;
Expand All @@ -28,4 +29,11 @@ abstract public function getLanguageValue(string $language = 'en'): LanguageValu


abstract public function getXMLAttribute(int $x = 1): XMLAttribute;


/**
* @param non-empty-string $text
* @return \Dom\NodeList<\Dom\Node>
*/
abstract public function getDOMText(string $text): Dom\NodeList;
}
29 changes: 24 additions & 5 deletions src/XML/Container/XMLSchemaElementsTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace SimpleSAML\XML\Container;

use DOMText;
use Dom;
use SimpleSAML\XML\DOMDocumentFactory;
use SimpleSAML\XMLSchema\Type\AnyURIValue;
use SimpleSAML\XMLSchema\XML\Appinfo;
Expand All @@ -26,22 +26,41 @@ trait XMLSchemaElementsTrait
/** @var array<positive-int, \SimpleSAML\XMLSchema\XML\Appinfo> */
protected array $appinfo = [];

/** @var array<non-empty-string, \Dom\NodeList> */
protected array $domText = [];


/** @param positive-int $x */
public function getAppinfo(int $x = 1): Appinfo
{
if (!array_key_exists($x, $this->appinfo)) {
$appinfoDocument = DOMDocumentFactory::create();
$text = new DOMText(sprintf('Application Information (%d)', $x));
$appinfoDocument->appendChild($text);
$domTextNode = $this->getDOMText(sprintf('Application Information (%d)', $x));

$this->appinfo[$x] = new Appinfo(
$appinfoDocument->childNodes,
$domTextNode,
AnyURIValue::fromString(static::SOURCE),
[$this->getXMLAttribute($x)],
);
}

return $this->appinfo[$x];
}


/** @param non-empty-string $text */
public function getDOMText(string $text): Dom\NodeList
{
if (!array_key_exists($text, $this->domText)) {
$doc = DOMDocumentFactory::create();

$elt = $doc->createElement('root');
$domText = $doc->createTextNode($text);

$elt->appendChild($domText);

$this->domText[$text] = $elt->childNodes;
}

return $this->domText[$text];
}
}
Loading
Loading