EntityDescriptor::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 41
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 22
nc 1
nop 11
dl 0
loc 41
rs 9.568
c 0
b 0
f 0

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 DateTimeImmutable;
8
use DOMElement;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\Assert\Assert as SAMLAssert;
11
use SimpleSAML\SAML2\Constants as C;
12
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
13
use SimpleSAML\XML\Exception\InvalidDOMElementException;
14
use SimpleSAML\XML\Exception\TooManyElementsException;
15
use SimpleSAML\XML\ExtendableAttributesTrait;
16
use SimpleSAML\XML\SchemaValidatableElementInterface;
17
use SimpleSAML\XML\SchemaValidatableElementTrait;
18
use SimpleSAML\XML\XsNamespace as NS;
19
use SimpleSAML\XMLSecurity\XML\ds\Signature;
20
21
use function is_null;
22
23
/**
24
 * Class representing SAML 2 EntityDescriptor element.
25
 *
26
 * @package simplesamlphp/saml2
27
 */
28
final class EntityDescriptor extends AbstractMetadataDocument implements SchemaValidatableElementInterface
29
{
30
    use ExtendableAttributesTrait;
31
    use SchemaValidatableElementTrait;
32
33
    /** The namespace-attribute for the xs:anyAttribute element */
34
    public const XS_ANY_ATTR_NAMESPACE = NS::OTHER;
35
36
37
    /**
38
     * Initialize an EntitiyDescriptor.
39
     *
40
     * @param string $entityId The entityID of the entity described by this descriptor.
41
     * @param string|null $id The ID for this document. Defaults to null.
42
     * @param \DateTimeImmutable|null $validUntil Unix time of validify for this document. Defaults to null.
43
     * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null.
44
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions.
45
     * @param \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType[] $roleDescriptor An array of role descriptors.
46
     * @param \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor An affiliation descriptor to
47
     *   use instead of role descriptors.
48
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization The organization responsible for the SAML entity.
49
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contactPerson A list of contact persons for this SAML entity.
50
     * @param \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[] $additionalMetadataLocation A list of
51
     *   additional metadata locations.
52
     * @param list<\SimpleSAML\XML\Attribute> $namespacedAttribute
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\md\list 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...
53
     *
54
     * @throws \Exception
55
     */
56
    public function __construct(
57
        protected string $entityId,
58
        ?string $id = null,
59
        ?DateTimeImmutable $validUntil = null,
60
        ?string $cacheDuration = null,
61
        ?Extensions $extensions = null,
62
        protected array $roleDescriptor = [],
63
        protected ?AffiliationDescriptor $affiliationDescriptor = null,
64
        protected ?Organization $organization = null,
65
        protected array $contactPerson = [],
66
        protected array $additionalMetadataLocation = [],
67
        array $namespacedAttribute = [],
68
    ) {
69
        Assert::false(
70
            (empty($roleDescriptor) && $affiliationDescriptor === null),
71
            'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.',
72
            ProtocolViolationException::class,
73
        );
74
        SAMLAssert::validEntityID($entityId);
75
        Assert::maxCount($roleDescriptor, C::UNBOUNDED_LIMIT);
76
        Assert::allIsInstanceOf(
77
            $roleDescriptor,
78
            AbstractRoleDescriptorType::class,
79
            'All role descriptors must extend AbstractRoleDescriptor.',
80
        );
81
        Assert::maxCount($contactPerson, C::UNBOUNDED_LIMIT);
82
        Assert::allIsInstanceOf(
83
            $contactPerson,
84
            ContactPerson::class,
85
            'All md:ContactPerson elements must be an instance of ContactPerson.',
86
        );
87
        Assert::maxCount($additionalMetadataLocation, C::UNBOUNDED_LIMIT);
88
        Assert::allIsInstanceOf(
89
            $additionalMetadataLocation,
90
            AdditionalMetadataLocation::class,
91
            'All md:AdditionalMetadataLocation elements must be an instance of AdditionalMetadataLocation',
92
        );
93
94
        parent::__construct($id, $validUntil, $cacheDuration, $extensions);
95
96
        $this->setAttributesNS($namespacedAttribute);
97
    }
98
99
100
    /**
101
     * Convert an existing XML into an EntityDescriptor object
102
     *
103
     * @param \DOMElement $xml An existing EntityDescriptor XML document.
104
     * @return static
105
     *
106
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
107
     *   if the qualified name of the supplied element is wrong
108
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
109
     *   if the supplied element is missing one of the mandatory attributes
110
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException
111
     *   if too many child-elements of a type are specified
112
     */
113
    public static function fromXML(DOMElement $xml): static
114
    {
115
        Assert::same($xml->localName, 'EntityDescriptor', InvalidDOMElementException::class);
116
        Assert::same($xml->namespaceURI, EntityDescriptor::NS, InvalidDOMElementException::class);
117
118
        $validUntil = self::getOptionalAttribute($xml, 'validUntil', null);
119
        SAMLAssert::nullOrValidDateTime($validUntil);
120
121
        $extensions = Extensions::getChildrenOfClass($xml);
122
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
123
124
        $signature = Signature::getChildrenOfClass($xml);
125
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
126
127
        $entityID = self::getAttribute($xml, 'entityID');
128
        $roleDescriptors = [];
129
        $affiliationDescriptor = null;
130
        $organization = null;
131
        $contactPersons = [];
132
        $additionalMetadataLocation = [];
133
        foreach ($xml->childNodes as $node) {
134
            if (
135
                !($node instanceof DOMElement)
136
                || ($node->namespaceURI !== C::NS_MD)
137
            ) {
138
                continue;
139
            }
140
141
            switch ($node->localName) {
142
                case 'Extensions':
143
                    continue 2;
144
                case 'IDPSSODescriptor':
145
                    $roleDescriptors[] = IDPSSODescriptor::fromXML($node);
146
                    break;
147
                case 'SPSSODescriptor':
148
                    $roleDescriptors[] = SPSSODescriptor::fromXML($node);
149
                    break;
150
                case 'AuthnAuthorityDescriptor':
151
                    $roleDescriptors[] = AuthnAuthorityDescriptor::fromXML($node);
152
                    break;
153
                case 'AttributeAuthorityDescriptor':
154
                    $roleDescriptors[] = AttributeAuthorityDescriptor::fromXML($node);
155
                    break;
156
                case 'PDPDescriptor':
157
                    $roleDescriptors[] = PDPDescriptor::fromXML($node);
158
                    break;
159
                case 'AffiliationDescriptor':
160
                    if ($affiliationDescriptor !== null) {
161
                        throw new TooManyElementsException('More than one AffiliationDescriptor in the entity.');
162
                    }
163
                    $affiliationDescriptor = AffiliationDescriptor::fromXML($node);
164
                    break;
165
                case 'Organization':
166
                    if ($organization !== null) {
167
                        throw new TooManyElementsException('More than one Organization in the entity.');
168
                    }
169
                    $organization = Organization::fromXML($node);
170
                    break;
171
                case 'ContactPerson':
172
                    $contactPersons[] = ContactPerson::fromXML($node);
173
                    break;
174
                case 'AdditionalMetadataLocation':
175
                    $additionalMetadataLocation[] = AdditionalMetadataLocation::fromXML($node);
176
                    break;
177
                default:
178
                    $roleDescriptors[] = UnknownRoleDescriptor::fromXML($node);
179
            }
180
        }
181
182
        Assert::false(
183
            empty($roleDescriptors) && is_null($affiliationDescriptor),
184
            'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.',
185
            ProtocolViolationException::class,
186
        );
187
        Assert::false(
188
            !empty($roleDescriptors) && !is_null($affiliationDescriptor),
189
            'AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.',
190
            ProtocolViolationException::class,
191
        );
192
193
        $entity = new static(
194
            $entityID,
195
            self::getOptionalAttribute($xml, 'ID', null),
196
            $validUntil !== null ? new DateTimeImmutable($validUntil) : null,
197
            self::getOptionalAttribute($xml, 'cacheDuration', null),
198
            !empty($extensions) ? $extensions[0] : null,
199
            $roleDescriptors,
200
            $affiliationDescriptor,
201
            $organization,
202
            $contactPersons,
203
            $additionalMetadataLocation,
204
            self::getAttributesNSFromXML($xml),
205
        );
206
207
        if (!empty($signature)) {
208
            $entity->setSignature($signature[0]);
209
            $entity->setXML($xml);
210
        }
211
212
        return $entity;
213
    }
214
215
216
    /**
217
     * Collect the value of the entityID property.
218
     *
219
     * @return string
220
     * @throws \SimpleSAML\Assert\AssertionFailedException
221
     */
222
    public function getEntityId(): string
223
    {
224
        return $this->entityId;
225
    }
226
227
228
    /**
229
     * Collect the value of the RoleDescriptor property.
230
     *
231
     * @return \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType[]
232
     */
233
    public function getRoleDescriptor(): array
234
    {
235
        return $this->roleDescriptor;
236
    }
237
238
239
    /**
240
     * Collect the value of the AffiliationDescriptor property.
241
     *
242
     * @return \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null
243
     */
244
    public function getAffiliationDescriptor(): ?AffiliationDescriptor
245
    {
246
        return $this->affiliationDescriptor;
247
    }
248
249
250
    /**
251
     * Collect the value of the Organization property.
252
     *
253
     * @return \SimpleSAML\SAML2\XML\md\Organization|null
254
     */
255
    public function getOrganization(): ?Organization
256
    {
257
        return $this->organization;
258
    }
259
260
261
    /**
262
     * Collect the value of the ContactPerson property.
263
     *
264
     * @return \SimpleSAML\SAML2\XML\md\ContactPerson[]
265
     */
266
    public function getContactPerson(): array
267
    {
268
        return $this->contactPerson;
269
    }
270
271
272
    /**
273
     * Collect the value of the AdditionalMetadataLocation property.
274
     *
275
     * @return \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[]
276
     */
277
    public function getAdditionalMetadataLocation(): array
278
    {
279
        return $this->additionalMetadataLocation;
280
    }
281
282
283
    /**
284
     * Convert this assertion to an unsigned XML document.
285
     * This method does not sign the resulting XML document.
286
     *
287
     * @return \DOMElement The root element of the DOM tree
288
     */
289
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
290
    {
291
        $e = parent::toUnsignedXML($parent);
292
        $e->setAttribute('entityID', $this->getEntityId());
293
294
        foreach ($this->getAttributesNS() as $attr) {
295
            $attr->toXML($e);
296
        }
297
298
        foreach ($this->getRoleDescriptor() as $n) {
299
            $n->toXML($e);
300
        }
301
302
        $this->getAffiliationDescriptor()?->toXML($e);
303
        $this->getOrganization()?->toXML($e);
304
305
        foreach ($this->getContactPerson() as $cp) {
306
            $cp->toXML($e);
307
        }
308
309
        foreach ($this->getAdditionalMetadataLocation() as $n) {
310
            $n->toXML($e);
311
        }
312
313
        return $e;
314
    }
315
}
316