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

Response::fromXML()   B

Complexity

Conditions 9
Paths 12

Size

Total Lines 58
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 9
eloc 40
c 1
b 1
f 0
nc 12
nop 1
dl 0
loc 58
rs 7.7244

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SAML2\XML\samlp;
6
7
use DOMElement;
8
use SAML2\Constants;
9
use SAML2\Utils;
10
use SAML2\XML\ds\Signature;
11
use SAML2\XML\saml\Assertion;
12
use SAML2\XML\saml\EncryptedAssertion;
13
use SAML2\XML\saml\Issuer;
14
use Webmozart\Assert\Assert;
15
16
/**
17
 * Class for SAML 2 Response messages.
18
 *
19
 * @package SimpleSAMLphp
20
 */
21
class Response extends AbstractStatusResponse
22
{
23
    /**
24
     * The assertions in this response.
25
     *
26
     * @var (\SAML2\XML\saml\Assertion|\SAML2\XML\saml\EncryptedAssertion)[]
27
     */
28
    protected $assertions = [];
29
30
31
    /**
32
     * Constructor for SAML 2 response messages.
33
     *
34
     * @param \SAML2\XML\samlp\Status $status
35
     * @param \SAML2\XML\saml\Issuer $issuer
36
     * @param string $id
37
     * @param int $issueInstant
38
     * @param string $inResponseTo
39
     * @param string|null $destination
40
     * @param string|null $consent
41
     * @param \SAML2\XML\samlp\Extensions $extensions
42
     * @param (\SAML2\XML\saml\Assertion|\SAML2\XML\saml\EncryptedAssertion)[] $assertions
43
     */
44
    public function __construct(
45
        Status $status,
46
        ?Issuer $issuer = null,
47
        ?string $id = null,
48
        ?int $issueInstant = null,
49
        ?string $inResponseTo = null,
50
        ?string $destination = null,
51
        ?string $consent = null,
52
        ?Extensions $extensions = null,
53
        array $assertions = []
54
    ) {
55
        parent::__construct(
56
            $status,
57
            $issuer,
58
            $id,
59
            $issueInstant,
60
            $inResponseTo,
61
            $destination,
62
            $consent,
63
            $extensions
64
        );
65
66
        $this->setAssertions($assertions);
67
    }
68
69
70
    /**
71
     * Retrieve the assertions in this response.
72
     *
73
     * @return \SAML2\XML\saml\Assertion[]|\SAML2\XML\saml\EncryptedAssertion[]
74
     */
75
    public function getAssertions(): array
76
    {
77
        return $this->assertions;
78
    }
79
80
81
    /**
82
     * Set the assertions that should be included in this response.
83
     *
84
     * @param (\SAML2\XML\saml\Assertion|\SAML2\XML\saml\EncryptedAssertion)[] $assertions The assertions.
85
     * @return void
86
     */
87
    protected function setAssertions(array $assertions): void
88
    {
89
        Assert::allIsInstanceOfAny($assertions, [Assertion::class, EncryptedAssertion::class]);
90
        $this->assertions = $assertions;
91
    }
92
93
94
    /**
95
     * Convert XML into a Response element.
96
     *
97
     * @param \DOMElement $xml The input message.
98
     * @return self
99
     */
100
    public static function fromXML(DOMElement $xml): object
101
    {
102
        Assert::same($xml->localName, 'Response');
103
        Assert::same($xml->namespaceURI, Response::NS);
104
        Assert::same('2.0', self::getAttribute($xml, 'Version'));
105
106
        $id = self::getAttribute($xml, 'ID');
107
        /** @psalm-suppress PossiblyNullArgument */
108
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
109
        $inResponseTo = self::getAttribute($xml, 'InResponseTo', null);
110
        $destination = self::getAttribute($xml, 'Destination', null);
111
        $consent = self::getAttribute($xml, 'Consent', null);
112
113
        $issuer = Issuer::getChildrenOfClass($xml);
114
        Assert::countBetween($issuer, 0, 1);
115
116
        $status = Status::getChildrenOfClass($xml);
117
        Assert::count($status, 1);
118
119
        $extensions = Extensions::getChildrenOfClass($xml);
120
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
121
122
        $assertions = [];
123
        foreach ($xml->childNodes as $node) {
124
            if ($node->namespaceURI !== Constants::NS_SAML) {
125
                continue;
126
            } elseif (!($node instanceof DOMElement)) {
127
                continue;
128
            }
129
130
            if ($node->localName === 'Assertion') {
131
                $assertions[] = new Assertion($node);
132
            } elseif ($node->localName === 'EncryptedAssertion') {
133
                $assertions[] = EncryptedAssertion::fromXML($node);
134
            }
135
        }
136
137
        $signature = Signature::getChildrenOfClass($xml);
138
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
139
140
        $response = new self(
141
            array_pop($status),
142
            empty($issuer) ? null : array_pop($issuer),
143
            $id,
144
            $issueInstant,
145
            $inResponseTo,
146
            $destination,
147
            $consent,
148
            empty($extensions) ? null : array_pop($extensions),
149
            $assertions
150
        );
151
152
        if (!empty($signature)) {
153
            $response->setSignature($signature[0]);
154
            $response->messageContainedSignatureUponConstruction = true;
155
        }
156
157
        return $response;
158
    }
159
160
161
    /**
162
     * Convert the response message to an XML element.
163
     *
164
     * @return \DOMElement This response.
165
     */
166
    public function toXML(?DOMElement $parent = null): DOMElement
167
    {
168
        $e = parent::toXML($parent);
169
170
        foreach ($this->assertions as $assertion) {
171
            $assertion->toXML($e);
172
        }
173
174
        return $this->signElement($e);
175
    }
176
}
177