LogoutResponse   A
last analyzed

Complexity

Total Complexity 4

Size/Duplication

Total Lines 105
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 45
dl 0
loc 105
rs 10
c 0
b 0
f 0
wmc 4

2 Methods

Rating   Name   Duplication   Size   Complexity  
A fromXML() 0 50 3
A __construct() 0 21 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\samlp;
6
7
use DateTimeImmutable;
8
use DOMElement;
9
use SimpleSAML\SAML2\Assert\Assert;
10
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
11
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
12
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
13
use SimpleSAML\SAML2\XML\saml\Issuer;
14
use SimpleSAML\XML\Exception\InvalidDOMElementException;
15
use SimpleSAML\XML\SchemaValidatableElementInterface;
16
use SimpleSAML\XML\SchemaValidatableElementTrait;
17
use SimpleSAML\XMLSecurity\XML\ds\Signature;
18
19
use function array_pop;
20
use function preg_replace;
21
22
/**
23
 * Class for SAML 2 LogoutResponse messages.
24
 *
25
 * @package simplesamlphp/saml2
26
 */
27
final class LogoutResponse extends AbstractStatusResponse implements SchemaValidatableElementInterface
28
{
29
    use SchemaValidatableElementTrait;
30
31
    /**
32
     * Constructor for SAML 2 LogoutResponse.
33
     *
34
     * @param \SimpleSAML\SAML2\XML\samlp\Status $status
35
     * @param \DateTimeImmutable $issueInstant
36
     * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer
37
     * @param string|null $id
38
     * @param string $version
39
     * @param string|null $inResponseTo
40
     * @param string|null $destination
41
     * @param string|null $consent
42
     * @param \SimpleSAML\SAML2\XML\samlp\Extensions|null $extensions
43
     *
44
     * @throws \Exception
45
     */
46
    public function __construct(
47
        Status $status,
48
        DateTimeImmutable $issueInstant,
49
        ?Issuer $issuer = null,
50
        ?string $id = null,
51
        string $version = '2.0',
52
        ?string $inResponseTo = null,
53
        ?string $destination = null,
54
        ?string $consent = null,
55
        ?Extensions $extensions = null,
56
    ) {
57
        parent::__construct(
58
            $status,
59
            $issueInstant,
60
            $issuer,
61
            $id,
62
            $version,
63
            $inResponseTo,
64
            $destination,
65
            $consent,
66
            $extensions,
67
        );
68
    }
69
70
71
    /**
72
     * Convert XML into an LogoutResponse
73
     *
74
     * @param \DOMElement $xml
75
     * @return static
76
     *
77
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
78
     *   if the qualified name of the supplied element is wrong
79
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
80
     *   if the supplied element is missing one of the mandatory attributes
81
     */
82
    public static function fromXML(DOMElement $xml): static
83
    {
84
        Assert::same($xml->localName, 'LogoutResponse', InvalidDOMElementException::class);
85
        Assert::same($xml->namespaceURI, LogoutResponse::NS, InvalidDOMElementException::class);
86
87
        $version = self::getAttribute($xml, 'Version');
88
        Assert::true(version_compare('2.0', $version, '<='), RequestVersionTooLowException::class);
89
        Assert::true(version_compare('2.0', $version, '>='), RequestVersionTooHighException::class);
90
91
        $id = self::getAttribute($xml, 'ID');
92
        Assert::validNCName($id); // Covers the empty string
93
94
        $issueInstant = self::getAttribute($xml, 'IssueInstant');
95
        // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
96
        $issueInstant = preg_replace('/([.][0-9]+Z)$/', 'Z', $issueInstant, 1);
97
98
        Assert::validDateTime($issueInstant, ProtocolViolationException::class);
99
        $issueInstant = new DateTimeImmutable($issueInstant);
100
101
        $issuer = Issuer::getChildrenOfClass($xml);
102
        Assert::countBetween($issuer, 0, 1);
103
104
        $status = Status::getChildrenOfClass($xml);
105
        Assert::count($status, 1);
106
107
        $extensions = Extensions::getChildrenOfClass($xml);
108
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
109
110
        $signature = Signature::getChildrenOfClass($xml);
111
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
112
113
        $response = new static(
114
            array_pop($status),
115
            $issueInstant,
116
            array_pop($issuer),
117
            $id,
118
            $version,
119
            self::getOptionalAttribute($xml, 'InResponseTo', null),
120
            self::getOptionalAttribute($xml, 'Destination', null),
121
            self::getOptionalAttribute($xml, 'Consent', null),
122
            empty($extensions) ? null : array_pop($extensions),
123
        );
124
125
        if (!empty($signature)) {
126
            $response->setSignature($signature[0]);
127
            $response->messageContainedSignatureUponConstruction = true;
128
            $response->setXML($xml);
129
        }
130
131
        return $response;
132
    }
133
}
134