Completed
Push — master ( da4b66...3ae217 )
by Tim
19s queued 15s
created

AbstractRequestAbstractType::toXML()   A

Complexity

Conditions 6
Paths 5

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 17
c 1
b 0
f 0
dl 0
loc 33
rs 9.0777
cc 6
nc 5
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML11\XML\samlp;
6
7
use DateTimeImmutable;
8
use DOMElement;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML11\Utils\XPath;
11
use SimpleSAML\XML\Exception\SchemaViolationException;
12
13
use function array_pop;
14
15
/**
16
 * Base class for all SAML 1.1 requests.
17
 *
18
 * @package simplesamlphp/saml11
19
 */
20
abstract class AbstractRequestAbstractType extends AbstractMessage
21
{
22
    /**
23
     * Initialize a request.
24
     *
25
     * @param string $id
26
     * @param int $majorVersion
27
     * @param int $minorVersion
28
     * @param \DateTimeImmutable $issueInstant
29
     * @param array<\SimpleSAML\SAML11\XML\samlp\RespondWith>
30
     *
31
     * @throws \Exception
32
     */
33
    protected function __construct(
34
        protected string $id,
35
        int $majorVersion,
36
        int $minorVersion,
37
        DateTimeImmutable $issueInstant,
38
        protected array $respondWith = [],
39
    ) {
40
        Assert::validNCName($id, SchemaViolationException::class);
41
        Assert::allIsInstanceOf($respondWith, RespondWith::class, SchemaViolationException::class);
42
43
        parent::__construct($majorVersion, $minorVersion, $issueInstant);
44
    }
45
46
47
    /**
48
     * Retrieve the ID of this request.
49
     *
50
     * @return string The ID of this request
51
     */
52
    public function getID(): string
53
    {
54
        return $this->id;
55
    }
56
57
58
    /**
59
     * @return array<\SimpleSAML\SAML11\XML\samlp\RespondWith>
60
     */
61
    public function getRespondWith(): array
62
    {
63
        return $this->respondWith;
64
    }
65
66
67
    /**
68
     * Convert this message to an unsigned XML document.
69
     * This method does not sign the resulting XML document.
70
     *
71
     * @return \DOMElement The root element of the DOM tree
72
     */
73
    protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
74
    {
75
        $e = parent::toUnsignedXML($parent);
76
        $e->setAttribute('RequestID', $this->getID());
77
78
        foreach ($this->getRespondWith() as $respondWith) {
79
            $respondWith->toXML($e);
80
        }
81
82
        return $e;
83
    }
84
85
86
    /**
87
     * Create XML from this class
88
     *
89
     * @param \DOMElement|null $parent
90
     * @return \DOMElement
91
     */
92
    public function toXML(?DOMElement $parent = null): DOMElement
93
    {
94
        if ($this->isSigned() === true && $this->signer === null) {
95
            // We already have a signed document and no signer was set to re-sign it
96
            if ($parent === null) {
97
                return $this->xml;
98
            }
99
100
            $node = $parent->ownerDocument?->importNode($this->getXML(), true);
101
            $parent->appendChild($node);
102
103
            return $parent;
104
        }
105
106
        $e = $this->toUnsignedXML($parent);
107
108
        if ($this->signer !== null) {
109
            $signedXML = $this->doSign($e);
110
111
            // Test for an RespondWith
112
            $messageElements = XPath::xpQuery($signedXML, './saml_protocol:RespondWith', XPath::getXPath($signedXML));
113
            $respondWith = array_pop($messageElements);
114
115
            if ($respondWith === null) {
116
                $signedXML->appendChild($this->signature?->toXML($signedXML));
117
            } else {
118
                $signedXML->insertBefore($this->signature?->toXML($signedXML), $respondWith->nextSibling);
119
            }
120
121
            return $signedXML;
122
        }
123
124
        return $e;
125
    }
126
}
127