Completed
Branch rewrite-api-md (eb38e5)
by Tim
03:57
created

EntityDescriptor::__construct()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 31
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 13
nc 2
nop 10
dl 0
loc 31
rs 9.8333
c 1
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 SAML2\XML\md;
6
7
use DOMElement;
8
use SAML2\Constants;
9
use SAML2\DOMDocumentFactory;
10
use SAML2\Utils;
11
use Webmozart\Assert\Assert;
12
13
/**
14
 * Class representing SAML 2 EntityDescriptor element.
15
 *
16
 * @package simplesamlphp/saml2
17
 */
18
final class EntityDescriptor extends AbstractMetadataDocument
19
{
20
    /**
21
     * The entityID this EntityDescriptor represents.
22
     *
23
     * @var string
24
     */
25
    protected $entityID;
26
27
    /**
28
     * Array with all roles for this entity.
29
     *
30
     * Array of \SAML2\XML\md\RoleDescriptor objects (and subclasses of RoleDescriptor).
31
     *
32
     * @var \SAML2\XML\md\AbstractRoleDescriptor[]
33
     */
34
    protected $RoleDescriptor = [];
35
36
    /**
37
     * AffiliationDescriptor of this entity.
38
     *
39
     * @var \SAML2\XML\md\AffiliationDescriptor|null
40
     */
41
    protected $AffiliationDescriptor = null;
42
43
    /**
44
     * Organization of this entity.
45
     *
46
     * @var \SAML2\XML\md\Organization|null
47
     */
48
    protected $Organization = null;
49
50
    /**
51
     * ContactPerson elements for this entity.
52
     *
53
     * @var \SAML2\XML\md\ContactPerson[]
54
     */
55
    protected $ContactPerson = [];
56
57
    /**
58
     * AdditionalMetadataLocation elements for this entity.
59
     *
60
     * @var \SAML2\XML\md\AdditionalMetadataLocation[]
61
     */
62
    protected $AdditionalMetadataLocation = [];
63
64
65
    /**
66
     * Initialize an EntitiyDescriptor.
67
     *
68
     * @param string $entityID The entityID of the entity described by this descriptor.
69
     * @param string|null $id The ID for this document. Defaults to null.
70
     * @param int|null $validUntil Unix time of validify for this document. Defaults to null.
71
     * @param string|null $cacheDuration Maximum time this document can be cached. Defaults to null.
72
     * @param \SAML2\XML\md\Extensions|null $extensions An array of extensions.
73
     * @param \SAML2\XML\md\AbstractRoleDescriptor[]|null $roleDescriptors An array of role descriptors.
74
     * @param \SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor An affiliation descriptor to use instead
75
     * of role descriptors.
76
     * @param \SAML2\XML\md\Organization|null $organization The organization responsible for the SAML entity.
77
     * @param \SAML2\XML\md\ContactPerson[]|null $contacts A list of contact persons for this SAML entity.
78
     * @param \SAML2\XML\md\AdditionalMetadataLocation[]|null $additionalMdLocations A list of additional metadata
79
     * locations.
80
     *
81
     * @throws \Exception
82
     */
83
    public function __construct(
84
        string $entityID,
85
        ?string $id = null,
86
        ?int $validUntil = null,
87
        ?string $cacheDuration = null,
88
        Extensions $extensions = null,
89
        array $roleDescriptors = [],
90
        ?AffiliationDescriptor $affiliationDescriptor = null,
91
        ?Organization $organization = null,
92
        array $contacts = [],
93
        array $additionalMdLocations = []
94
    ) {
95
        if (empty($roleDescriptors) && $affiliationDescriptor === null) {
96
            throw new \Exception(
97
                'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'
98
            );
99
        }
100
101
        Assert::false(
102
            is_null($validUntil) && is_null($cacheDuration),
103
            'You need either validUntil or cacheDuration set'
104
        );
105
106
        parent::__construct($id, $validUntil, $cacheDuration, $extensions);
107
108
        $this->entityID = $entityID;
109
        $this->setRoleDescriptor($roleDescriptors);
110
        $this->AffiliationDescriptor = $affiliationDescriptor;
111
        $this->Organization = $organization;
112
        $this->setContactPerson($contacts);
113
        $this->setAdditionalMetadataLocation($additionalMdLocations);
114
    }
115
116
117
    /**
118
     * Convert an existing XML into an EntityDescriptor object
119
     *
120
     * @param \DOMElement $xml An existing EntityDescriptor XML document.
121
     *
122
     * @return \SAML2\XML\md\EntityDescriptor An object representing the given document.
123
     * @throws \Exception If an error occurs while processing the XML document.
124
     */
125
    public static function fromXML(DOMElement $xml): object
126
    {
127
        $validUntil = self::getAttribute($xml, 'validUntil', null);
128
        $extensions = Extensions::getChildrenOfClass($xml);
129
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.');
130
131
        $roleDescriptors = [];
132
        $affiliationDescriptor = null;
133
        $organization = null;
134
        $contactPersons = [];
135
        $additionalMetadataLocation = [];
136
        foreach ($xml->childNodes as $node) {
137
            if (!($node instanceof DOMElement)) {
138
                continue;
139
            }
140
141
            if ($node->namespaceURI !== Constants::NS_MD) {
142
                continue;
143
            }
144
145
            switch ($node->localName) {
146
                case 'IDPSSODescriptor':
147
                    $roleDescriptors[] = IDPSSODescriptor::fromXML($node);
148
                    break;
149
                case 'SPSSODescriptor':
150
                    $roleDescriptors[] = new SPSSODescriptor($node);
151
                    break;
152
                case 'AuthnAuthorityDescriptor':
153
                    $roleDescriptors[] = AuthnAuthorityDescriptor::fromXML($node);
154
                    break;
155
                case 'AttributeAuthorityDescriptor':
156
                    $roleDescriptors[] = AttributeAuthorityDescriptor::fromXML($node);
157
                    break;
158
                case 'PDPDescriptor':
159
                    $roleDescriptors[] = new PDPDescriptor($node);
0 ignored issues
show
Bug introduced by
The call to SAML2\XML\md\PDPDescriptor::__construct() has too few arguments starting with protocolSupportEnumeration. ( Ignorable by Annotation )

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

159
                    $roleDescriptors[] = /** @scrutinizer ignore-call */ new PDPDescriptor($node);

This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug introduced by
$node of type DOMElement is incompatible with the type array expected by parameter $authServiceEndpoints of SAML2\XML\md\PDPDescriptor::__construct(). ( Ignorable by Annotation )

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

159
                    $roleDescriptors[] = new PDPDescriptor(/** @scrutinizer ignore-type */ $node);
Loading history...
160
                    break;
161
                case 'AffiliationDescriptor':
162
                    if ($affiliationDescriptor !== null) {
163
                        throw new \Exception('More than one AffiliationDescriptor in the entity.');
164
                    }
165
                    $affiliationDescriptor = AffiliationDescriptor::fromXML($node);
166
                    break;
167
                case 'Organization':
168
                    if ($organization !== null) {
169
                        throw new \Exception('More than one Organization in the entity.');
170
                    }
171
                    $organization = Organization::fromXML($node);
172
                    break;
173
                case 'ContactPerson':
174
                    $contactPersons[] = ContactPerson::fromXML($node);
175
                    break;
176
                case 'AdditionalMetadataLocation':
177
                    $additionalMetadataLocation[] = AdditionalMetadataLocation::fromXML($node);
178
                    break;
179
                default:
180
                    $roleDescriptors[] = UnknownRoleDescriptor::fromXML($node);
181
            }
182
        }
183
184
        if (empty($roleDescriptors) && is_null($affiliationDescriptor)) {
185
            throw new \Exception(
186
                'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'
187
            );
188
        } elseif (!empty($roleDescriptors) && !is_null($affiliationDescriptor)) {
189
            throw new \Exception(
190
                'AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.'
191
            );
192
        }
193
194
        return new self(
195
            self::getAttribute($xml, 'entityID'),
196
            self::getAttribute($xml, 'ID', null),
197
            $validUntil !== null ? Utils::xsDateTimeToTimestamp($validUntil) : null,
198
            self::getAttribute($xml, 'cacheDuration', null),
199
            !empty($extensions) ? $extensions[0] : null,
200
            $roleDescriptors,
201
            $affiliationDescriptor,
202
            $organization,
203
            $contactPersons,
204
            $additionalMetadataLocation
205
        );
206
    }
207
208
209
    /**
210
     * Collect the value of the entityID property.
211
     *
212
     * @return string
213
     *
214
     * @throws \InvalidArgumentException if assertions are false
215
     */
216
    public function getEntityID(): string
217
    {
218
        Assert::notEmpty($this->entityID);
219
220
        return $this->entityID;
221
    }
222
223
224
    /**
225
     * Set the value of the entityID-property
226
     * @param string $entityId
227
     * @return void
228
     */
229
    protected function setEntityID(string $entityId): void
230
    {
231
        $this->entityID = $entityId;
232
    }
233
234
235
    /**
236
     * Collect the value of the RoleDescriptor property.
237
     *
238
     * @return \SAML2\XML\md\AbstractRoleDescriptor[]
239
     */
240
    public function getRoleDescriptor(): array
241
    {
242
        return $this->RoleDescriptor;
243
    }
244
245
246
    /**
247
     * Set the value of the RoleDescriptor property.
248
     *
249
     * @param \SAML2\XML\md\AbstractRoleDescriptor[] $roleDescriptor
250
     *
251
     * @return void
252
     */
253
    protected function setRoleDescriptor(array $roleDescriptor): void
254
    {
255
        $this->RoleDescriptor = $roleDescriptor;
256
    }
257
258
259
    /**
260
     * Collect the value of the AffiliationDescriptor property.
261
     *
262
     * @return \SAML2\XML\md\AffiliationDescriptor|null
263
     */
264
    public function getAffiliationDescriptor(): ?AffiliationDescriptor
265
    {
266
        return $this->AffiliationDescriptor;
267
    }
268
269
270
    /**
271
     * Set the value of the AffliationDescriptor property.
272
     *
273
     * @param \SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor
274
     * @return void
275
     */
276
    protected function setAffiliationDescriptor(AffiliationDescriptor $affiliationDescriptor = null): void
277
    {
278
        $this->AffiliationDescriptor = $affiliationDescriptor;
279
    }
280
281
282
    /**
283
     * Collect the value of the Organization property.
284
     *
285
     * @return \SAML2\XML\md\Organization|null
286
     */
287
    public function getOrganization(): ?Organization
288
    {
289
        return $this->Organization;
290
    }
291
292
293
    /**
294
     * Set the value of the Organization property.
295
     *
296
     * @param \SAML2\XML\md\Organization|null $organization
297
     * @return void
298
     */
299
    protected function setOrganization(Organization $organization = null): void
300
    {
301
        $this->Organization = $organization;
302
    }
303
304
305
    /**
306
     * Collect the value of the ContactPerson property.
307
     *
308
     * @return \SAML2\XML\md\ContactPerson[]
309
     */
310
    public function getContactPerson(): array
311
    {
312
        return $this->ContactPerson;
313
    }
314
315
316
    /**
317
     * Set the value of the ContactPerson property.
318
     *
319
     * @param array $contactPerson
320
     * @return void
321
     */
322
    protected function setContactPerson(array $contactPerson): void
323
    {
324
        $this->ContactPerson = $contactPerson;
325
    }
326
327
328
    /**
329
     * Collect the value of the AdditionalMetadataLocation property.
330
     *
331
     * @return \SAML2\XML\md\AdditionalMetadataLocation[]
332
     */
333
    public function getAdditionalMetadataLocation(): array
334
    {
335
        return $this->AdditionalMetadataLocation;
336
    }
337
338
339
    /**
340
     * Set the value of the AdditionalMetadataLocation property.
341
     *
342
     * @param array $additionalMetadataLocation
343
     * @return void
344
     */
345
    protected function setAdditionalMetadataLocation(array $additionalMetadataLocation): void
346
    {
347
        $this->AdditionalMetadataLocation = $additionalMetadataLocation;
348
    }
349
350
351
    /**
352
     * Create this EntityDescriptor.
353
     *
354
     * @param \DOMElement|null $parent The EntitiesDescriptor we should append this EntityDescriptor to.
355
     * @return \DOMElement
356
     *
357
     * @throws \InvalidArgumentException if assertions are false
358
     */
359
    public function toXML(DOMElement $parent = null): DOMElement
360
    {
361
        Assert::notEmpty($this->entityID, 'Cannot convert EntityDescriptor to XML without an EntityID set.');
362
363
        if ($parent === null) {
364
            $doc = DOMDocumentFactory::create();
365
            $e = $doc->createElementNS(Constants::NS_MD, 'md:EntityDescriptor');
366
            $doc->appendChild($e);
367
        } else {
368
            $e = $parent->ownerDocument->createElementNS(Constants::NS_MD, 'md:EntityDescriptor');
369
            $parent->appendChild($e);
370
        }
371
372
        $e->setAttribute('entityID', $this->entityID);
373
374
        if ($this->ID !== null) {
375
            $e->setAttribute('ID', $this->ID);
376
        }
377
378
        if ($this->validUntil !== null) {
379
            $e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil));
380
        }
381
382
        if ($this->cacheDuration !== null) {
383
            $e->setAttribute('cacheDuration', $this->cacheDuration);
384
        }
385
386
        if (!empty($this->Extensions)) {
387
            $this->Extensions->toXML($e);
388
        }
389
390
        foreach ($this->RoleDescriptor as $n) {
391
            $n->toXML($e);
392
        }
393
394
        if ($this->AffiliationDescriptor !== null) {
395
            $this->AffiliationDescriptor->toXML($e);
396
        }
397
398
        if ($this->Organization !== null) {
399
            $this->Organization->toXML($e);
400
        }
401
402
        foreach ($this->ContactPerson as $cp) {
403
            $cp->toXML($e);
404
        }
405
406
        foreach ($this->AdditionalMetadataLocation as $n) {
407
            $n->toXML($e);
408
        }
409
410
        /** @var \DOMElement $child */
411
        $child = $e->firstChild;
412
        $this->signElement($e, $child);
413
414
        return $e;
415
    }
416
}
417