Passed
Pull Request — master (#374)
by Tim
02:36
created

SPSSODescriptor::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 61
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 31
nc 1
nop 17
dl 0
loc 61
rs 9.424
c 0
b 0
f 0

How to fix   Long Method    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Type\AnyURIListValue;
10
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
11
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
12
use SimpleSAML\XML\Constants as C;
13
use SimpleSAML\XML\SchemaValidatableElementInterface;
14
use SimpleSAML\XML\SchemaValidatableElementTrait;
15
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
16
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
17
use SimpleSAML\XMLSchema\Type\BooleanValue;
18
use SimpleSAML\XMLSchema\Type\DurationValue;
19
use SimpleSAML\XMLSchema\Type\IDValue;
20
use SimpleSAML\XMLSecurity\XML\ds\Signature;
21
22
use function array_filter;
23
use function var_export;
24
25
/**
26
 * Class representing SAML 2 SPSSODescriptor.
27
 *
28
 * @package simplesamlphp/saml2
29
 */
30
final class SPSSODescriptor extends AbstractSSODescriptor implements SchemaValidatableElementInterface
31
{
32
    use SchemaValidatableElementTrait;
33
34
35
    /**
36
     * SPSSODescriptor constructor.
37
     *
38
     * @param array<\SimpleSAML\SAML2\XML\md\AssertionConsumerService> $assertionConsumerService
39
     * @param \SimpleSAML\SAML2\Type\AnyURIListValue $protocolSupportEnumeration
40
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $authnRequestsSigned
41
     * @param \SimpleSAML\XMLSchema\Type\BooleanValue|null $wantAssertionsSigned
42
     * @param array<\SimpleSAML\SAML2\XML\md\AttributeConsumingService> $attributeConsumingService
43
     * @param \SimpleSAML\XMLSchema\Type\IDValue|null $ID
44
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $validUntil
45
     * @param \SimpleSAML\XMLSchema\Type\DurationValue|null $cacheDuration
46
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
47
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $errorURL
48
     * @param array<\SimpleSAML\SAML2\XML\md\KeyDescriptor> $keyDescriptors
49
     * @param \SimpleSAML\SAML2\XML\md\Organization|null $organization
50
     * @param array<\SimpleSAML\SAML2\XML\md\ContactPerson> $contacts
51
     * @param array<\SimpleSAML\SAML2\XML\md\ArtifactResolutionService> $artifactResolutionService
52
     * @param array<\SimpleSAML\SAML2\XML\md\SingleLogoutService> $singleLogoutService
53
     * @param array<\SimpleSAML\SAML2\XML\md\ManageNameIDService> $manageNameIDService
54
     * @param array<\SimpleSAML\SAML2\XML\md\NameIDFormat> $nameIDFormat
55
     */
56
    public function __construct(
57
        protected array $assertionConsumerService,
58
        AnyURIListValue $protocolSupportEnumeration,
59
        protected ?BooleanValue $authnRequestsSigned = null,
60
        protected ?BooleanValue $wantAssertionsSigned = null,
61
        protected array $attributeConsumingService = [],
62
        ?IDValue $ID = null,
63
        ?SAMLDateTimeValue $validUntil = null,
64
        ?DurationValue $cacheDuration = null,
65
        ?Extensions $extensions = null,
66
        ?SAMLAnyURIValue $errorURL = null,
67
        array $keyDescriptors = [],
68
        ?Organization $organization = null,
69
        array $contacts = [],
70
        array $artifactResolutionService = [],
71
        array $singleLogoutService = [],
72
        array $manageNameIDService = [],
73
        array $nameIDFormat = [],
74
    ) {
75
        parent::__construct(
76
            $protocolSupportEnumeration,
77
            $ID,
78
            $validUntil,
79
            $cacheDuration,
80
            $extensions,
81
            $errorURL,
82
            $keyDescriptors,
83
            $organization,
84
            $contacts,
85
            $artifactResolutionService,
86
            $singleLogoutService,
87
            $manageNameIDService,
88
            $nameIDFormat,
89
        );
90
91
        Assert::maxCount($assertionConsumerService, C::UNBOUNDED_LIMIT);
92
        Assert::minCount($assertionConsumerService, 1, 'At least one AssertionConsumerService must be specified.');
93
        Assert::allIsInstanceOf(
94
            $assertionConsumerService,
95
            AssertionConsumerService::class,
96
            'All md:AssertionConsumerService endpoints must be an instance of AssertionConsumerService.',
97
        );
98
        Assert::maxCount($attributeConsumingService, C::UNBOUNDED_LIMIT);
99
        Assert::allIsInstanceOf(
100
            $attributeConsumingService,
101
            AttributeConsumingService::class,
102
            'All md:AttributeConsumingService endpoints must be an instance of AttributeConsumingService.',
103
        );
104
105
        /**
106
         * E87:  test that only one ACS is marked as default
107
         */
108
        Assert::maxCount(
109
            array_filter(
110
                $attributeConsumingService,
111
                function (AttributeConsumingService $acs) {
112
                    return $acs->getIsDefault()?->toBoolean() === true;
113
                },
114
            ),
115
            1,
116
            'At most one <AttributeConsumingService> element can have the attribute isDefault set to true.',
117
        );
118
    }
119
120
121
    /**
122
     * Collect the value of the AuthnRequestsSigned-property
123
     *
124
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
125
     */
126
    public function getAuthnRequestsSigned(): ?BooleanValue
127
    {
128
        return $this->authnRequestsSigned;
129
    }
130
131
132
    /**
133
     * Collect the value of the WantAssertionsSigned-property
134
     *
135
     * @return \SimpleSAML\XMLSchema\Type\BooleanValue|null
136
     */
137
    public function getWantAssertionsSigned(): ?BooleanValue
138
    {
139
        return $this->wantAssertionsSigned;
140
    }
141
142
143
    /**
144
     * Collect the value of the AssertionConsumerService-property
145
     *
146
     * @return \SimpleSAML\SAML2\XML\md\AssertionConsumerService[]
147
     */
148
    public function getAssertionConsumerService(): array
149
    {
150
        return $this->assertionConsumerService;
151
    }
152
153
154
    /**
155
     * Collect the value of the AttributeConsumingService-property
156
     *
157
     * @return \SimpleSAML\SAML2\XML\md\AttributeConsumingService[]
158
     */
159
    public function getAttributeConsumingService(): array
160
    {
161
        return $this->attributeConsumingService;
162
    }
163
164
165
    /**
166
     * Convert XML into a SPSSODescriptor
167
     *
168
     * @param \DOMElement $xml The XML element we should load
169
     * @return static
170
     *
171
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
172
     *   if the qualified name of the supplied element is wrong
173
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
174
     *   if the supplied element is missing one of the mandatory attributes
175
     * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException
176
     *   if too many child-elements of a type are specified
177
     */
178
    public static function fromXML(DOMElement $xml): static
179
    {
180
        Assert::same($xml->localName, 'SPSSODescriptor', InvalidDOMElementException::class);
181
        Assert::same($xml->namespaceURI, SPSSODescriptor::NS, InvalidDOMElementException::class);
182
183
        $orgs = Organization::getChildrenOfClass($xml);
184
        Assert::maxCount(
185
            $orgs,
186
            1,
187
            'More than one Organization found in this descriptor',
188
            TooManyElementsException::class,
189
        );
190
191
        $extensions = Extensions::getChildrenOfClass($xml);
192
        Assert::maxCount(
193
            $extensions,
194
            1,
195
            'Only one md:Extensions element is allowed.',
196
            TooManyElementsException::class,
197
        );
198
199
        $signature = Signature::getChildrenOfClass($xml);
200
        Assert::maxCount(
201
            $signature,
202
            1,
203
            'Only one ds:Signature element is allowed.',
204
            TooManyElementsException::class,
205
        );
206
207
        $spssod = new static(
208
            AssertionConsumerService::getChildrenOfClass($xml),
209
            self::getAttribute($xml, 'protocolSupportEnumeration', AnyURIListValue::class),
210
            self::getOptionalAttribute($xml, 'AuthnRequestsSigned', BooleanValue::class, null),
211
            self::getOptionalAttribute($xml, 'WantAssertionsSigned', BooleanValue::class, null),
212
            AttributeConsumingService::getChildrenOfClass($xml),
213
            self::getOptionalAttribute($xml, 'ID', IDValue::class, null),
214
            self::getOptionalAttribute($xml, 'validUntil', SAMLDateTimeValue::class, null),
215
            self::getOptionalAttribute($xml, 'cacheDuration', DurationValue::class, null),
216
            !empty($extensions) ? $extensions[0] : null,
217
            self::getOptionalAttribute($xml, 'errorURL', SAMLAnyURIValue::class, null),
218
            KeyDescriptor::getChildrenOfClass($xml),
219
            !empty($orgs) ? $orgs[0] : null,
220
            ContactPerson::getChildrenOfClass($xml),
221
            ArtifactResolutionService::getChildrenOfClass($xml),
222
            SingleLogoutService::getChildrenOfClass($xml),
223
            ManageNameIDService::getChildrenOfClass($xml),
224
            NameIDFormat::getChildrenOfClass($xml),
225
        );
226
227
        if (!empty($signature)) {
228
            $spssod->setSignature($signature[0]);
229
            $spssod->setXML($xml);
230
        }
231
232
        return $spssod;
233
    }
234
235
236
    /**
237
     * Convert this assertion to an unsigned XML document.
238
     * This method does not sign the resulting XML document.
239
     *
240
     * @return \DOMElement The root element of the DOM tree
241
     */
242
    public function toUnsignedXML(?DOMElement $parent = null): DOMElement
243
    {
244
        $e = parent::toUnsignedXML($parent);
245
246
        if ($this->getAuthnRequestsSigned() !== null) {
247
            $e->setAttribute('AuthnRequestsSigned', var_export($this->getAuthnRequestsSigned()->toBoolean(), true));
248
        }
249
250
        if ($this->getWantAssertionsSigned() !== null) {
251
            $e->setAttribute('WantAssertionsSigned', var_export($this->getWantAssertionsSigned()->toBoolean(), true));
252
        }
253
254
        foreach ($this->getAssertionConsumerService() as $ep) {
255
            $ep->toXML($e);
256
        }
257
258
        foreach ($this->getAttributeConsumingService() as $acs) {
259
            $acs->toXML($e);
260
        }
261
262
        return $e;
263
    }
264
}
265