Passed
Push — master ( 6db269...70aff8 )
by Jaime Pérez
02:49
created

EntityDescriptor::getOrganization()   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 SAML2\XML\md;
6
7
use DOMElement;
8
use SAML2\Constants;
9
use SAML2\Utils;
10
use SAML2\XML\ds\Signature;
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
75
     *   use instead of role descriptors.
76
     * @param \SAML2\XML\md\Organization|null $organization The organization responsible for the SAML entity.
77
     * @param \SAML2\XML\md\ContactPerson[] $contacts A list of contact persons for this SAML entity.
78
     * @param \SAML2\XML\md\AdditionalMetadataLocation[] $additionalMdLocations A list of
79
     *   additional metadata 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 \InvalidArgumentException(
97
                'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'
98
            );
99
        }
100
101
        parent::__construct($id, $validUntil, $cacheDuration, $extensions);
102
103
        $this->setEntityID($entityID);
104
        $this->setRoleDescriptors($roleDescriptors);
105
        $this->setAffiliationDescriptor($affiliationDescriptor);
106
        $this->setOrganization($organization);
107
        $this->setContactPersons($contacts);
108
        $this->setAdditionalMetadataLocations($additionalMdLocations);
109
    }
110
111
112
    /**
113
     * Convert an existing XML into an EntityDescriptor object
114
     *
115
     * @param \DOMElement $xml An existing EntityDescriptor XML document.
116
     * @return \SAML2\XML\md\EntityDescriptor An object representing the given document.
117
     * @throws \InvalidArgumentException if the qualified name of the supplied element is wrong
118
     * @throws \Exception
119
     */
120
    public static function fromXML(DOMElement $xml): object
121
    {
122
        Assert::same($xml->localName, 'EntityDescriptor');
123
        Assert::same($xml->namespaceURI, EntityDescriptor::NS);
124
125
        $validUntil = self::getAttribute($xml, 'validUntil', null);
126
        $extensions = Extensions::getChildrenOfClass($xml);
127
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.');
128
129
        $signature = Signature::getChildrenOfClass($xml);
130
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
131
132
        $roleDescriptors = [];
133
        $affiliationDescriptor = null;
134
        $organization = null;
135
        $contactPersons = [];
136
        $additionalMetadataLocation = [];
137
        foreach ($xml->childNodes as $node) {
138
            if (!($node instanceof DOMElement)) {
139
                continue;
140
            } elseif ($node->namespaceURI !== Constants::NS_MD) {
141
                continue;
142
            }
143
144
            switch ($node->localName) {
145
                case 'Extensions':
146
                    continue 2;
147
                case 'IDPSSODescriptor':
148
                    $roleDescriptors[] = IDPSSODescriptor::fromXML($node);
149
                    break;
150
                case 'SPSSODescriptor':
151
                    $roleDescriptors[] = SPSSODescriptor::fromXML($node);
152
                    break;
153
                case 'AuthnAuthorityDescriptor':
154
                    $roleDescriptors[] = AuthnAuthorityDescriptor::fromXML($node);
155
                    break;
156
                case 'AttributeAuthorityDescriptor':
157
                    $roleDescriptors[] = AttributeAuthorityDescriptor::fromXML($node);
158
                    break;
159
                case 'PDPDescriptor':
160
                    $roleDescriptors[] = PDPDescriptor::fromXML($node);
161
                    break;
162
                case 'AffiliationDescriptor':
163
                    if ($affiliationDescriptor !== null) {
164
                        throw new \InvalidArgumentException('More than one AffiliationDescriptor in the entity.');
165
                    }
166
                    $affiliationDescriptor = AffiliationDescriptor::fromXML($node);
167
                    break;
168
                case 'Organization':
169
                    if ($organization !== null) {
170
                        throw new \InvalidArgumentException('More than one Organization in the entity.');
171
                    }
172
                    $organization = Organization::fromXML($node);
173
                    break;
174
                case 'ContactPerson':
175
                    $contactPersons[] = ContactPerson::fromXML($node);
176
                    break;
177
                case 'AdditionalMetadataLocation':
178
                    $additionalMetadataLocation[] = AdditionalMetadataLocation::fromXML($node);
179
                    break;
180
                default:
181
                    $roleDescriptors[] = UnknownRoleDescriptor::fromXML($node);
182
            }
183
        }
184
185
        if (empty($roleDescriptors) && is_null($affiliationDescriptor)) {
186
            throw new \InvalidArgumentException(
187
                'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.'
188
            );
189
        } elseif (!empty($roleDescriptors) && !is_null($affiliationDescriptor)) {
190
            throw new \InvalidArgumentException(
191
                'AffiliationDescriptor cannot be combined with other RoleDescriptor elements in EntityDescriptor.'
192
            );
193
        }
194
195
        $entity = new self(
196
            self::getAttribute($xml, 'entityID'),
197
            self::getAttribute($xml, 'ID', null),
198
            $validUntil !== null ? Utils::xsDateTimeToTimestamp($validUntil) : null,
199
            self::getAttribute($xml, 'cacheDuration', null),
200
            !empty($extensions) ? $extensions[0] : null,
201
            $roleDescriptors,
202
            $affiliationDescriptor,
203
            $organization,
204
            $contactPersons,
205
            $additionalMetadataLocation
206
        );
207
        if (!empty($signature)) {
208
            $entity->setSignature($signature[0]);
209
        }
210
        return $entity;
211
    }
212
213
214
    /**
215
     * Collect the value of the entityID property.
216
     *
217
     * @return string
218
     * @throws \InvalidArgumentException
219
     */
