Passed
Pull Request — master (#226)
by Jaime Pérez
03:17
created

ArtifactResponse   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 54
dl 0
loc 147
rs 10
c 0
b 0
f 0
wmc 11

5 Methods

Rating   Name   Duplication   Size   Complexity  
A setMessage() 0 3 1
B fromXML() 0 55 6
A getMessage() 0 3 1
A __construct() 0 23 1
A toXML() 0 9 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SAML2\XML\samlp;
6
7
use DOMElement;
8
use SAML2\Utils;
9
use SAML2\XML\ds\Signature;
10
use SAML2\XML\saml\Issuer;
11
use Webmozart\Assert\Assert;
12
13
/**
14
 * The \SAML2\ArtifactResponse, is the response to the \SAML2\ArtifactResolve.
15
 *
16
 * @author Danny Bollaert, UGent AS. <[email protected]>
17
 * @package SimpleSAMLphp
18
 */
19
class ArtifactResponse extends AbstractStatusResponse
20
{
21
    /** @var \SAML2\XML\samlp\AbstractMessage */
22
    protected $message;
23
24
25
    /**
26
     * Constructor for SAML 2 ArtifactResponse.
27
     *
28
     * @param \SAML2\XML\samlp\Status $status
29
     * @param \SAML2\XML\saml\Issuer|null $issuer
30
     * @param string|null $id
31
     * @param int|null $issueInstant
32
     * @param string|null $inResponseTo
33
     * @param string|null $destination
34
     * @param string|null $consent
35
     * @param \SAML2\XML\samlp\Extensions|null $extensions
36
     * @param \SAML2\XML\samlp\AbstractMessage|null $message
37
     */
38
    public function __construct(
39
        Status $status,
40
        ?Issuer $issuer = null,
41
        ?string $id = null,
42
        ?int $issueInstant = null,
43
        ?string $inResponseTo = null,
44
        ?string $destination = null,
45
        ?string $consent = null,
46
        ?Extensions $extensions = null,
47
        ?AbstractMessage $message = null
48
    ) {
49
        parent::__construct(
50
            $status,
51
            $issuer,
52
            $id,
53
            $issueInstant,
54
            $inResponseTo,
55
            $destination,
56
            $consent,
57
            $extensions
58
        );
59
60
        $this->setMessage($message);
61
    }
62
63
64
    /**
65
     * Collect the value of the any-property
66
     *
67
     * @return \SAML2\XML\samlp\AbstractMessage|null
68
     */
69
    public function getMessage(): ?AbstractMessage
70
    {
71
        return $this->message;
72
    }
73
74
75
    /**
76
     * Set the value of the any-property
77
     *
78
     * @param \SAML2\XML\samlp\AbstractMessage|null $message
79
     * @return void
80
     */
81
    private function setMessage(?AbstractMessage $message): void
82
    {
83
        $this->message = $message;
84
    }
85
86
87
    /**
88
     * Convert XML into an ArtifactResponse
89
     *
90
     * @param \DOMElement $xml
91
     * @return self
92
     * @throws \Exception
93
     */
94
    public static function fromXML(DOMElement $xml): object
95
    {
96
        Assert::same($xml->localName, 'ArtifactResponse');
97
        Assert::same($xml->namespaceURI, ArtifactResponse::NS);
98
        Assert::same('2.0', self::getAttribute($xml, 'Version'));
99
100
        $id = self::getAttribute($xml, 'ID');
101
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
102
        $inResponseTo = self::getAttribute($xml, 'InResponseTo', null);
103
        $destination = self::getAttribute($xml, 'Destination', null);
104
        $consent = self::getAttribute($xml, 'Consent', null);
105
106
        $issuer = Issuer::getChildrenOfClass($xml);
107
        Assert::countBetween($issuer, 0, 1);
108
109
        // find message; it should come last, after the Status-element
110
        $status = Utils::xpQuery($xml, './saml_protocol:Status');
111
        $status = $status[0];
112
        $message = null;
113
114
        /** @psalm-suppress RedundantCondition */
115
        for ($child = $status->nextSibling; $child !== null; $child = $child->nextSibling) {
116
            if ($child instanceof DOMElement) {
117
                $message = MessageFactory::fromXML($child);
118
                break;
119
            }
120
            /* Ignore comments and text nodes. */
121
        }
122
123
        $status = Status::getChildrenOfClass($xml);
124
        Assert::count($status, 1);
125
126
        $extensions = Extensions::getChildrenOfClass($xml);
127
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
128
129
        $signature = Signature::getChildrenOfClass($xml);
130
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
131
132
        $response = new self(
133
            array_pop($status),
134
            empty($issuer) ? null : array_pop($issuer),
135
            $id,
136
            $issueInstant,
137
            $inResponseTo,
138
            $destination,
139
            $consent,
140
            empty($extensions) ? null : array_pop($extensions),
141
            $message
142
        );
143
144
        if (!empty($signature)) {
145
            $response->setSignature($signature[0]);
146
        }
147
148
        return $response;
149
    }
150
151
152
    /**
153
     * Convert the ArtifactResponse message to an XML element.
154
     *
155
     * @return \DOMElement This response.
156
     */
157
    public function toXML(?DOMElement $parent = null): DOMElement
158
    {
159
        $e = parent::toXML($parent);
160
161
        if ($this->message !== null) {
162
            $this->message->toXML($e);
163
        }
164
165
        return $this->signElement($e);
166
    }
167
}
168