Passed
Pull Request — master (#306)
by Tim
03:01
created

AbstractRoleDescriptor::getContactPersons()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML2\Compat\ContainerSingleton;
10
use SimpleSAML\SAML2\Constants as C;
11
use SimpleSAML\SAML2\Utils;
12
use SimpleSAML\SAML2\XML\ExtensionPointInterface;
13
use SimpleSAML\SAML2\XML\ExtensionPointTrait;
14
use SimpleSAML\XML\Chunk;
15
use SimpleSAML\XML\Exception\InvalidDOMElementException;
16
use SimpleSAML\XML\Exception\SchemaViolationException;
17
use SimpleSAML\XML\Exception\TooManyElementsException;
18
use SimpleSAML\XML\Utils as XMLUtils;
19
use SimpleSAML\XMLSecurity\Backend\EncryptionBackend;
20
use SimpleSAML\XMLSecurity\XML\EncryptableElementInterface;
21
use SimpleSAML\XMLSecurity\XML\EncryptableElementTrait;
22
23
use function array_pop;
24
use function count;
25
use function explode;
26
27
/**
28
 * SAML Metadata RoleDescriptor element.
29
 *
30
 * @package simplesamlphp/saml2
31
 */
32
abstract class AbstractRoleDescriptor extends AbstractRoleDescriptorType implements ExtensionPointInterface
33
{
34
    use ExtensionPointTrait;
35
36
    /** @var string */
37
    public const LOCALNAME = 'RoleDescriptor';
38
39
    /** @var string */
40
    protected string $type;
41
42
43
    /**
44
     * Initialize a saml:RoleDescriptor from scratch
45
     *
46
     * @param string $type
47
     * @param string[] $protocolSupportEnumeration A set of URI specifying the protocols supported.
48
     * @param string|null $ID The ID for this document. Defaults to null.
49
     * @param int|null $validUntil Unix time of validity for this document. Defaults to null.
50
     * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null.
51
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An Extensions object. Defaults to null.
52
     * @param string|null $errorURL An URI where to redirect users for support. Defaults to null.
53
     * @param \SimpleSAML\SAML2\XML\md\KeyDescriptor[] $keyDescriptors An array of KeyDescriptor elements. Defaults to an empty array.
54
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization The organization running this entity. Defaults to null.
55
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contacts An array of contacts for this entity. Defaults to an empty array.
56
     * @param \DOMAttr[] $namespacedAttributes
57
     */
58
    protected function __construct(
59
        string $type,
60
        array $protocolSupportEnumeration,
61
        ?string $ID = null,
62
        ?int $validUntil = null,
63
        ?string $cacheDuration = null,
64
        ?Extensions $extensions = null,
65
        ?string $errorURL = null,
66
        array $keyDescriptors = [],
67
        ?Organization $organization = null,
68
        array $contacts = [],
69
        array $namespacedAttributes = []
70
    ) {
71
        parent::__construct(
72
            $protocolSupportEnumeration,
73
            $ID,
74
            $validUntil,
75
            $cacheDuration,
76
            $extensions,
77
            $errorURL,
78
            $keyDescriptors,
79
            $organization,
80
            $contacts,
81
            $namespacedAttributes
82
        );
83
84
        $this->type = $type;
85
    }
86
87
88
    /**
89
     * @inheritDoc
90
     */
91
    public function getXsiType(): string
92
    {
93
        return $this->type;
94
    }
95
96
97
    /**
98
     * Convert XML into an RoleDescriptor
99
     *
100
     * @param \DOMElement $xml The XML element we should load
101
     * @return \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor
102
     *
103
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
104
     */
105
    public static function fromXML(DOMElement $xml): static
106
    {
107
        Assert::same($xml->localName, 'RoleDescriptor', InvalidDOMElementException::class);
108
        Assert::same($xml->namespaceURI, C::NS_MD, InvalidDOMElementException::class);
109
        Assert::true(
110
            $xml->hasAttributeNS(C::NS_XSI, 'type'),
111
            'Missing required xsi:type in <saml:RoleDescriptor> element.',
112
            SchemaViolationException::class
113
        );
114
115
        $type = $xml->getAttributeNS(C::NS_XSI, 'type');
116
        Assert::validQName($type, SchemaViolationException::class);
117
118
        // first, try to resolve the type to a full namespaced version
119
        $qname = explode(':', $type, 2);
120
        if (count($qname) === 2) {
121
            list($prefix, $element) = $qname;
122
        } else {
123
            $prefix = null;
124
            list($element) = $qname;
125
        }
126
        $ns = $xml->lookupNamespaceUri($prefix);
127
        $type = ($ns === null ) ? $element : implode(':', [$ns, $element]);
128
129
        // now check if we have a handler registered for it
130
        $handler = Utils::getContainer()->getExtensionHandler($type);
131
        if ($handler === null) {
132
            // we don't have a handler, proceed with unknown identifier
133
            $protocols = self::getAttribute($xml, 'protocolSupportEnumeration');
134
135
            $validUntil = self::getAttribute($xml, 'validUntil', null);
136
            $orgs = Organization::getChildrenOfClass($xml);
137
            Assert::maxCount($orgs, 1, 'More than one Organization found in this descriptor', TooManyElementsException::class);
138
139
            $extensions = Extensions::getChildrenOfClass($xml);
140
            Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
141
142
            return new UnknownRoleDescriptor(
143
                new Chunk($xml),
144
                $type,
145
                preg_split('/[\s]+/', trim($protocols)),
146
                self::getAttribute($xml, 'ID', null),
147
                $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
148
                self::getAttribute($xml, 'cacheDuration', null),
149
                array_pop($extensions),
150
                self::getAttribute($xml, 'errorURL', null),
151
                KeyDescriptor::getChildrenOfClass($xml),
152
                array_pop($orgs),
153
                ContactPerson::getChildrenOfClass($xml),
154
            );
155
        }
156
157
        Assert::subclassOf(
158
            $handler,
159
            AbstractRoleDescriptor::class,
160
            'Elements implementing RoleDescriptor must extend \SimpleSAML\SAML2\XML\saml\AbstractRoleDescriptor.',
161
        );
162
163
        return $handler::fromXML($xml);
164
    }
165
166
167
    /**
168
     * Convert this RoleDescriptor to XML.
169
     *
170
     * @param \DOMElement|null $parent The element we are converting to XML.
171
     * @return \DOMElement The XML element after adding the data corresponding to this RoleDescriptor.
172
     */
173
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
174
    {
175
        $e = parent::toUnsignedXML($parent);
176
177
        $xsiType = $e->ownerDocument->createAttributeNS(C::NS_XSI, 'xsi:type');
0 ignored issues
show
Bug introduced by
The method createAttributeNS() does not exist on null. ( Ignorable by Annotation )

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

177
        /** @scrutinizer ignore-call */ 
178
        $xsiType = $e->ownerDocument->createAttributeNS(C::NS_XSI, 'xsi:type');

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...
178
        $xsiType->value = $this->getXsiType();
179
        $e->setAttributeNodeNS($xsiType);
180
181
        $e->setAttribute('xmlns:' . static::getXsiTypePrefix(), static::getXsiTypeNamespaceURI());
182
183
        return $e;
184
    }
185
}
186