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

AttributeValue::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\SAML11\Assert\Assert;
9
use SimpleSAML\SAML11\Constants as C;
10
use SimpleSAML\SAML11\Type\{DateTimeValue, StringValue};
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML11\Type\DateTimeValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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 AttributeValue.
25
 *
26
 * @package simplesamlphp/saml11
27
 */
28
class AttributeValue extends AbstractSamlElement implements SchemaValidatableElementInterface
29
{
30
    use SchemaValidatableElementTrait;
31
32
    /**
33
     * Create an AttributeValue.
34
     *
35
     * @param \SimpleSAML\XML\Type\ValueTypeInterface|\SimpleSAML\XML\AbstractElement $value
36
     * @throws \SimpleSAML\Assert\AssertionFailedException if the supplied value is neither a string or a DOMElement
37
     */
38
    final public function __construct(
39
        protected StringValue|IntegerValue|DateTimeValue|AbstractElement $value,
40
    ) {
41
    }
42
43
44
    /**
45
     * Get the XSI type of this attribute value.
46
     *
47
     * @return string
48
     */
49
    public function getXsiType(): string
50
    {
51
        $value = $this->getValue();
52
53
        if ($value === null) {
54
            return 'xs:nil';
55
        } elseif ($value instanceof ValueTypeInterface) {
0 ignored issues
show
introduced by
$value is never a sub-type of SimpleSAML\XML\Type\ValueTypeInterface.
Loading history...
56
            return $value::SCHEMA_TYPE;
57
        } else {
58
            return sprintf(
59
                '%s:%s',
60
                $value::getNamespacePrefix(),
61
                $value::getLocalName(),
62
            );
63
        }
64
    }
65
66
67
    /**
68
     * Get this attribute value.
69
     *
70
     * @return string|int|\SimpleSAML\XML\AbstractElement[]|null
71
     */
72
    public function getValue()
73
    {
74
        return $this->value;
75
    }
76
77
78
    /**
79
     * Convert XML into a AttributeValue
80
     *
81
     * @param \DOMElement $xml The XML element we should load
82
     * @return static
83
     *
84
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
85
     *   if the qualified name of the supplied element is wrong
86
     */
87
    public static function fromXML(DOMElement $xml): static
88
    {
89
        Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class);
90
        Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
91
92
        if ($xml->childElementCount > 0) {
93
            $node = $xml->firstElementChild;
94
95
            if (str_contains($node->tagName, ':')) {
96
                list($prefix, $eltName) = explode(':', $node->tagName);
97
                $className = sprintf('\SimpleSAML\SAML11\XML\%s\%s', $prefix, $eltName);
98
99
                if (class_exists($className)) {
100
                    $value = $className::fromXML($node);
101
                } else {
102
                    $value = Chunk::fromXML($node);
103
                }
104
            } else {
105
                $value = Chunk::fromXML($node);
106
            }
107
        } elseif (
108
            $xml->hasAttributeNS(C::NS_XSI, "type") &&
109
            $xml->getAttributeNS(C::NS_XSI, "type") === "xs:integer"
110
        ) {
111
            // we have an integer as value
112
            $value = IntegerValue::fromString($xml->textContent);
113
        } elseif (
114
            $xml->hasAttributeNS(C::NS_XSI, "nil") &&
115
            ($xml->getAttributeNS(C::NS_XSI, "nil") === "1" || $xml->getAttributeNS(C::NS_XSI, "nil") === "true")
116
        ) {
117
            // we have a nill value
118
            $value = null;
119
        } elseif (
120
            $xml->hasAttributeNS(C::NS_XSI, "type") &&
121
            $xml->getAttributeNS(C::NS_XSI, "type") === "xs:dateTime"
122
        ) {
123
            // we have a dateTime as value
124
            $value = DateTimeValue::fromString($xml->textContent);
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 AttributeValue 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 IntegerValue::class:
149
                // make sure that the xs namespace is available in the AttributeValue
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 "object":
156
                if ($value instanceof DateTimeValue) {
157
                    $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C::NS_XSI);
158
                    $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C::NS_XS);
159
                    $e->setAttributeNS(C::NS_XSI, 'xsi:type', 'xs:dateTime');
160
                    $e->textContent = strval($value);
161
                } elseif ($value instanceof ValueTypeInterface) {
162
                    if ($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