Passed
Pull Request — master (#6)
by Tim
13:32
created

SubjectConfirmationData::toXML()   B

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