Passed
Push — master ( d3e6a5...90893b )
by Tim
02:27
created

Conditions   A

Complexity

Total Complexity 31

Size/Duplication

Total Lines 298
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 77
dl 0
loc 298
rs 9.92
c 0
b 0
f 0
wmc 31

16 Methods

Rating   Name   Duplication   Size   Complexity  
A getAudienceRestriction() 0 3 1
A setCondition() 0 5 1
A setAudienceRestriction() 0 5 1
A getOneTimeUse() 0 3 1
A setProxyRestriction() 0 3 1
A getProxyRestriction() 0 3 1
A __construct() 0 16 2
A setNotOnOrAfter() 0 3 1
A getCondition() 0 3 1
A getNotBefore() 0 3 1
A isEmptyElement() 0 9 6
A setOneTimeUse() 0 3 1
A getNotOnOrAfter() 0 3 1
A setNotBefore() 0 3 1
A fromXML() 0 46 5
A toXML() 0 30 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\saml;
6
7
use DOMElement;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
10
use SimpleSAML\XML\Exception\InvalidDOMElementException;
11
use SimpleSAML\XML\Utils as XMLUtils;
12
13
use function array_pop;
14
use function gmdate;
15
use function is_bool;
16
17
/**
18
 * Class representing SAML 2 Conditions element.
19
 *
20
 * @package simplesamlphp/saml2
21
 */
