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

SubjectConfirmationData::getXsiType()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
c 1
b 0
f 0
nc 4
nop 0
dl 0
loc 17
rs 9.8333
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
        $type = gettype($this->value);
57
58
        switch ($type) {
59
            case "integer":
60
                return "xs:integer";
61
            case "NULL":
62
                return "xs:nil";
63
            case "object":
64
                return sprintf(
65
                    '%s:%s',
66
                    $this->value::getNamespacePrefix(),
0 ignored issues
show
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

66
                    $this->value::/** @scrutinizer ignore-call */ 
67
                                  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\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

66
                    $this->value::/** @scrutinizer ignore-call */ 
67
                                  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...
67
                    AbstractElement::getClassName(get_class($this->value)),
0 ignored issues
show
Bug introduced by
It seems like $this->value can also be of type null; however, parameter $object of get_class() does only seem to accept object, maybe add an additional type check? ( Ignorable by Annotation )

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

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