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

AbstractRoleDescriptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 27
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 12
c 0
b 0
f 0
nc 1
nop 11
dl 0
loc 27
rs 9.8666

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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