Passed
Pull Request — master (#280)
by Tim
02:22
created

EntityDescriptor::__construct()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 27
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 10
nc 2
nop 11
dl 0
loc 27
rs 9.9332
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 DOMElement;
8
use InvalidArgumentException;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\Constants;
11
use SimpleSAML\XML\Exception\InvalidDOMElementException;
12
use SimpleSAML\XML\Exception\TooManyElementsException;
13
use SimpleSAML\XML\Utils as XMLUtils;
14
use SimpleSAML\XMLSecurity\XML\ds\Signature;
15
16
use function is_null;
17
18
/**
19
 * Class representing SAML 2 EntityDescriptor element.
20
 *
21
 * @package simplesamlphp/saml2
22
 */
23
final class EntityDescriptor extends AbstractMetadataDocument
24
{
25
    /**
26
     * The entityID this EntityDescriptor represents.
27
     *
28
     * @var string
29
     */
30
    protected string $entityID;
31
32
    /**
33
     * Array with all roles for this entity.
34
     *
35
     * Array of \SimpleSAML\SAML2\XML\md\RoleDescriptor objects (and subclasses of RoleDescriptor).
36
     *
37
     * @var \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor[]
38
     */
39
    protected array $RoleDescriptor = [];
40
41
    /**
42
     * AffiliationDescriptor of this entity.
43
     *
44
     * @var \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null
45
     */
46
    protected ?AffiliationDescriptor $AffiliationDescriptor = null;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\md\AffiliationDescriptor 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...
47
48
    /**
49
     * Organization of this entity.
50
     *
51
     * @var \SimpleSAML\SAML2\XML\md\Organization|null
52
     */
53
    protected ?Organization $Organization = null;
54
55
    /**
56
     * ContactPerson elements for this entity.
57
     *
58
     * @var \SimpleSAML\SAML2\XML\md\ContactPerson[]
59
     */
60
    protected array $ContactPerson = [];
61
62
    /**
63
     * AdditionalMetadataLocation elements for this entity.
64
     *
65
     * @var \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[]
66
     */
67
    protected array $AdditionalMetadataLocation = [];
68
69
70
    /**
71
     * Initialize an EntitiyDescriptor.
72
     *
73
     * @param string $entityID The entityID of the entity described by this descriptor.
74
     * @param string|null $id The ID for this document. Defaults to null.
75
     * @param int|null $validUntil Unix time of validify for this document. Defaults to null.
76
     * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null.
77
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions.
78
     * @param \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor[] $roleDescriptors An array of role descriptors.
79
     * @param \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor An affiliation descriptor to
80
     *   use instead of role descriptors.
81
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization The organization responsible for the SAML entity.
82
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contacts A list of contact persons for this SAML entity.
83
     * @param \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[] $additionalMdLocations A list of
84
     *   additional metadata locations.
85
     * @param \DOMAttr[] $namespacedAttributes
86
     *
87
     * @throws \Exception
88
     */
89
    public function __construct(
90
        string $entityID,
91
        ?string $id = null,
92
        ?int $validUntil = null,
93
        ?string $cacheDuration = null,
94
        Extensions $extensions = null,
95
        array $roleDescriptors = [],
96
        ?AffiliationDescriptor $affiliationDescriptor = null,
97
        ?Organization $organization = null,
98
        array $contacts = [],
99
        array $additionalMdLocations = [],
100
        array $namespacedAttributes = []
101
    ) {
102
        if (empty($roleDescriptors) && $affiliationDescriptor === null) {
103
            throw new InvalidArgumentException(
104
                'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'
105
            );
106
        }
107
108
        parent::__construct($id, $validUntil, $cacheDuration, $extensions, $namespacedAttributes);
109
110
        $this->setEntityID($entityID);
111
        $this->setRoleDescriptors($roleDescriptors);
112
        $this->setAffiliationDescriptor($affiliationDescriptor);
113
        $this->setOrganization($organization);
114
        $this->setContactPersons($contacts);
115
        $this->setAdditionalMetadataLocations($additionalMdLocations);
116
    }
117
118
119
    /**
120
     * Convert an existing XML into an EntityDescriptor object
121
     *
122
     * @param \DOMElement $xml An existing EntityDescriptor XML document.
123
     * @return \SimpleSAML\SAML2\XML\md\EntityDescriptor An object representing the given document.
124
     *
125
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
126
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
127
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
128
     */
129
    public static function fromXML(DOMElement $xml): object
130
    {
131
        Assert::same($xml->localName, 'EntityDescriptor', InvalidDOMElementException::class);
132
        Assert::same($xml->namespaceURI, EntityDescriptor::NS, InvalidDOMElementException::class);
133
134
        $validUntil = self::getAttribute($xml, 'validUntil', null);
135
        $extensions = Extensions::getChildrenOfClass($xml);
136
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
137
138
        $signature = Signature::getChildrenOfClass($xml);
139
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
140
141
        $entityID = self::getAttribute($xml, 'entityID');
142
        $roleDescriptors = [];
143
        $affiliationDescriptor = null;
144
        $organization = null;
145
        $contactPersons = [];
146
        $additionalMetadataLocation = [];
147
        foreach ($xml->childNodes as $node) {
148
            if (
149
                !($node instanceof DOMElement)
150
                || ($node->namespaceURI !== Constants::NS_MD)
151
            ) {
152
                continue;
153
            }
154
155
            switch ($node->localName) {
156
                case 'Extensions':
157
                    continue 2;
158
                case 'IDPSSODescriptor':
159
                    $roleDescriptors[] = IDPSSODescriptor::fromXML($node);
160
                    break;
161
                case 'SPSSODescriptor':
162
                    $roleDescriptors[] = SPSSODescriptor::fromXML($node);
163
                    break;
164
                case 'AuthnAuthorityDescriptor':
165
                    $roleDescriptors[] = AuthnAuthorityDescriptor::fromXML($node);
166
                    break;
167
                case 'AttributeAuthorityDescriptor':
168
                    $roleDescriptors[] = AttributeAuthorityDescriptor::fromXML($node);
169
                    break;
170
                case 'PDPDescriptor':
171
                    $roleDescriptors[] = PDPDescriptor::fromXML($node);
172
                    break;
173
                case 'AffiliationDescriptor':
174
                    if ($affiliationDescriptor !== null) {
175
                        throw new TooManyElementsException('More than one AffiliationDescriptor in the entity.');
176
                    }
177
                    $affiliationDescriptor = AffiliationDescriptor::fromXML($node);
178
                    break;
179
                case 'Organization':
180
                    if ($organization !== null) {
181
                        throw new TooManyElementsException('More than one Organization in the entity.');
182
                    }
183
                    $organization = Organization::fromXML($node);
184
                    break;
185
                case 'ContactPerson':
186
                    $contactPersons[] = ContactPerson::fromXML($node);
187
                    break;
188
                case 'AdditionalMetadataLocation':
189
                    $additionalMetadataLocation[] = AdditionalMetadataLocation::fromXML($node);
190
                    break;
191
                default:
192
                    $roleDescriptors[] = UnknownRoleDescriptor::fromXML($node);
193
            }
194
        }
195
196
        if (empty($roleDescriptors) && is_null($affiliationDescriptor)) {
197
            throw new InvalidArgumentException(
198
                'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'
199
            );
200
        } elseif (!empty($roleDescriptors) && !is_null($affiliationDescriptor)) {
201
            throw new InvalidArgumentException(
202
                'AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.'
203
            );
204
        }
205
206
        $entity = new self(
207
            $entityID,
208
            self::getAttribute($xml, 'ID', null),
209
            $validUntil !== null ? XMLUtils::xsDateTimeToTimestamp($validUntil) : null,
210
            self::getAttribute($xml, 'cacheDuration', null),
211
            !empty($extensions) ? $extensions[0] : null,
212
            $roleDescriptors,
213
            $affiliationDescriptor,
214
            $organization,
215
            $contactPersons,
216
            $additionalMetadataLocation,
217
            self::getAttributesNSFromXML($xml)
218
        );
219
220
        if (!empty($signature)) {
221
            $entity->setSignature($signature[0]);
222
        }
223
224
        $entity->setXML($xml);
225
226
        return $entity;
227
    }
228
229
230
    /**
231
     * Collect the value of the entityID property.
232
     *
233
     * @return string
234
     * @throws \SimpleSAML\Assert\AssertionFailedException
235
     */
236
    public function getEntityID(): string
237
    {
238
        Assert::notEmpty($this->entityID);
239
240
        return $this->entityID;
241
    }
242
243
244
    /**
245
     * Set the value of the entityID-property
246
     * @param string $entityId
247
     */
248
    protected function setEntityID(string $entityId): void
249
    {
250
        Assert::notEmpty($entityId, 'The entityID attribute cannot be empty.');
251
        Assert::maxLength($entityId, 1024, 'The entityID attribute cannot be longer than 1024 characters.');
252
        $this->entityID = $entityId;
253
    }
254
255
256
    /**
257
     * Collect the value of the RoleDescriptor property.
258
     *
259
     * @return \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor[]
260
     */
261
    public function getRoleDescriptors(): array
262
    {
263
        return $this->RoleDescriptor;
264
    }
265
266
267
    /**
268
     * Set the value of the RoleDescriptor property.
269
     *
270
     * @param \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptor[] $roleDescriptors
271
     * @throws \SimpleSAML\Assert\AssertionFailedException
272
     */
273
    protected function setRoleDescriptors(array $roleDescriptors): void
274
    {
275
        Assert::allIsInstanceOf(
276
            $roleDescriptors,
277
            AbstractRoleDescriptor::class,
278
            'All role descriptors must extend AbstractRoleDescriptor.'
279
        );
280
        $this->RoleDescriptor = $roleDescriptors;
281
    }
282
283
284
    /**
285
     * Collect the value of the AffiliationDescriptor property.
286
     *
287
     * @return \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null
288
     */
289
    public function getAffiliationDescriptor(): ?AffiliationDescriptor
290
    {
291
        return $this->AffiliationDescriptor;
292
    }
293
294
295
    /**
296
     * Set the value of the AffliationDescriptor property.
297
     *
298
     * @param \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor
299
     */
300
    protected function setAffiliationDescriptor(?AffiliationDescriptor $affiliationDescriptor = null): void
301
    {
302
        $this->AffiliationDescriptor = $affiliationDescriptor;
303
    }
304
305
306
    /**
307
     * Collect the value of the Organization property.
308
     *
309
     * @return \SimpleSAML\SAML2\XML\md\Organization|null
310
     */
311
    public function getOrganization(): ?Organization
312
    {
313
        return $this->Organization;
314
    }
315
316
317
    /**
318
     * Set the value of the Organization property.
319
     *
320
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
321
     */
322
    protected function setOrganization(?Organization $organization = null): void
323
    {
324
        $this->Organization = $organization;
325
    }
326
327
328
    /**
329
     * Collect the value of the ContactPerson property.
330
     *
331
     * @return \SimpleSAML\SAML2\XML\md\ContactPerson[]
332
     */
333
    public function getContactPersons(): array
334
    {
335
        return $this->ContactPerson;
336
    }
337
338
339
    /**
340
     * Set the value of the ContactPerson property.
341
     *
342
     * @param array $contactPerson
343
     * @throws \SimpleSAML\Assert\AssertionFailedException
344
     */
345
    protected function setContactPersons(array $contactPerson): void
346
    {
347
        Assert::allIsInstanceOf(
348
            $contactPerson,
349
            ContactPerson::class,
350
            'All md:ContactPerson elements must be an instance of ContactPerson.'
351
        );
352
        $this->ContactPerson = $contactPerson;
353
    }
354
355
356
    /**
357
     * Collect the value of the AdditionalMetadataLocation property.
358
     *
359
     * @return \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[]
360
     */
361
    public function getAdditionalMetadataLocations(): array
362
    {
363
        return $this->AdditionalMetadataLocation;
364
    }
365
366
367
    /**
368
     * Set the value of the AdditionalMetadataLocation property.
369
     *
370
     * @param array $additionalMetadataLocation
371
     * @throws \SimpleSAML\Assert\AssertionFailedException
372
     */
373
    protected function setAdditionalMetadataLocations(array $additionalMetadataLocation): void
374
    {
375
        Assert::allIsInstanceOf(
376
            $additionalMetadataLocation,
377
            AdditionalMetadataLocation::class,
378
            'All md:AdditionalMetadataLocation elements must be an instance of AdditionalMetadataLocation'
379
        );
380
        $this->AdditionalMetadataLocation = $additionalMetadataLocation;
381
    }
382
383
384
    /**
385
     * Convert this descriptor to an unsigned XML document.
386
     * This method does not sign the resulting XML document.
387
     *
388
     * @param \DOMElement|null $parent
389
     * @return \DOMElement The root element of the DOM tree
390
     */
391
    protected function toUnsignedXML(DOMElement $parent = null): DOMElement
392
    {
393
        $e = parent::toUnsignedXML($parent);
394
        $e->setAttribute('entityID', $this->entityID);
395
396
        foreach ($this->getAttributesNS() as $attr) {
397
            $e->setAttributeNS($attr['namespaceURI'], $attr['qualifiedName'], $attr['value']);
398
        }
399
400
        foreach ($this->RoleDescriptor as $n) {
401
            $n->toXML($e);
402
        }
403
404
        if ($this->AffiliationDescriptor !== null) {
405
            $this->AffiliationDescriptor->toXML($e);
406
        }
407
408
        if ($this->Organization !== null) {
409
            $this->Organization->toXML($e);
410
        }
411
412
        foreach ($this->ContactPerson as $cp) {
413
            $cp->toXML($e);
414
        }
415
416
        foreach ($this->AdditionalMetadataLocation as $n) {
417
            $n->toXML($e);
418
        }
419
420
        return $e;
421
    }
422
}
423