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

AttributeValue::getValue()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
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
     * The value of this element. Can be one of:
36
     *  - \SimpleSAML\SAML11\Type\StringValue
37
     *  - \SimpleSAML\SAML11\Type\DateTimeValue
38
     *  - \SimpleSAML\XML\Type\IntegerValue
39
     *  - \SimpleSAML\XML\AbstractElement
40
     *
41
     * @param string|int|\DateTimeInterface|\SimpleSAML\XML\AbstractElement $value
42
     * @throws \SimpleSAML\Assert\AssertionFailedException if the supplied value is neither a string or a DOMElement
43
     */
44
    final public function __construct(
45
        protected StringValue|IntegerValue|DateTimeValue|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
        $type = gettype($value);
59
60
        switch ($type) {
61
            case "integer":
62
                return "xs:integer";
63
            case "object":
64
                if ($value instanceof DateTimeInterface) {
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML11\XML\saml\DateTimeInterface was not found. Did you mean DateTimeInterface? If so, make sure to prefix the type with \.
Loading history...
65
                    return 'xs:dateTime';
66
                }
67
68
                return sprintf(
69
                    '%s:%s',
70
                    $this->value::getNamespacePrefix(),
0 ignored issues
show
Bug introduced by
The method getNamespacePrefix() does not exist on SimpleSAML\SAML11\Type\StringValue. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
                    $this->value::/** @scrutinizer ignore-call */ 
71
                                  getNamespacePrefix(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
Bug introduced by
The method getNamespacePrefix() does not exist on SimpleSAML\XML\Type\IntegerValue. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

70
                    $this->value::/** @scrutinizer ignore-call */ 
71
                                  getNamespacePrefix(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
71
                    AbstractElement::getClassName(get_class($value)),
72
                );
73
            default:
74
                return "xs:string";
75
        }
76
    }
77
78
79
    /**
80
     * Get this attribute value.
81
     *
82
     * @return string|int|\SimpleSAML\XML\AbstractElement[]|null
83
     */
84
    public function getValue()
85
    {
86
        return $this->value;
87
    }
88
89
90
    /**
91
     * Convert XML into a AttributeValue
92
     *
93
     * @param \DOMElement $xml The XML element we should load
94
     * @return static
95
     *
96
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
97
     *   if the qualified name of the supplied element is wrong
98
     */
99
    public static function fromXML(DOMElement $xml): static
100
    {
101
        Assert::same($xml->localName, static::getLocalName(), InvalidDOMElementException::class);
102
        Assert::same($xml->namespaceURI, static::NS, InvalidDOMElementException::class);
103
104
        if ($xml->childElementCount > 0) {
105
            $node = $xml->firstElementChild;
106
107
            if (str_contains($node->tagName, ':')) {
108
                list($prefix, $eltName) = explode(':', $node->tagName);
109
                $className = sprintf('\SimpleSAML\SAML11\XML\%s\%s', $prefix, $eltName);
110
111
                if (class_exists($className)) {
112
                    $value = $className::fromXML($node);
113
                } else {
114
                    $value = Chunk::fromXML($node);
115
                }
116
            } else {
117
                $value = Chunk::fromXML($node);
118
            }
119
        } elseif (
120
            $xml->hasAttributeNS(C::NS_XSI, "type") &&
121
            $xml->getAttributeNS(C::NS_XSI, "type") === "xs:integer"
122
        ) {
123
            // we have an integer as value
124
            $value = IntegerValue::fromString($xml->textContent);
125
        } elseif (
126
            $xml->hasAttributeNS(C::NS_XSI, "nil") &&
127
            ($xml->getAttributeNS(C::NS_XSI, "nil") === "1" || $xml->getAttributeNS(C::NS_XSI, "nil") === "true")
128
        ) {
129
            // we have a nill value
130
            $value = null;
131
        } elseif (
132
            $xml->hasAttributeNS(C::NS_XSI, "type") &&
133
            $xml->getAttributeNS(C::NS_XSI, "type") === "xs:dateTime"
134
        ) {
135
            // we have a dateTime as value
136
            $value = DateTimeValue::fromString($xml->textContent);
137
        } else {
138
            $value = StringValue::fromString($xml->textContent);
139
        }
140
141
        return new static($value);
142
    }
143
144
145
    /**
146
     * Append this attribute value to an element.
147
     *
148
     * @param \DOMElement|null $parent The element we should append this attribute value to.
149
     *
150
     * @return \DOMElement The generated AttributeValue element.
151
     */
152
    public function toXML(?DOMElement $parent = null): DOMElement
153
    {
154
        $e = parent::instantiateParentElement($parent);
155
156
        $value = $this->getValue();
157
        $type = gettype($value);
158
159
        switch ($type) {
160
            case "integer":
161
            case IntegerValue::class:
162
                // make sure that the xs namespace is available in the AttributeValue
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
                $e->textContent = strval($value);
167
                break;
168
            case "object":
169
                if ($value instanceof DateTimeInterface || $value instanceof DateTimeValue) {
170
                    $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C::NS_XSI);
171
                    $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C::NS_XS);
172
                    $e->setAttributeNS(C::NS_XSI, 'xsi:type', 'xs:dateTime');
173
                    $e->textContent = strval($value);
174
                } elseif ($value instanceof ValueTypeInterface) {
175
                    if ($value instanceof IntegerValue) {
176
                        $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xsi', C::NS_XSI);
177
                        $e->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xs', C::NS_XS);
178
                        $e->setAttributeNS(C::NS_XSI, 'xsi:type', 'xs:integer');
179
                    }
180
                    $e->textContent = strval($value);
181
                } else {
182
                    $value->toXML($e);
183
                }
184
                break;
185
            default: // string
186
                $e->textContent = strval($value);
187
                break;
188
        }
189
190
        return $e;
191
    }
192
}
193