22
final class Conditions extends AbstractSamlElement
23
{
24
    /** @var int|null */
25
    protected ?int $notBefore;
26
27
    /** @var int|null */
28
    protected ?int $notOnOrAfter;
29
30
    /** @var \SimpleSAML\SAML2\XML\saml\Condition[] */
31
    protected array $condition;
32
33
    /** @var \SimpleSAML\SAML2\XML\saml\AudienceRestriction[] */
34
    protected array $audienceRestriction;
35
36
    /** @var bool */
37
    protected bool $oneTimeUse = false;
38
39
    /** @var \SimpleSAML\SAML2\XML\saml\ProxyRestriction|null */
40
    protected ?ProxyRestriction $proxyRestriction;
41
42
43
    /**
44
     * Initialize a Conditions element.
45
     *
46
     * @param int|null $notBefore
47
     * @param int|null $notOnOrAfter
48
     * @param \SimpleSAML\SAML2\XML\saml\Condition[] $condition
49
     * @param \SimpleSAML\SAML2\XML\saml\AudienceRestriction[] $audienceRestriction
50
     * @param bool|null $oneTimeUse
51
     * @param \SimpleSAML\SAML2\XML\saml\ProxyRestriction|null $proxyRestriction
52
     */
53
    public function __construct(
54
        ?int $notBefore = null,
55
        ?int $notOnOrAfter = null,
56
        array $condition = [],
57
        array $audienceRestriction = [],
58
        ?bool $oneTimeUse = null,
59
        ?ProxyRestriction $proxyRestriction = null
60
    ) {
61
        $this->setNotBefore($notBefore);
62
        $this->setNotOnOrAfter($notOnOrAfter);
63
        $this->setCondition($condition);
64
        $this->setAudienceRestriction($audienceRestriction);
65
        if (is_bool($oneTimeUse)) {
66
            $this->setOneTimeUse($oneTimeUse);
67
        }
68
        $this->setProxyRestriction($proxyRestriction);
69
    }
70
71
72
    /**
73
     * Collect the value of the notBefore-property
74
     *
75
     * @return int|null
76
     */
77
    public function getNotBefore(): ?int
78
    {
79
        return $this->notBefore;
80
    }
81
82
83
    /**
84
     * Set the value of the notBefore-property
85
     *
86
     * @param int|null $notBefore
87
     */
88
    private function setNotBefore(?int $notBefore): void
89
    {
90
        $this->notBefore = $notBefore;
91
    }
92
93
94
    /**
95
     * Collect the value of the notOnOrAfter-property
96
     *
97
     * @return int|null
98
     */
99
    public function getNotOnOrAfter(): ?int
100
    {
101
        return $this->notOnOrAfter;
102
    }
103
104
105
    /**
106
     * Set the value of the notOnOrAfter-property
107
     *
108
     * @param int|null $notOnOrAfter
109
     */
110
    private function setNotOnOrAfter(?int $notOnOrAfter): void
111
    {
112
        $this->notOnOrAfter = $notOnOrAfter;
113
    }
114
115
116
    /**
117
     * Collect the value of the condition-property
118
     *
119
     * @return \SimpleSAML\SAML2\XML\saml\Condition[]
120
     */
121
    public function getCondition(): array
122
    {
123
        return $this->condition;
124
    }
125
126
127
    /**
128
     * Set the value of the condition-property
129
     *
130
     * @param \SimpleSAML\SAML2\XML\saml\Condition[] $condition
131
     */
132
    private function setCondition(array $condition): void
133
    {
134
        Assert::allIsInstanceOf($condition, Condition::class);
135
136
        $this->condition = $condition;
137
    }
138
139
140
    /**
141
     * Collect the value of the audienceRestriction-property
142
     *
143
     * @return \SimpleSAML\SAML2\XML\saml\AudienceRestriction[]
144
     */
145
    public function getAudienceRestriction(): array
146
    {
147
        return $this->audienceRestriction;
148
    }
149
150
151
    /**
152
     * Set the value of the audienceRestriction-property
153
     *
154
     * @param \SimpleSAML\SAML2\XML\saml\AudienceRestriction[] $audienceRestriction
155
     */
156
    private function setAudienceRestriction(array $audienceRestriction): void
157
    {
158
        Assert::allIsInstanceOf($audienceRestriction, AudienceRestriction::class);
159
160
        $this->audienceRestriction = $audienceRestriction;
161
    }
162
163
164
    /**
165
     * Collect the value of the oneTimeUse-property
166
     *
167
     * @return bool
168
     */
169
    public function getOneTimeUse(): bool
170
    {
171
        return $this->oneTimeUse;
172
    }
173
174
175
    /**
176
     * Set the value of the oneTimeUse-property
177
     *
178
     * @param bool $oneTimeUse
179
     */
180
    private function setOneTimeUse(bool $oneTimeUse): void
181
    {
182
        $this->oneTimeUse = $oneTimeUse;
183
    }
184
185
186
    /**
187
     * Collect the value of the proxyRestriction-property
188
     *
189
     * @return \SimpleSAML\SAML2\XML\saml\ProxyRestriction|null
190
     */
191
    public function getProxyRestriction(): ?ProxyRestriction
192
    {
193
        return $this->proxyRestriction;
194
    }
195
196
197
    /**
198
     * Set the value of the proxyRestriction-property
199
     *
200
     * @param \SimpleSAML\SAML2\XML\saml\ProxyRestriction|null $proxyRestriction
201
     */
202
    private function setProxyRestriction(?ProxyRestriction $proxyRestriction): void
203
    {
204
        $this->proxyRestriction = $proxyRestriction;
205
    }
206
207
208
    /**
209
     * Test if an object, at the state it's in, would produce an empty XML-element
210
     *
211
     * @return bool
212
     */
213
    public function isEmptyElement(): bool
214
    {
215
        return (
216
            empty($this->notBefore)
217
            && empty($this->notOnOrAfter)
218
            && empty($this->condition)
219
            && empty($this->audienceRestriction)
220
            && $this->oneTimeUse === false
221
            && empty($this->proxyRestriction)
222
        );
223
    }
224
225
226
    /**
227
     * Convert XML into a Conditions object
228
     *
229
     * @param \DOMElement $xml The XML element we should load
230
     * @return self
231
     *
232
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
233
     */
234
    public static function fromXML(DOMElement $xml): static
235
    {
236
        Assert::same($xml->localName, 'Conditions', InvalidDOMElementException::class);
237
        Assert::same($xml->namespaceURI, Conditions::NS, InvalidDOMElementException::class);
238
239
        $notBefore = self::getAttribute($xml, 'NotBefore', null);
240
        if ($notBefore !== null) {
241
            // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
242
            $notBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $notBefore, 1);
243
244
            Assert::validDateTimeZulu($notBefore, ProtocolViolationException::class);
245
        }
246
247
        $notOnOrAfter = self::getAttribute($xml, 'NotOnOrAfter', null);
248
        if ($notOnOrAfter !== null) {
249
            // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
250
            $notOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $notOnOrAfter, 1);
251
252
            Assert::validDateTimeZulu($notOnOrAfter, ProtocolViolationException::class);
253
        }
