44
55namespace SimpleSAML \SAML2 \XML \saml ;
66
7+ use DateTimeImmutable ;
8+ use DateTimeInterface ;
79use DOMElement ;
810use SimpleSAML \Assert \Assert ;
911use SimpleSAML \SAML2 \Constants as C ;
@@ -27,16 +29,18 @@ class AttributeValue extends AbstractSamlElement
2729 /**
2830 * Create an AttributeValue.
2931 *
30- * @param string|int|null|\SimpleSAML\XML\AbstractElement $value The value of this element. Can be one of:
32+ * The value of this element. Can be one of:
3133 * - string
3234 * - int
3335 * - null
36+ * - \DateTimeInterface
3437 * - \SimpleSAML\XML\AbstractElement
3538 *
39+ * @param string|int|null|\DateTimeInterface|\SimpleSAML\XML\AbstractElement $value
3640 * @throws \SimpleSAML\Assert\AssertionFailedException if the supplied value is neither a string or a DOMElement
3741 */
3842 final public function __construct (
39- protected string |int |null |AbstractElement $ value ,
43+ protected string |int |null |DateTimeInterface | AbstractElement $ value ,
4044 ) {
4145 }
4246
@@ -48,18 +52,23 @@ final public function __construct(
4852 */
4953 public function getXsiType (): string
5054 {
51- $ type = gettype ($ this ->value );
55+ $ value = $ this ->getValue ();
56+ $ type = gettype ($ value );
5257
5358 switch ($ type ) {
5459 case "integer " :
5560 return "xs:integer " ;
5661 case "NULL " :
5762 return "xs:nil " ;
5863 case "object " :
64+ if ($ value instanceof DateTimeInterface) {
65+ return 'xs:dateTime ' ;
66+ }
67+
5968 return sprintf (
6069 '%s:%s ' ,
61- $ this -> value ::getNamespacePrefix (),
62- AbstractElement::getClassName (get_class ($ this -> value )),
70+ $ value ::getNamespacePrefix (),
71+ AbstractElement::getClassName (get_class ($ value )),
6372 );
6473 default :
6574 return "xs:string " ;
@@ -111,14 +120,26 @@ public static function fromXML(DOMElement $xml): static
111120 $ xml ->hasAttributeNS (C::NS_XSI , "type " ) &&
112121 $ xml ->getAttributeNS (C::NS_XSI , "type " ) === "xs:integer "
113122 ) {
123+ Assert::numeric ($ xml ->textContent );
124+
114125 // we have an integer as value
115126 $ value = intval ($ xml ->textContent );
127+ } elseif (
128+ $ xml ->hasAttributeNS (C::NS_XSI , "type " ) &&
129+ $ xml ->getAttributeNS (C::NS_XSI , "type " ) === "xs:dateTime "
130+ ) {
131+ Assert::validDateTime ($ xml ->textContent );
132+
133+ // we have a dateTime as value
134+ $ value = new DateTimeImmutable ($ xml ->textContent );
116135 } elseif (
117136 // null value
118137 $ xml ->hasAttributeNS (C::NS_XSI , "nil " ) &&
119138 ($ xml ->getAttributeNS (C::NS_XSI , "nil " ) === "1 " ||
120139 $ xml ->getAttributeNS (C::NS_XSI , "nil " ) === "true " )
121140 ) {
141+ Assert::isEmpty ($ xml ->textContent );
142+
122143 $ value = null ;
123144 } else {
124145 $ value = $ xml ->textContent ;
@@ -139,26 +160,34 @@ public function toXML(DOMElement $parent = null): DOMElement
139160 {
140161 $ e = parent ::instantiateParentElement ($ parent );
141162
142- $ type = gettype ($ this ->value );
163+ $ value = $ this ->getValue ();
164+ $ type = gettype ($ value );
143165
144166 switch ($ type ) {
145167 case "integer " :
146168 // make sure that the xs namespace is available in the AttributeValue
147169 $ e ->setAttributeNS ('http://www.w3.org/2000/xmlns/ ' , 'xmlns:xsi ' , C::NS_XSI );
148170 $ e ->setAttributeNS ('http://www.w3.org/2000/xmlns/ ' , 'xmlns:xs ' , C::NS_XS );
149171 $ e ->setAttributeNS (C::NS_XSI , 'xsi:type ' , 'xs:integer ' );
150- $ e ->textContent = strval ($ this -> getValue () );
172+ $ e ->textContent = strval ($ value );
151173 break ;
152174 case "NULL " :
153175 $ e ->setAttributeNS ('http://www.w3.org/2000/xmlns/ ' , 'xmlns:xsi ' , C::NS_XSI );
154176 $ e ->setAttributeNS (C::NS_XSI , 'xsi:nil ' , '1 ' );
155177 $ e ->textContent = '' ;
156178 break ;
157179 case "object " :
158- $ this ->getValue ()->toXML ($ e );
180+ if ($ value instanceof DateTimeInterface) {
181+ $ e ->setAttributeNS ('http://www.w3.org/2000/xmlns/ ' , 'xmlns:xsi ' , C::NS_XSI );
182+ $ e ->setAttributeNS ('http://www.w3.org/2000/xmlns/ ' , 'xmlns:xs ' , C::NS_XS );
183+ $ e ->setAttributeNS (C::NS_XSI , 'xsi:type ' , 'xs:dateTime ' );
184+ $ e ->textContent = $ value ->format (C::DATETIME_FORMAT );
185+ } else {
186+ $ value ->toXML ($ e );
187+ }
159188 break ;
160189 default : // string
161- $ e ->textContent = $ this -> getValue () ;
190+ $ e ->textContent = $ value ;
162191 break ;
163192 }
164193
0 commit comments