Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
1f7dc57
Order use-statements alphabetically
tvdijen Jan 10, 2025
97cbfaf
Create type-classes for all xsd-types
tvdijen Jan 10, 2025
d9bc76a
Create assertion and type-class for xs:gMonth
tvdijen Jan 11, 2025
205cd5c
Create assertion and type-class for xs:gYearMonth
tvdijen Jan 11, 2025
c9ea240
Create assertion and type-class for xs:time
tvdijen Jan 11, 2025
25da338
Create assertion and type-class for xs:QName
tvdijen Jan 11, 2025
be21f13
Create assertion and type-class for xs:NMTOKEN
tvdijen Jan 11, 2025
11316ca
Create assertion and type-class for xs:NMTOKENS
tvdijen Jan 11, 2025
bff8ce6
Create assertion and type-class for xs:NCName
tvdijen Jan 11, 2025
e9fe9cd
Create assertion and type-class for xs:Name
tvdijen Jan 11, 2025
a11df6a
Create assertion and type-class for xs:language
tvdijen Jan 11, 2025
710cac8
Create assertion and type-class for xs:ID
tvdijen Jan 11, 2025
5589e2e
Create assertion and type-class for xs:IDREF
tvdijen Jan 11, 2025
734134f
Create assertion and type-class for xs:IDREFS
tvdijen Jan 11, 2025
9edbea7
Create assertion and type-class for xs:hexBinary
tvdijen Jan 11, 2025
db37e04
Create assertion and type-class for xs:ENTITY
tvdijen Jan 11, 2025
a40a664
Create assertion and type-class for xs:ENTITIES
tvdijen Jan 11, 2025
4a93082
Create assertion and type-class for xs:duration
tvdijen Jan 11, 2025
6de1e23
Create assertion and type-class for xs:dateTime
tvdijen Jan 11, 2025
736f940
Create assertion and type-class for xs:anyURI
tvdijen Jan 11, 2025
075caf2
Create assertion and type-class for xs:gDay
tvdijen Jan 11, 2025
46ef6ae
Create assertion and type-class for xs:date
tvdijen Jan 11, 2025
aa755f6
Create assertion and type-class for xs:token
tvdijen Jan 11, 2025
63ae568
Create assertion and type-class for xs:string
tvdijen Jan 11, 2025
59dfc7b
Create assertion and type-class for xs:normalizedString
tvdijen Jan 12, 2025
99c2c05
Create assertion and type-class for xs:base64Binary
tvdijen Jan 13, 2025
67d349b
Create assertion and type-class for xs:boolean
tvdijen Jan 13, 2025
cc9a8d2
Create assertion and type-class for xs:decimal
tvdijen Jan 13, 2025
0228ede
Create assertion and type-class for xs:integer
tvdijen Jan 13, 2025
23ed682
Create assertion and type-class for xs:nonPositiveInteger
tvdijen Jan 13, 2025
c23e4c4
Create assertion and type-class for xs:negativeInteger
tvdijen Jan 13, 2025
2395dd1
Create assertion and type-class for xs:nonNegativeInteger
tvdijen Jan 13, 2025
255c8a1
Create assertion and type-class for xs:positiveInteger
tvdijen Jan 13, 2025
c9cc921
Create assertion and type-class for xs:long
tvdijen Jan 13, 2025
f062d50
Create assertion and type-class for xs:int
tvdijen Jan 13, 2025
72e8712
Create assertion and type-class for xs:short
tvdijen Jan 13, 2025
78a293a
Create assertion and type-class for xs:byte
tvdijen Jan 13, 2025
0cd29ec
Create assertion and type-class for xs:float
tvdijen Jan 13, 2025
aed6ae0
Create assertion and type-class for xs:double
tvdijen Jan 13, 2025
b42b9c3
Create assertion and type-class for xs:unsignedLong
tvdijen Jan 13, 2025
ec3ef02
Create assertion and type-class for xs:unsignedInt
tvdijen Jan 14, 2025
c74fc62
Create assertion and type-class for xs:unsignedShort
tvdijen Jan 14, 2025
9591efd
Create assertion and type-class for xs:unsignedByte
tvdijen Jan 14, 2025
4586188
Create assertion and type-class for xs:gYear
tvdijen Jan 14, 2025
036a478
Restructure getAttribute/getOptionalAttribute
tvdijen Jan 15, 2025
f4eac09
Ensure the default value is one of the type we're expecting to find
tvdijen Jan 16, 2025
bf4f14b
Remove element traits
tvdijen Jan 16, 2025
d75bc7e
Re-add element traits
tvdijen Jan 16, 2025
056e93d
Migrate Attribute to use value type
tvdijen Jan 16, 2025
2108760
Split long regex over multiple lines
tvdijen Jan 16, 2025
4abcd00
Add missing getter
tvdijen Jan 17, 2025
8ccfc4e
Fix description
tvdijen Jan 17, 2025
274bb18
Fix regex for single digits
tvdijen Jan 18, 2025
317ce62
Add toArray for list-types
tvdijen Jan 18, 2025
6d83776
Break parentage of AssertionFailedException for SchemaViolationException
tvdijen Jan 18, 2025
c49aafe
namespace cleanup
tvdijen Jan 18, 2025
e6af096
Add DateTimeValue::fromDateTime
tvdijen Jan 20, 2025
253f887
Refactor unit tests
tvdijen Jan 20, 2025
ae69833
Refactor QName type
tvdijen Jan 22, 2025
62dd526
Add constants that hold the xsd-type
tvdijen Jan 25, 2025
304fb63
Fix typo
tvdijen Jan 27, 2025
8ad2180
Append namespace-attribute when necessary
tvdijen Jan 27, 2025
b1f812f
No longer normalize elements before sending them through fromXML; thi…
tvdijen Jan 31, 2025
5ac7a5b
Fix scrutinizer issues
tvdijen Jan 31, 2025
e94ba59
Fix calling a method on null
tvdijen Jan 31, 2025
eb96eef
Improve re-usability of the TypedTextContentTrait
tvdijen Feb 2, 2025
3b2a5ff
Refactor schema-constants
tvdijen Feb 2, 2025
c15932c
Add helper-methods to BooleanValue
tvdijen Feb 2, 2025
d983245
Add toInteger/fromInteger helpers
tvdijen Feb 4, 2025
6b1efda
Fix regular expression to allow numbers ending with a zero
tvdijen Feb 4, 2025
e2ed394
s/static/self/
tvdijen Feb 7, 2025
de32d87
Remove unused use-statement
tvdijen Feb 7, 2025
f396167
Add dependency for testArrayization on testMarshalling
tvdijen Feb 8, 2025
0e8cf6b
Fix attribute-arrayization
tvdijen Feb 9, 2025
c40c260
Auto-insert attribute namespace if it's not already known
tvdijen Feb 11, 2025
bc80e64
Add toDateTime
tvdijen Feb 24, 2025
eb5a3c8
Remove unused php-extension
tvdijen Feb 24, 2025
c98b7c7
Add equals-method to compare value types
tvdijen Feb 25, 2025
6f6cb55
Add missing bcmath-dependency
tvdijen Jun 12, 2025
7130d3b
Fix qa
tvdijen Jun 12, 2025
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
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
},
"require": {
"php": "^8.1",

"ext-bcmath": "*",
"ext-date": "*",
"ext-dom": "*",
"ext-filter": "*",
Expand Down
146 changes: 32 additions & 114 deletions src/AbstractElement.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,13 @@
use DOMElement;
use RuntimeException;
use SimpleSAML\XML\Assert\Assert;
use SimpleSAML\XML\Exception\MissingAttributeException;
use SimpleSAML\XML\Exception\SchemaViolationException;
use SimpleSAML\XML\Exception\{MissingAttributeException, SchemaViolationException};
use SimpleSAML\XML\SerializableElementTrait;
use SimpleSAML\XML\Type\{QNameValue, StringValue, ValueTypeInterface};

use function array_slice;
use function defined;
use function explode;
use function func_num_args;
use function in_array;
use function intval;
use function join;
use function strval;

Expand Down Expand Up @@ -57,133 +54,59 @@ public function instantiateParentElement(?DOMElement $parent = null): DOMElement


/**
* Get the value of an attribute from a given element.
*
* @param \DOMElement $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @return string
* @template T of \SimpleSAML\XML\Type\ValueTypeInterface
* @param \DOMElement $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\XML\Exception\MissingAttributeException if the attribute is missing from the element
*/
public static function getAttribute(DOMElement $xml, string $name): string
{
public static function getAttribute(
DOMElement $xml,
string $name,
string $type = StringValue::class,
): ValueTypeInterface {
Assert::isAOf($type, ValueTypeInterface::class);

$prefix = static::getNamespacePrefix();
$localName = static::getLocalName();
$qName = $prefix ? ($prefix . ':' . $localName) : $localName;
Assert::true(
$xml->hasAttribute($name) && func_num_args() === 2,
$xml->hasAttribute($name),
sprintf('Missing \'%s\' attribute on %s.', $name, $qName),
MissingAttributeException::class,
);

return $xml->getAttribute($name);
$value = $xml->getAttribute($name);
return ($type === QNameValue::class) ? QNameValue::fromDocument($value, $xml) : $type::fromString($value);
}


/**
* Get the value of an attribute from a given element.
*
* @param \DOMElement $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param string|null $default The default to return in case the attribute does not exist and it is optional.
* @return ($default is string ? string : string|null)
*/
public static function getOptionalAttribute(DOMElement $xml, string $name, ?string $default = null): ?string
{
if (!$xml->hasAttribute($name)) {
return $default;
}

return self::getAttribute($xml, $name);
}


/**
* @param \DOMElement $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @return bool
*
* @throws \SimpleSAML\XML\Exception\MissingAttributeException if the attribute is missing from the element
* @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not a boolean
* @template T of \SimpleSAML\XML\Type\ValueTypeInterface
* @param \DOMElement $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\XML\Type\ValueTypeInterface|null $default
* The default to return in case the attribute does not exist and it is optional.
* @return ($default is \SimpleSAML\XML\Type\ValueTypeInterface ? T : T|null)
*/
public static function getBooleanAttribute(DOMElement $xml, string $name): bool
{
$value = self::getAttribute($xml, $name);
public static function getOptionalAttribute(
DOMElement $xml,
string $name,
string $type = StringValue::class,
?ValueTypeInterface $default = null,
): ?ValueTypeInterface {
Assert::nullOrIsInstanceOf($default, $type);

$prefix = static::getNamespacePrefix();
$localName = static::getLocalName();
$qName = $prefix ? ($prefix . ':' . $localName) : $localName;
Assert::oneOf(
$value,
['0', '1', 'false', 'true'],
sprintf('The \'%s\' attribute of %s must be a boolean.', $name, $qName),
);

return in_array($value, ['1', 'true'], true);
}


/**
* @param \DOMElement $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param bool|null $default The default to return in case the attribute does not exist and it is optional.
* @return ($default is bool ? bool : bool|null)
*
* @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not a boolean
*/
public static function getOptionalBooleanAttribute(DOMElement $xml, string $name, ?bool $default = null): ?bool
{
if (!$xml->hasAttribute($name)) {
return $default;
}

return self::getBooleanAttribute($xml, $name);
}


/**
* Get the integer value of an attribute from a given element.
*
* @param \DOMElement $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @return int
*
* @throws \SimpleSAML\XML\Exception\MissingAttributeException if the attribute is missing from the element
* @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not an integer
*/
public static function getIntegerAttribute(DOMElement $xml, string $name): int
{
$value = self::getAttribute($xml, $name);

$prefix = static::getNamespacePrefix();
$localName = static::getLocalName();
$qName = $prefix ? ($prefix . ':' . $localName) : $localName;
Assert::numeric(
$value,
sprintf('The \'%s\' attribute of %s must be numerical.', $name, $qName),
);

return intval($value);
}


/**
* Get the integer value of an attribute from a given element.
*
* @param \DOMElement $xml The element where we should search for the attribute.
* @param string $name The name of the attribute.
* @param int|null $default The default to return in case the attribute does not exist and it is optional.
* @return ($default is int ? int : int|null)
*
* @throws \SimpleSAML\Assert\AssertionFailedException if the attribute is not an integer
*/
public static function getOptionalIntegerAttribute(DOMElement $xml, string $name, ?int $default = null): ?int
{
if (!$xml->hasAttribute($name)) {
return $default;
}

return self::getIntegerAttribute($xml, $name);
return self::getAttribute($xml, $name, $type);
}


Expand Down Expand Up @@ -230,11 +153,6 @@ public static function getChildrenOfClass(DOMElement $parent): array
&& $node->namespaceURI === static::getNamespaceURI()
&& $node->localName === static::getLocalName()
) {
// Normalize the DOMElement by importing it into a clean empty document
$newDoc = DOMDocumentFactory::create();
/** @var \DOMElement $node */
$node = $newDoc->appendChild($newDoc->importNode($node, true));

$ret[] = static::fromXML($node);
}
}
Expand Down
26 changes: 26 additions & 0 deletions src/Assert/AnyURITrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

declare(strict_types=1);

namespace SimpleSAML\XML\Assert;

use InvalidArgumentException;

/**
* @package simplesamlphp/xml-common
*/
trait AnyURITrait
{
/**
* @param string $value
* @param string $message
*/
protected static function validAnyURI(string $value, string $message = ''): void
{
parent::validURI(
$value,
$message ?: '%s is not a valid xs:anyURI',
InvalidArgumentException::class,
);
}
}
Loading