254
255
        $condition = AbstractCondition::getChildrenOfClass($xml);
256
        $audienceRestriction = AudienceRestriction::getChildrenOfClass($xml);
257
        $oneTimeUse = XMLUtils::extractStrings($xml, AbstractSamlElement::NS, 'OneTimeUse');
258
        $proxyRestriction = ProxyRestriction::getChildrenOfClass($xml);
259
260
        Assert::maxCount(
261
            $oneTimeUse,
262
            1,
263
            'There MUST occur at most one <saml:OneTimeUse> element inside a <saml:Conditions>',
264
            ProtocolViolationException::class
265
        );
266
        Assert::maxCount(
267
            $proxyRestriction,
268
            1,
269
            'There MUST occur at most one <saml:ProxyRestriction> element inside a <saml:Conditions>',
270
            ProtocolViolationException::class
271
        );
272
273
        return new static(
274
            $notBefore !== null ? XMLUtils::xsDateTimeToTimestamp($notBefore) : null,
275
            $notOnOrAfter !== null ? XMLUtils::xsDateTimeToTimestamp($notOnOrAfter) : null,
276
            $condition,
277
            $audienceRestriction,
278
            !empty($oneTimeUse),
279
            array_pop($proxyRestriction)
280
        );
281
    }
282
283
284
    /**
285
     * Convert this element to XML.
286
     *
287
     * @param  \DOMElement|null $parent The parent element we should append this element to.
288
     * @return \DOMElement This element, as XML.
289
     */
290
    public function toXML(DOMElement $parent = null): DOMElement
291
    {
292
        $e = $this->instantiateParentElement($parent);
293
294
        if ($this->getNotBefore() !== null) {
295
            $e->setAttribute('NotBefore', gmdate('Y-m-d\TH:i:s\Z', $this->getNotBefore()));
296
        }
297
298
        if ($this->getNotOnOrAfter() !== null) {
299
            $e->setAttribute('NotOnOrAfter', gmdate('Y-m-d\TH:i:s\Z', $this->getNotOnOrAfter()));
300
        }
301
302
        foreach ($this->getCondition() as $condition) {
303
            $condition->toXML($e);
304
        }
305
306
        foreach ($this->getAudienceRestriction() as $audienceRestriction) {
307
            $audienceRestriction->toXML($e);
308
        }
309
310
        if ($this->getOneTimeUse() !== false) {
311
            /** @psalm-suppress PossiblyNullReference */
312
            $e->appendChild(
313
                $e->ownerDocument->createElementNS(AbstractSamlElement::NS, 'saml:OneTimeUse')
0 ignored issues
show
Bug introduced by
The method createElementNS() does not exist on null. ( Ignorable by Annotation )

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

313
                $e->ownerDocument->/** @scrutinizer ignore-call */ 
314
                                   createElementNS(AbstractSamlElement::NS, 'saml:OneTimeUse')

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
314
            );
315
        }
316
317
        $this->getProxyRestriction()?->toXML($e);
318
319
        return $e;
320
    }
321
}
322