220
    public function getEntityID(): string
221
    {
222
        Assert::notEmpty($this->entityID);
223
224
        return $this->entityID;
225
    }
226
227
228
    /**
229
     * Set the value of the entityID-property
230
     * @param string $entityId
231
     * @return void
232
     */
233
    protected function setEntityID(string $entityId): void
234
    {
235
        Assert::notEmpty($entityId, 'The entityID attribute cannot be empty.');
236
        Assert::maxLength($entityId, 1024, 'The entityID attribute cannot be longer than 1024 characters.');
237
        $this->entityID = $entityId;
238
    }
239
240
241
    /**
242
     * Collect the value of the RoleDescriptor property.
243
     *
244
     * @return \SAML2\XML\md\AbstractRoleDescriptor[]
245
     */
246
    public function getRoleDescriptors(): array
247
    {
248
        return $this->RoleDescriptor;
249
    }
250
251
252
    /**
253
     * Set the value of the RoleDescriptor property.
254
     *
255
     * @param \SAML2\XML\md\AbstractRoleDescriptor[] $roleDescriptors
256
     * @return void
257
     */
258
    protected function setRoleDescriptors(array $roleDescriptors): void
259
    {
260
        Assert::allIsInstanceOf(
261
            $roleDescriptors,
262
            AbstractRoleDescriptor::class,
263
            'All role descriptors must extend AbstractRoleDescriptor.'
264
        );
265
        $this->RoleDescriptor = $roleDescriptors;
266
    }
267
268
269
    /**
270
     * Collect the value of the AffiliationDescriptor property.
271
     *
272
     * @return \SAML2\XML\md\AffiliationDescriptor|null
273
     */
274
    public function getAffiliationDescriptor(): ?AffiliationDescriptor
275
    {
276
        return $this->AffiliationDescriptor;
277
    }
278
279
280
    /**
281
     * Set the value of the AffliationDescriptor property.
282
     *
283
     * @param \SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor
284
     * @return void
285
     */
286
    protected function setAffiliationDescriptor(?AffiliationDescriptor $affiliationDescriptor = null): void
287
    {
288
        $this->AffiliationDescriptor = $affiliationDescriptor;
289
    }
290
291
292
    /**
293
     * Collect the value of the Organization property.
294
     *
295
     * @return \SAML2\XML\md\Organization|null
296
     */
297
    public function getOrganization(): ?Organization
298
    {
299
        return $this->Organization;
300
    }
301
302
303
    /**
304
     * Set the value of the Organization property.
305
     *
306
     * @param \SAML2\XML\md\Organization|null $organization
307
     * @return void
308
     */
309
    protected function setOrganization(?Organization $organization = null): void
310
    {
311
        $this->Organization = $organization;
312
    }
313
314
315
    /**
316
     * Collect the value of the ContactPerson property.
317
     *
318
     * @return \SAML2\XML\md\ContactPerson[]
319
     */
320
    public function getContactPersons(): array
321
    {
322
        return $this->ContactPerson;
323
    }
324
325
326
    /**
327
     * Set the value of the ContactPerson property.
328
     *
329
     * @param array $contactPerson
330
     * @return void
331
     */
332
    protected function setContactPersons(array $contactPerson): void
333
    {
334
        Assert::allIsInstanceOf(
335
            $contactPerson,
336
            ContactPerson::class,
337
            'All md:ContactPerson elements must be an instance of ContactPerson.'
338
        );
339
        $this->ContactPerson = $contactPerson;
340
    }
341
342
343
    /**
344
     * Collect the value of the AdditionalMetadataLocation property.
345
     *
346
     * @return \SAML2\XML\md\AdditionalMetadataLocation[]
347
     */
348
    public function getAdditionalMetadataLocations(): array
349
    {
350
        return $this->AdditionalMetadataLocation;
351
    }
352
353
354
    /**
355
     * Set the value of the AdditionalMetadataLocation property.
356
     *
357
     * @param array $additionalMetadataLocation
358
     * @return void
359
     */
360
    protected function setAdditionalMetadataLocations(array $additionalMetadataLocation): void
361
    {
362
        Assert::allIsInstanceOf(
363
            $additionalMetadataLocation,
364
            AdditionalMetadataLocation::class,
365
            'All md:AdditionalMetadataLocation elements must be an instance of AdditionalMetadataLocation'
366
        );
367
        $this->AdditionalMetadataLocation = $additionalMetadataLocation;
368
    }
369
370
371
    /**
372
     * Create this EntityDescriptor.
373
     *
374
     * @param \DOMElement|null $parent The EntitiesDescriptor we should append this EntityDescriptor to.
375
     * @return \DOMElement
376
     * @throws \Exception
377
     */
378
    public function toXML(DOMElement $parent = null): DOMElement
379
    {
380
        $e = parent::toXML($parent);
381
        $e->setAttribute('entityID', $this->entityID);
382
383
        foreach ($this->RoleDescriptor as $n) {
384
            $n->toXML($e);
385
        }
386
387
        if ($this->AffiliationDescriptor !== null) {
388
            $this->AffiliationDescriptor->toXML($e);
389
        }
390
391
        if ($this->Organization !== null) {
392
            $this->Organization->toXML($e);
393
        }
394
395
        foreach ($this->ContactPerson as $cp) {
396
            $cp->toXML($e);
397
        }
398
399
        foreach ($this->AdditionalMetadataLocation as $n) {
400
            $n->toXML($e);
401
        }
402
403
        return $this->signElement($e);
404
    }
405
}
406