EntityDescriptor::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 40
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 21
nc 1
nop 11
dl 0
loc 40
rs 9.584
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 SimpleSAML\SAML2\Assert\Assert;
9
use SimpleSAML\SAML2\Constants as C;
10
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
11
use SimpleSAML\SAML2\Type\EntityIDValue;
12
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
13
use SimpleSAML\XML\ExtendableAttributesTrait;
14
use SimpleSAML\XML\SchemaValidatableElementInterface;
15
use SimpleSAML\XML\SchemaValidatableElementTrait;
16
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
17
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
18
use SimpleSAML\XMLSchema\Type\DurationValue;
19
use SimpleSAML\XMLSchema\Type\IDValue;
20
use SimpleSAML\XMLSchema\XML\Constants\NS;
21
use SimpleSAML\XMLSecurity\XML\ds\Signature;
22
23
use function is_null;
24
25
/**
26
 * Class representing SAML 2 EntityDescriptor element.
27
 *
28
 * @package simplesamlphp/saml2
29
 */
30
final class EntityDescriptor extends AbstractMetadataDocument implements SchemaValidatableElementInterface
31
{
32
    use ExtendableAttributesTrait;
33
    use SchemaValidatableElementTrait;
34
35
36
    /** The namespace-attribute for the xs:anyAttribute element */
37
    public const XS_ANY_ATTR_NAMESPACE = NS::OTHER;
38
39
40
    /**
41
     * Initialize an EntitiyDescriptor.
42
     *
43
     * @param \SimpleSAML\SAML2\Type\EntityIDValue $entityId The entityID of the entity described by this descriptor.
44
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $id The ID for this document. Defaults to null.
45
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil Unix time of validify for this document.
46
     *   Defaults to null.
47
     * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration Maximum time this document can be cached.
48
     *   Defaults to null.
49
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions An array of extensions.
50
     * @param \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType[] $roleDescriptor An array of role descriptors.
51
     * @param \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null $affiliationDescriptor An affiliation descriptor to
52
     *   use instead of role descriptors.
53
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization The organization responsible for the SAML entity.
54
     * @param \SimpleSAML\SAML2\XML\md\ContactPerson[] $contactPerson A list of contact persons for this SAML entity.
55
     * @param \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[] $additionalMetadataLocation A list of
56
     *   additional metadata locations.
57
     * @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...
58
     *
59
     * @throws \Exception
60
     */
61
    public function __construct(
62
        protected EntityIDValue $entityId,
63
        ?IDValue $id = null,
64
        ?SAMLDateTimeValue $validUntil = null,
65
        ?DurationValue $cacheDuration = null,
66
        ?Extensions $extensions = null,
67
        protected array $roleDescriptor = [],
68
        protected ?AffiliationDescriptor $affiliationDescriptor = null,
69
        protected ?Organization $organization = null,
70
        protected array $contactPerson = [],
71
        protected array $additionalMetadataLocation = [],
72
        array $namespacedAttribute = [],
73
    ) {
74
        Assert::false(
75
            (empty($roleDescriptor) && $affiliationDescriptor === null),
76
            'Must have either one of the RoleDescriptors or an AffiliationDescriptor in EntityDescriptor.',
77
            ProtocolViolationException::class,
78
        );
79
        Assert::maxCount($roleDescriptor, C::UNBOUNDED_LIMIT);
80
        Assert::allIsInstanceOf(
81
            $roleDescriptor,
82
            AbstractRoleDescriptorType::class,
83
            'All role descriptors must extend AbstractRoleDescriptor.',
84
        );
85
        Assert::maxCount($contactPerson, C::UNBOUNDED_LIMIT);
86
        Assert::allIsInstanceOf(
87
            $contactPerson,
88
            ContactPerson::class,
89
            'All md:ContactPerson elements must be an instance of ContactPerson.',
90
        );
91
        Assert::maxCount($additionalMetadataLocation, C::UNBOUNDED_LIMIT);
92
        Assert::allIsInstanceOf(
93
            $additionalMetadataLocation,
94
            AdditionalMetadataLocation::class,
95
            'All md:AdditionalMetadataLocation elements must be an instance of AdditionalMetadataLocation',
96
        );
97
98
        parent::__construct($id, $validUntil, $cacheDuration, $extensions);
99
100
        $this->setAttributesNS($namespacedAttribute);
101
    }
102
103
104
    /**
105
     * Convert an existing XML into an EntityDescriptor object
106
     *
107
     * @param \DOMElement $xml An existing EntityDescriptor XML document.
108
     * @return static
109
     *
110
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
111
     *   if the qualified name of the supplied element is wrong
112
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
113
     *   if the supplied element is missing one of the mandatory attributes
114
     * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException
115
     *   if too many child-elements of a type are specified
116
     */
117
    public static function fromXML(DOMElement $xml): static
118
    {
119
        Assert::same($xml->localName, 'EntityDescriptor', InvalidDOMElementException::class);
120
        Assert::same($xml->namespaceURI, EntityDescriptor::NS, InvalidDOMElementException::class);
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
        $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
            self::getAttribute($xml, 'entityID', EntityIDValue::class),
195
            self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
196
            self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
197
            self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, 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 \SimpleSAML\SAML2\Type\EntityIDValue
220
     */
221
    public function getEntityId(): EntityIDValue
222
    {
223
        return $this->entityId;
224
    }
225
226
227
    /**
228
     * Collect the value of the RoleDescriptor property.
229
     *
230
     * @return \SimpleSAML\SAML2\XML\md\AbstractRoleDescriptorType[]
231
     */
232
    public function getRoleDescriptor(): array
233
    {
234
        return $this->roleDescriptor;
235
    }
236
237
238
    /**
239
     * Collect the value of the AffiliationDescriptor property.
240
     *
241
     * @return \SimpleSAML\SAML2\XML\md\AffiliationDescriptor|null
242
     */
243
    public function getAffiliationDescriptor(): ?AffiliationDescriptor
244
    {
245
        return $this->affiliationDescriptor;
246
    }
247
248
249
    /**
250
     * Collect the value of the Organization property.
251
     *
252
     * @return \SimpleSAML\SAML2\XML\md\Organization|null
253
     */
254
    public function getOrganization(): ?Organization
255
    {
256
        return $this->organization;
257
    }
258
259
260
    /**
261
     * Collect the value of the ContactPerson property.
262
     *
263
     * @return \SimpleSAML\SAML2\XML\md\ContactPerson[]
264
     */
265
    public function getContactPerson(): array
266
    {
267
        return $this->contactPerson;
268
    }
269
270
271
    /**
272
     * Collect the value of the AdditionalMetadataLocation property.
273
     *
274
     * @return \SimpleSAML\SAML2\XML\md\AdditionalMetadataLocation[]
275
     */
276
    public function getAdditionalMetadataLocation(): array
277
    {
278
        return $this->additionalMetadataLocation;
279
    }
280
281
282
    /**
283
     * Convert this assertion to an unsigned XML document.
284
     * This method does not sign the resulting XML document.
285
     *
286
     * @return \DOMElement The root element of the DOM tree
287
     */
288
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
289
    {
290
        $e = parent::toUnsignedXML($parent);
291
        $e->setAttribute('entityID', $this->getEntityId()->getValue());
292
293
        foreach ($this->getAttributesNS() as $attr) {
294
            $attr->toXML($e);
295
        }
296
297
        foreach ($this->getRoleDescriptor() as $n) {
298
            $n->toXML($e);
299
        }
300
301
        $this->getAffiliationDescriptor()?->toXML($e);
302
        $this->getOrganization()?->toXML($e);
303
304
        foreach ($this->getContactPerson() as $cp) {
305
            $cp->toXML($e);
306
        }
307
308
        foreach ($this->getAdditionalMetadataLocation() as $n) {
309
            $n->toXML($e);
310
        }
311
312
        return $e;
313
    }
314
}
315