SubjectConfirmationData::toXML()   B
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 38
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 29
c 1
b 0
f 0
dl 0
loc 38
rs 8.8337
cc 6
nc 6
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML11\XML\saml;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML11\Type\SAMLStringValue;
10
use SimpleSAML\XML\AbstractElement;
11
use SimpleSAML\XML\Chunk;
12
use SimpleSAML\XML\{SchemaValidatableElementInterface, SchemaValidatableElementTrait};
13
use SimpleSAML\XMLSchema\Constants as C_XSI;
14
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
15
use SimpleSAML\XMLSchema\Type\IntegerValue;
16
use SimpleSAML\XMLSchema\Type\Interface\ValueTypeInterface;
17
18
use function class_exists;
19
use function explode;
20
use function gettype;
21
use function str_contains;
22
use function strval;
23
24
/**
25
 * Serializable class representing an SubjectConfirmationData.
26
 *
27
 * @package simplesamlphp/saml11
28
 */
29
class SubjectConfirmationData extends AbstractSamlElement implements SchemaValidatableElementInterface
30
{
31
    use SchemaValidatableElementTrait;
32
33
    /**
34
     * Create an SubjectConfirmationData.
35
     *
36
     * @param mixed $value The value of this element. Can be one of:
37
     *  - \SimpleSAML\XMLSchema\Type\IntegerValue
38
     *  - \SimpleSAML\SAML11\Type\SAMLStringValue
39
     *  - null
40
     *  - \SimpleSAML\XML\AbstractElement
41
     *
42
     * @throws \SimpleSAML\Assert\AssertionFailedException if the supplied value is neither a string or a DOMElement
43
     */
44
    final public function __construct(
45
        protected SAMLStringValue|IntegerValue|null|AbstractElement $value,
46
    ) {
47
    }
48
49
50
    /**
51
     * Get the XSI type of this attribute value.
52
     *
53
     * @return string
54
     */
55
    public function getXsiType(): string
56
    {
57
        $value = $this->getValue();
58
59
        if ($value === null) {
60
            return 'xs:nil';
61
        } elseif ($value instanceof ValueTypeInterface) {
62
            return $value::SCHEMA_NAMESPACE_PREFIX . ':' . $value::SCHEMA_TYPE;
63
        } else {
64
            return sprintf(
65
                '%s:%s',
66
                $value::getNamespacePrefix(),
67
                $value::getLocalName(),
68
            );
69
        }
70
    }
71
72
73
    /**
74
     * Get this attribute value.
75
     *
76
     * @return (
77
     *   \SimpleSAML\XMLSchema\Type\IntegerValue|
78
     *   \SimpleSAML\SAML11\Type\SAMLStringValue|
79
     *   \SimpleSAML\XML\AbstractElement|
80
     *   null
81
     * )
82
     */
83
    public function getValue(): SAMLStringValue|IntegerValue|AbstractElement|null
84
    {
85
        return $this->value;
86
    }
87
88
89
    /**
90
     * Convert XML into a SubjectConfirmationData
91
     *
92
     * @param \DOMElement $xml The XML element we should load
93
     * @return static
94
     *
95
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
96
     *   if the qualified name of the supplied element is wrong
97
     */
98
    public static function fromXML(DOMElement $xml): static
99
    {
100
        Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class);
101
        Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
102
103
        if ($xml->childElementCount > 0) {
104
            $node = $xml->firstElementChild;
105
106
            if (str_contains($node->tagName, ':')) {
107
                list($prefix, $eltName) = explode(':', $node->tagName);
108
                $className = sprintf('\SimpleSAML\SAML11\XML\%s\%s', $prefix, $eltName);
109
110
                if (class_exists($className)) {
111
                    $value = $className::fromXML($node);
112
                } else {
113
                    $value = Chunk::fromXML($node);
114
                }
115
            } else {
116
                $value = Chunk::fromXML($node);
117
            }
118
        } elseif (
119
            $xml->hasAttributeNS(C_XSI::NS_XSI, "type") &&
120
            $xml->getAttributeNS(C_XSI::NS_XSI, "type") === "xs:integer"
121
        ) {
122
            // we have an integer as value
123
            $value = IntegerValue::fromString($xml->textContent);
124
        } elseif (
125
            // null value
126
            $xml->hasAttributeNS(C_XSI::NS_XSI, "nil") &&
127
            ($xml->getAttributeNS(C_XSI::NS_XSI, "nil") === "1" ||
128
                $xml->getAttributeNS(C_XSI::NS_XSI, "nil") === "true")
129
        ) {
130
            $value = null;
131
        } else {
132
            $value = SAMLStringValue::fromString($xml->textContent);
133
        }
134
135
        return new static($value);
136
    }
137
138
139
    /**
140
     * Append this attribute value to an element.
141
     *
142
     * @param \DOMElement|null $parent The element we should append this attribute value to.
143
     *
144
     * @return \DOMElement The generated SubjectConfirmationData element.
145
     */
146
    public function toXML(?DOMElement $parent = null): DOMElement
147
    {
148
        $e = parent::instantiateParentElement($parent);
149
150
        $value = $this->getValue();
151
        $type = gettype($value);
152
153
        switch ($type) {
154
            case "integer":
155
                // make sure that the xs namespace is available in the SubjectConfirmationData
156
                $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C_XSI::NS_XSI);
157
                $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C_XSI::NS_XS);
158
                $e->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'xs:integer');
159
                $e->textContent = strval($value);
160
                break;
161
            case "NULL":
162
                $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C_XSI::NS_XSI);
163
                $e->setAttributeNS(C_XSI::NS_XSI, 'xsi:nil', '1');
164
                $e->textContent = '';
165
                break;
166
            case "object":
167
                if ($value instanceof ValueTypeInterface) {
168
                    if ($this->value instanceof IntegerValue) {
169
                        $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C_XSI::NS_XSI);
170
                        $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C_XSI::NS_XS);
171
                        $e->setAttributeNS(C_XSI::NS_XSI, 'xsi:type', 'xs:integer');
172
                    }
173
                    $e->textContent = strval($value);
174
                } else {
175
                    $value->toXML($e);
176
                }
177
                break;
178
            default: // string
179
                $e->textContent = strval($value);
180
                break;
181
        }
182
183
        return $e;
184
    }
185
}
186