Skip to content
This repository was archived by the owner on Jan 21, 2026. It is now read-only.

Commit a1f00e0

Browse files
committed
Migrate to xsd-types
1 parent b997e24 commit a1f00e0

12 files changed

Lines changed: 180 additions & 84 deletions

src/Assert/Assert.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@
88

99
/**
1010
* @package simplesamlphp/ws-security
11+
*
12+
* @method static void validWSUDateTime(mixed $value, string $message = '', string $exception = '')
13+
* @method static void allWSUDateTime(mixed $value, string $message = '', string $exception = '')
14+
* @method static void nullOrValueWSUDateTime(mixed $value, string $message = '', string $exception = '')
1115
*/
1216
class Assert extends BaseAssert
1317
{
18+
use WSUDateTimeTrait;
1419
}

src/Assert/WSUDateTimeTrait.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\WSSecurity\Assert;
6+
7+
use SimpleSAML\Assert\AssertionFailedException;
8+
use SimpleSAML\WSSecurity\Exception\ProtocolViolationException;
9+
10+
/**
11+
* @package simplesamlphp/ws-security
12+
*/
13+
trait WSUDateTimeTrait
14+
{
15+
/**
16+
* @param string $value
17+
* @param string $message
18+
*/
19+
protected static function validWSUDateTime(string $value, string $message = ''): void
20+
{
21+
parent::validDateTime($value);
22+
23+
try {
24+
parent::endsWith(
25+
$value,
26+
'Z',
27+
'%s is not a DateTime expressed in the UTC timezone using the \'Z\' timezone identifier.',
28+
);
29+
} catch (AssertionFailedException $e) {
30+
throw new ProtocolViolationException($e->getMessage());
31+
}
32+
}
33+
}

src/XML/wst_200512/Forwardable.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use SimpleSAML\XML\SchemaValidatableElementInterface;
88
use SimpleSAML\XML\SchemaValidatableElementTrait;
99
use SimpleSAML\XML\TypedTextContentTrait;
10-
use SimpleSAML\XMLSchema\Type\BooleanValue
10+
use SimpleSAML\XMLSchema\Type\BooleanValue;
1111

1212
/**
1313
* A Forwardable element

src/XML/wsu/AbstractAttributedDateTime.php

Lines changed: 17 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,16 @@
44

55
namespace SimpleSAML\WSSecurity\XML\wsu;
66

7-
use DateTimeImmutable;
87
use DOMElement;
98
use SimpleSAML\WSSecurity\Assert\Assert;
109
use SimpleSAML\WSSecurity\Constants as C;
1110
use SimpleSAML\WSSecurity\Exception\ProtocolViolationException;
11+
use SimpleSAML\WSSecurity\XML\wsu\Type\IDValue;
12+
use SimpleSAML\WSSecurity\XML\wsu\Type\DateTimeValue;
1213
use SimpleSAML\XML\Attribute as XMLAttribute;
13-
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1414
use SimpleSAML\XML\ExtendableAttributesTrait;
15-
use SimpleSAML\XML\XsNamespace as NS;
15+
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
16+
use SimpleSAML\XMLSchema\XML\Constants\NS;
1617

1718
/**
1819
* Abstract class defining the AttributedDateTime type
@@ -30,24 +31,23 @@ abstract class AbstractAttributedDateTime extends AbstractWsuElement
3031
/**
3132
* AbstractAttributedDateTime constructor
3233
*
33-
* @param \DateTimeImmutable $dateTime
34-
* @param string|null $Id
34+
* @param \SimpleSAML\WSSecurity\XML\wsu\Type\DateTimeValue $dateTime
35+
* @param \SimpleSAML\WSSecurity\XML\wsu\Type\IDValue|null $Id
3536
* @param array<\SimpleSAML\XML\Attribute> $namespacedAttributes
3637
*/
3738
final public function __construct(
38-
protected DateTimeImmutable $dateTime,
39-
protected ?string $Id = null,
39+
protected DateTimeValue $dateTime,
40+
protected ?IDValue $Id = null,
4041
array $namespacedAttributes = [],
4142
) {
42-
Assert::nullOrValidNCName($Id);
4343
$this->setAttributesNS($namespacedAttributes);
4444
}
4545

