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

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