Passed
Pull Request — master (#317)
by Tim
12:30
created

EntityDescriptor::__construct()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 42
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

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