4646

4747
/**
48-
* @return string|null
48+
* @return \SimpleSAML\WSSecurity\XML\wsu\Type\IDValue|null
4949
*/
50-
public function getId(): ?string
50+
public function getId(): ?IDValue
5151
{
5252
return $this->Id;
5353
}
@@ -56,9 +56,9 @@ public function getId(): ?string
5656
/**
5757
* Collect the value of the dateTime property
5858
*
59-
* @return \DateTimeImmutable
59+
* @return \SimpleSAML\WSSecurity\XML\wsu\Type\DateTimeValue
6060
*/
61-
public function getDateTime(): DateTimeImmutable
61+
public function getDateTime(): DateTimeValue
6262
{
6363
return $this->dateTime;
6464
}
@@ -70,25 +70,20 @@ public function getDateTime(): DateTimeImmutable
7070
* @param \DOMElement $xml
7171
* @return static
7272
*
73-
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
73+
* @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
7474
* if the qualified name of the supplied element is wrong
7575
*/
7676
public static function fromXML(DOMElement $xml): static
7777
{
7878
Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class);
7979
Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
8080

81-
// Time values MUST be expressed in the UTC timezone using the 'Z' timezone identifier
82-
// Strip sub-seconds
83-
$xml->textContent = preg_replace('/([.][0-9]+)/', '', $xml->textContent, 1);
84-
Assert::validDateTime($xml->textContent, ProtocolViolationException::class);
85-
8681
$Id = null;
8782
if ($xml->hasAttributeNS(static::NS, 'Id')) {
88-
$Id = $xml->getAttributeNS(static::NS, 'Id');
83+
$Id = IDValue::fromString($xml->getAttributeNS(static::NS, 'Id'));
8984
}
9085

91-
return new static(new DateTimeImmutable($xml->textContent), $Id, self::getAttributesNSFromXML($xml));
86+
return new static(DateTimeValue::fromString($xml->textContent), $Id, self::getAttributesNSFromXML($xml));
9287
}
9388

9489

