Completed
Branch rewrite-api-md (eb38e5)
by Tim
03:57
created

IDPSSODescriptor::addAttribute()   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 1
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\saml\Attribute;
11
use Webmozart\Assert\Assert;
12
13
/**
14
 * Class representing SAML 2 IDPSSODescriptor.
15
 *
16
 * @package simplesamlphp/saml2
17
 */
18
final class IDPSSODescriptor extends AbstractSSODescriptor
19
{
20
    /**
21
     * Whether AuthnRequests sent to this IdP should be signed.
22
     *
23
     * @var bool|null
24
     */
25
    protected $wantAuthnRequestsSigned = null;
26
27
    /**
28
     * List of SingleSignOnService endpoints.
29
     *
30
     * @var \SAML2\XML\md\SingleSignOnService[]
31
     */
32
    protected $ssoServiceEndpoints = [];
33
34
    /**
35
     * List of NameIDMappingService endpoints.
36
     *
37
     * @var \SAML2\XML\md\NameIDMappingService[]
38
     */
39
    protected $nameIDMappingServiceEndpoints = [];
40
41
    /**
42
     * List of AssertionIDRequestService endpoints.
43
     *
44
     * @var \SAML2\XML\md\AssertionIDRequestService[]
45
     */
46
    protected $assertionIDRequestServiceEndpoints = [];
47
48
    /**
49
     * List of supported attribute profiles.
50
     *
51
     * @var string[]
52
     */
53
    protected $attributeProfiles = [];
54
55
    /**
56
     * List of supported attributes.
57
     *
58
     * @var \SAML2\XML\saml\Attribute[]
59
     */
60
    protected $attributes = [];
61
62
63
    /**
64
     * IDPSSODescriptor constructor.
65
     *
66
     * @param \SAML2\XML\md\SingleSignOnService[] $ssoServiceEndpoints
67
     * @param string[] $protocolSupportEnumeration
68
     * @param bool|null $wantAuthnRequestsSigned
69
     * @param \SAML2\XML\md\NameIDMappingService[]|null $nameIDMappingServiceEndpoints
70
     * @param \SAML2\XML\md\AssertionIDRequestService[]|null $assertionIDRequestServiceEndpoints
71
     * @param string[]|null $attributeProfiles
72
     * @param \SAML2\XML\saml\Attribute[]|null $attributes
73
     * @param string|null $ID
74
     * @param int|null $validUntil
75
     * @param string|null $cacheDuration
76
     * @param \SAML2\XML\md\Extensions|null $extensions
77
     * @param string|null $errorURL
78
     * @param \SAML2\XML\md\KeyDescriptor[]|null $keyDescriptors
79
     * @param \SAML2\XML\md\Organization|null $organization
80
     * @param \SAML2\XML\md\ContactPerson[]|null $contacts
81
     * @param \SAML2\XML\md\ArtifactResolutionService[]|null $artifactResolutionService
82
     * @param \SAML2\XML\md\SingleLogoutService[]|null $singleLogoutService
83
     * @param \SAML2\XML\md\ManageNameIDService[]|null $manageNameIDService
84
     * @param string[]|null $nameIDFormat
85
     */
86
    public function __construct(
87
        array $ssoServiceEndpoints,
88
        array $protocolSupportEnumeration,
89
        bool $wantAuthnRequestsSigned = null,
90
        ?array $nameIDMappingServiceEndpoints = null,
91
        ?array $assertionIDRequestServiceEndpoints = null,
92
        ?array $attributeProfiles = null,
93
        ?array $attributes = null,
94
        ?string $ID = null,
95
        ?int $validUntil = null,
96
        ?string $cacheDuration = null,
97
        ?Extensions $extensions = null,
98
        ?string $errorURL = null,
99
        ?array $keyDescriptors = [],
100
        ?Organization $organization = null,
101
        ?array $contacts = [],
102
        ?array $artifactResolutionService = [],
103
        ?array $singleLogoutService = [],
104
        ?array $manageNameIDService = [],
105
        ?array $nameIDFormat = []
106
    ) {
107
        parent::__construct(
108
            $protocolSupportEnumeration,
109
            $ID,
110
            $validUntil,
111
            $cacheDuration,
112
            $extensions,
113
            $errorURL,
114
            $keyDescriptors,
115
            $organization,
116
            $contacts,
117
            $artifactResolutionService,
118
            $singleLogoutService,
119
            $manageNameIDService,
120
            $nameIDFormat
121
        );
122
        $this->setSingleSignOnServices($ssoServiceEndpoints);
123
        $this->setWantAuthnRequestsSigned($wantAuthnRequestsSigned);
124
        $this->setNameIDMappingServices($nameIDMappingServiceEndpoints);
0 ignored issues
show
Bug introduced by
It seems like $nameIDMappingServiceEndpoints can also be of type null; however, parameter $nameIDMappingServices of SAML2\XML\md\IDPSSODescr...NameIDMappingServices() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

124
        $this->setNameIDMappingServices(/** @scrutinizer ignore-type */ $nameIDMappingServiceEndpoints);
Loading history...
125
        $this->setAssertionIDRequestService($assertionIDRequestServiceEndpoints);
0 ignored issues
show
Bug introduced by
It seems like $assertionIDRequestServiceEndpoints can also be of type null; however, parameter $assertionIDRequestServices of SAML2\XML\md\IDPSSODescr...rtionIDRequestService() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

125
        $this->setAssertionIDRequestService(/** @scrutinizer ignore-type */ $assertionIDRequestServiceEndpoints);
Loading history...
126
        $this->setAttributeProfiles($attributeProfiles);
0 ignored issues
show
Bug introduced by
It seems like $attributeProfiles can also be of type null; however, parameter $attributeProfiles of SAML2\XML\md\IDPSSODescr...:setAttributeProfiles() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

126
        $this->setAttributeProfiles(/** @scrutinizer ignore-type */ $attributeProfiles);
Loading history...
127
        $this->setSupportedAttributes($attributes);
0 ignored issues
show
Bug introduced by
It seems like $attributes can also be of type null; however, parameter $attributes of SAML2\XML\md\IDPSSODescr...etSupportedAttributes() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

127
        $this->setSupportedAttributes(/** @scrutinizer ignore-type */ $attributes);
Loading history...
128
    }
129
130
131
    /**
132
     * Initialize an IDPSSODescriptor.
133
     *
134
     * @param \DOMElement|null $xml The XML element we should load.
135
     * @return \SAML2\XML\md\IDPSSODescriptor
136
     * @throws \Exception
137
     */
138
    public static function fromXML(DOMElement $xml): object
139
    {
140
        $validUntil = self::getAttribute($xml, 'validUntil', null);
141
        $orgs = Organization::getChildrenOfClass($xml);
142
        Assert::maxCount($orgs, 1, 'More than one Organization found in this descriptor');
143
144
        $extensions = Extensions::getChildrenOfClass($xml);
145
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.');
146
147
        return new self(
148
            SingleSignOnService::getChildrenOfClass($xml),
149
            preg_split('/[\s]+/', trim(self::getAttribute($xml, 'protocolSupportEnumeration'))),
0 ignored issues
show
Bug introduced by
It seems like preg_split('/[\s]+/', tr...lSupportEnumeration'))) can also be of type false; however, parameter $protocolSupportEnumeration of SAML2\XML\md\IDPSSODescriptor::__construct() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

149
            /** @scrutinizer ignore-type */ preg_split('/[\s]+/', trim(self::getAttribute($xml, 'protocolSupportEnumeration'))),
Loading history...
150
            self::getBooleanAttribute($xml, 'WantAuthnRequestsSigned', null),
151
            NameIDMappingService::getChildrenOfClass($xml),
152
            AssertionIDRequestService::getChildrenOfClass($xml),
153
            Utils::extractStrings($xml, Constants::NS_MD, 'AttributeProfile'),
154
            Attribute::getChildrenOfClass($xml),
155
            self::getAttribute($xml, 'ID', null),
156
            $validUntil !== null ? Utils::xsDateTimeToTimestamp($validUntil) : null,
157
            self::getAttribute($xml, 'cacheDuration', null),
158
            !empty($extensions) ? $extensions[0] : null,
159
            self::getAttribute($xml, 'errorURL', null),
160
            KeyDescriptor::getChildrenOfClass($xml),
161
            !empty($orgs) ? $orgs[0] : null,
162
            ContactPerson::getChildrenOfClass($xml)
163
        );
164
    }
165
166
167
    /**
168
     * Collect the value of the WantAuthnRequestsSigned-property
169
     *
170
     * @return bool|null
171
     */
172
    public function wantAuthnRequestsSigned(): ?bool
173
    {
174
        return $this->wantAuthnRequestsSigned;
175
    }
176
177
178
    /**
179
     * Set the value of the WantAuthnRequestsSigned-property
180
     *
181
     * @param bool|null $flag
182
     */
183
    protected function setWantAuthnRequestsSigned(?bool $flag = null): void
184
    {
185
        $this->wantAuthnRequestsSigned = $flag;
186
    }
187
188
189
    /**
190
     * Get the SingleSignOnService endpoints
191
     *
192
     * @return \SAML2\XML\md\SingleSignOnService[]
193
     */
194
    public function getSingleSignOnServices(): array
195
    {
196
        return $this->ssoServiceEndpoints;
197
    }
198
199
200
    /**
201
     * Set the SingleSignOnService endpoints
202
     *
203
     * @param array $singleSignOnServices
204
     */
205
    protected function setSingleSignOnServices(array $singleSignOnServices): void
206
    {
207
        Assert::minCount($singleSignOnServices, 1, 'At least one SingleSignOnService must be specified.');
208
        Assert::allIsInstanceOf(
209
            $singleSignOnServices,
210
            SingleSignOnService::class,
211
            'All md:SingleSignOnService endpoints must be an instance of SingleSignOnService.'
212
        );
213
        $this->ssoServiceEndpoints = $singleSignOnServices;
214
    }
215
216
217
    /**
218
     * Get the NameIDMappingService endpoints
219
     *
220
     * @return \SAML2\XML\md\NameIDMappingService[]
221
     */
222
    public function getNameIDMappingServices(): array
223
    {
224
        return $this->nameIDMappingServiceEndpoints;
225
    }
226
227
228
    /**
229
     * Set the NameIDMappingService endpoints
230
     *
231
     * @param array $nameIDMappingServices
232
     */
233
    protected function setNameIDMappingServices(array $nameIDMappingServices): void
234
    {
235
        Assert::allIsInstanceOf(
236
            $nameIDMappingServices,
237
            NameIDMappingService::class,
238
            'All md:NameIDMappingService endpoints must be an instance of NameIDMappingService.'
239
        );
240
        $this->nameIDMappingServiceEndpoints = $nameIDMappingServices;
241
    }
242
243
244
    /**
245
     * Collect the AssertionIDRequestService endpoints
246
     *
247
     * @return \SAML2\XML\md\AssertionIDRequestService[]
248
     */
249
    public function getAssertionIDRequestServices(): array
250
    {
251
        return $this->assertionIDRequestServiceEndpoints;
252
    }
253
254
255
    /**
256
     * Set the AssertionIDRequestService endpoints
257
     *
258
     * @param array $assertionIDRequestServices
259
     */
260
    protected function setAssertionIDRequestService(array $assertionIDRequestServices): void
261
    {
262
        Assert::allIsInstanceOf(
263
            $assertionIDRequestServices,
264
            AssertionIDRequestService::class,
265
            'All md:AssertionIDRequestService endpoints must be an instance of AssertionIDRequestService.'
266
        );
267
        $this->assertionIDRequestServiceEndpoints = $assertionIDRequestServices;
268
    }
269
270
271
    /**
272
     * Get the attribute profiles supported
273
     *
274
     * @return string[]
275
     */
276
    public function getAttributeProfiles(): array
277
    {
278
        return $this->attributeProfiles;
279
    }
280
281
282
    /**
283
     * Set the attribute profiles supported
284
     *
285
     * @param array $attributeProfiles
286
     */
287
    protected function setAttributeProfiles(array $attributeProfiles): void
288
    {
289
        $this->attributeProfiles = $attributeProfiles;
290
    }
291
292
293
    /**
294
     * Get the attributes supported by this IdP
295
     *
296
     * @return \SAML2\XML\saml\Attribute[]
297
     */
298
    public function getSupportedAttributes(): array
299
    {
300
        return $this->attributes;
301
    }
302
303
304
    /**
305
     * Set the attributes supported by this IdP
306
     *
307
     * @param \SAML2\XML\saml\Attribute[] $attributes
308
     */
309
    protected function setSupportedAttributes(array $attributes): void
310
    {
311
        $this->attributes = $attributes;
312
    }
313
314
315
    /**
316
     * Add this IDPSSODescriptor to an EntityDescriptor.
317
     *
318
     * @param \DOMElement $parent The EntityDescriptor we should append this IDPSSODescriptor to.
319
     * @return \DOMElement
320
     * @throws \Exception
321
     */
322
    public function toXML(DOMElement $parent = null): DOMElement
323
    {
324
        $e = parent::toXML($parent);
325
326
        if (is_bool($this->wantAuthnRequestsSigned)) {
327
            $e->setAttribute('WantAuthnRequestsSigned', $this->wantAuthnRequestsSigned ? 'true' : 'false');
328
        }
329
330
        foreach ($this->ssoServiceEndpoints as $ep) {
331
            $ep->toXML($e);
332
        }
333
334
        foreach ($this->nameIDMappingServiceEndpoints as $ep) {
335
            $ep->toXML($e);
336
        }
337
338
        foreach ($this->assertionIDRequestServiceEndpoints as $ep) {
339
            $ep->toXML($e);
340
        }
341
342
        Utils::addStrings($e, Constants::NS_MD, 'md:AttributeProfile', false, $this->attributeProfiles);
343
344
        foreach ($this->attributes as $a) {
345
            $a->toXML($e);
346
        }
347
348
        return $e;
349
    }
350
}
351