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