@@ -99,11 +94,11 @@ public static function fromXML(DOMElement $xml): static
9994
final public function toXML(?DOMElement $parent = null): DOMElement
10095
{
10196
$e = $this->instantiateParentElement($parent);
102-
$e->textContent = $this->getDateTime()->format(C::DATETIME_FORMAT);
97+
$e->textContent = $this->getDateTime()->getValue();
10398

10499
$attributes = $this->getAttributesNS();
105100
if ($this->getId() !== null) {
106-
$attributes[] = new XMLAttribute(static::NS, 'wsu', 'Id', $this->getId());
101+
$this->getId()->toAttribute()->toXML($e);
107102
}
108103

109104
foreach ($attributes as $attr) {

src/XML/wsu/AbstractAttributedURI.php

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@
66

77
use DOMElement;
88
use SimpleSAML\WSSecurity\Assert\Assert;
9+
use SimpleSAML\WSSecurity\XML\wsu\Type\IDValue;
910
use SimpleSAML\XML\Attribute as XMLAttribute;
10-
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1111
use SimpleSAML\XML\ExtendableAttributesTrait;
12-
use SimpleSAML\XML\URIElementTrait;
13-
use SimpleSAML\XML\XsNamespace as NS;
12+
use SimpleSAML\XML\TypedTextContentTrait;
13+
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
14+
use SimpleSAML\XMLSchema\Type\AnyURIValue;
15+
use SimpleSAML\XMLSchema\XML\Constants\NS;
1416

1517
/**
1618
* Abstract class defining the AttributedURI type
@@ -20,7 +22,10 @@
2022
abstract class AbstractAttributedURI extends AbstractWsuElement
2123
{
2224
use ExtendableAttributesTrait;
23-
use URIElementTrait;
25+
use TypedTextContentTrait;
26+
27+
/** @var string */
28+
public const TEXTCONTENT_TYPE = AnyURIValue::class;
2429

2530
/** The namespace-attribute for the xs:anyAttribute element */
2631
public const XS_ANY_ATTR_NAMESPACE = NS::OTHER;
@@ -29,13 +34,13 @@ abstract class AbstractAttributedURI extends AbstractWsuElement
2934
/**
3035
* AbstractAttributedURI constructor
3136
*
32-
* @param string $uri
33-
* @param string|null $Id
37+
* @param \SimpleSAML\XMLSchema\Type\AnyURIValue $uri
38+
* @param \SimpleSAML\WSSecurity\XML\wsu\Type\IDValue|null $Id
3439
* @param array<\SimpleSAML\XML\Attribute> $namespacedAttributes
3540
*/
3641
final protected function __construct(
37-
string $uri,
38-
protected ?string $Id = null,
42+
AnyURIValue $uri,
43+
protected ?IDValue $Id = null,
3944
array $namespacedAttributes = [],
4045
) {
4146
Assert::nullOrValidNCName($Id);
@@ -46,9 +51,9 @@ final protected function __construct(
4651

4752

4853
/**
49-
* @return string|null
54+
* @return \SimpleSAML\WSSecurity\XML\wsu\Type\IDValue|null
5055
*/
51-
public function getId(): ?string
56+
public function getId(): ?IDValue
5257
{
5358
return $this->Id;
5459
}
@@ -60,7 +65,7 @@ public function getId(): ?string
6065
* @param \DOMElement $xml
6166
* @return static
6267
*
63-
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
68+
* @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
6469
* if the qualified name of the supplied element is wrong
6570
*/
6671
public static function fromXML(DOMElement $xml): static
@@ -70,10 +75,10 @@ public static function fromXML(DOMElement $xml): static
7075

7176
$Id = null;
7277
if ($xml->hasAttributeNS(static::NS, 'Id')) {
73-
$Id = $xml->getAttributeNS(static::NS, 'Id');
78+
$Id = IDValue::fromString($xml->getAttributeNS(static::NS, 'Id'));
7479
}
7580

76-
return new static($xml->textContent, $Id, self::getAttributesNSFromXML($xml));
81+
return new static(AnyURIValue::fromString($xml->textContent), $Id, self::getAttributesNSFromXML($xml));
7782
}
7883

7984

@@ -84,11 +89,11 @@ public static function fromXML(DOMElement $xml): static
8489
final public function toXML(?DOMElement $parent = null): DOMElement
8590
{
8691
$e = $this->instantiateParentElement($parent);
87-
$e->textContent = $this->getContent();
92+
$e->textContent = $this->getContent()->getValue();
8893

8994
$attributes = $this->getAttributesNS();
9095
if ($this->getId() !== null) {
91-
$attributes[] = new XMLAttribute(static::NS, 'wsu', 'Id', $this->getId());
96+
$this->getId()->toAttribute()->toXML($e);
9297
}
9398

9499
foreach ($attributes as $attr) {

src/XML/wsu/AbstractTimestamp.php

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66

77
use DOMElement;
88
use SimpleSAML\WSSecurity\Assert\Assert;
9+
use SimpleSAML\WSSecurity\XML\wsu\Type\IDValue;
910
use SimpleSAML\XML\Attribute as XMLAttribute;
10-
use SimpleSAML\XML\Exception\InvalidDOMElementException;
1111
use SimpleSAML\XML\ExtendableAttributesTrait;
1212
use SimpleSAML\XML\ExtendableElementTrait;
13-
use SimpleSAML\XML\XsNamespace as NS;
13+
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
14+
use SimpleSAML\XMLSchema\XML\Constants\NS;
1415

1516
use function array_pop;
1617

@@ -42,28 +43,26 @@ abstract class AbstractTimestamp extends AbstractWsuElement
4243
*
4344
* @param \SimpleSAML\WSSecurity\XML\wsu\Created|null $created
4445
* @param \SimpleSAML\WSSecurity\XML\wsu\Expires|null $expires
45-
* @param string|null $Id
46+
* @param \SimpleSAML\WSSecurity\XML\wsu\Type\IDValue|null $Id
4647
* @param array<\SimpleSAML\XML\SerializableElementInterface> $elements
4748
* @param array<\SimpleSAML\XML\Attribute> $namespacedAttributes
4849
*/
4950
final public function __construct(
5051
protected ?Created $created = null,
5152
protected ?Expires $expires = null,
52-
protected ?string $Id = null,
53+
protected ?IDValue $Id = null,
5354
array $elements = [],
5455
array $namespacedAttributes = [],
5556
) {
56-
Assert::nullOrValidNCName($Id);
57-
5857
$this->setElements($elements);
5958
$this->setAttributesNS($namespacedAttributes);
6059
}
6160

6261

6362
/**
64-
* @return string|null
63+
* @return \SimpleSAML\WSSecurity\XML\wsu\Type\IDValue|null
6564
*/
66-
public function getId(): ?string
65+
public function getId(): ?IDValue
6766
{
6867
return $this->Id;
6968
}
@@ -108,7 +107,7 @@ public function isEmptyElement(): bool
108107
* @param \DOMElement $xml
109108
* @return static
110109
*
111-
* @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
110+
* @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
112111
* if the qualified name of the supplied element is wrong
113112
*/
114113
public static function fromXML(DOMElement $xml): static
@@ -122,7 +121,7 @@ public static function fromXML(DOMElement $xml): static
122121

123122
$Id = null;
124123
if ($xml->hasAttributeNS(static::NS, 'Id')) {
125-
$Id = $xml->getAttributeNS(static::NS, 'Id');
124+
$Id = IDValue::fromString($xml->getAttributeNS(static::NS, 'Id'));
126125
}
127126

128127
return new static(
@@ -147,7 +146,7 @@ public function toXML(?DOMElement $parent = null): DOMElement
147146

148147
$attributes = $this->getAttributesNS();
149148
if ($this->getId() !== null) {
150-
$attributes[] = new XMLAttribute(static::NS, 'wsu', 'Id', $this->getId());
149+
$this->getId()->toAttribute()->toXML($e);
151150
}
152151

153152
foreach ($attributes as $attr) {
@@ -158,7 +157,6 @@ public function toXML(?DOMElement $parent = null): DOMElement
158157
$this->getExpires()?->toXML($e);
159158

160159
foreach ($this->getElements() as $detail) {
161-
/** @psalm-var \SimpleSAML\XML\SerializableElementInterface $detail */
162160
$detail->toXML($e);
163161
}
164162

src/XML/wsu/Type/DateTimeValue.php

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\WSSecurity\XML\wsu\Type;
6+
7+
use SimpleSAML\WSSecurity\Assert\Assert;
8+
use SimpleSAML\WSSecurity\Exception\ProtocolViolationException;
9+
use SimpleSAML\XMLSchema\Type\DateTimeValue as BaseDateTimeValue;
10+
11+
/**
12+
* @package simplesaml/saml2
13+
*/
14+
class DateTimeValue extends BaseDateTimeValue
15+
{
16+
// Lowercase p as opposed to the base-class to covert the timestamp to UTC as demanded by the WSSecurity specifications
17+
public const DATETIME_FORMAT = 'Y-m-d\\TH:i:sp';
18+
19+
20+
/**
21+
* Validate the value.
22+
*
23+
* @param string $value
24+
* @return void
25+
*/
26+
protected function validateValue(string $value): void
27+
{
28+
// Note: value must already be sanitized before validating
29+
Assert::validWSUDateTime($this->sanitizeValue($value), ProtocolViolationException::class);
30+
}
31+
}

src/XML/wsu/Type/IDValue.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace SimpleSAML\WSSecurity\XML\wsu\Type;
6+
7+
use SimpleSAML\WSSecurity\Constants as C;
8+
use SimpleSAML\XML\Attribute;
9+
use SimpleSAML\XMLSchema\Type\IDValue as XSDIDValue;
10+
use SimpleSAML\XMLSchema\Type\Interface\AttributeTypeInterface;
11+
12+
/**
13+
* @package simplesaml/ws-security
14+
*/
15+
class IDValue extends XSDIDValue implements AttributeTypeInterface
16+
{
17+
/**
18+
* Convert this value to an attribute
19+
*
20+
* @return \SimpleSAML\XML\Attribute
21+
*/
22+
public function toAttribute(): Attribute
23+
{
24+
return new Attribute(C::NS_SEC_UTIL, 'wsu', 'Id', $this);
25+
}
26+
}

0 commit comments

Comments
 (0)