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

AttributeQuery::toXML()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 1
dl 0
loc 11
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 Exception;
9
use SAML2\Constants;
10
use SAML2\Utils;
11
use SAML2\XML\ds\Signature;
12
use SAML2\XML\saml\Attribute;
13
use SAML2\XML\saml\Issuer;
14
use SAML2\XML\saml\Subject;
15
use Webmozart\Assert\Assert;
16
17
/**
18
 * Class for SAML 2 attribute query messages.
19
 *
20
 * An attribute query asks for a set of attributes. The following
21
 * rules apply:
22
 *
23
 * - If no attributes are present in the query, all attributes should be
24
 *   returned.
25
 * - If any attributes are present, only those attributes which are present
26
 *   in the query should be returned.
27
 * - If an attribute contains any attribute values, only the attribute values
28
 *   which match those in the query should be returned.
29
 *
30
 * @package SimpleSAMLphp
31
 */
32
class AttributeQuery extends AbstractSubjectQuery
33
{
34
    /**
35
     * The attributes, as an associative array.
36
     *
37
     * @var \SAML2\XML\saml\Attribute[]
38
     */
39
    protected $attributes = [];
40
41
42
    /**
43
     * Constructor for SAML 2 AttributeQuery.
44
     *
45
     * @param \SAML2\XML\saml\Subject $subject
46
     * @param \SAML2\XML\saml\Attribute[] $attributes
47
     * @param \SAML2\XML\saml\Issuer $issuer
48
     * @param string $id
49
     * @param string $version
50
     * @param int $issueInstant
51
     * @param string|null $destination
52
     * @param string|null $consent
53
     * @param \SAML2\XML\samlp\Extensions $extensions
54
     */
55
    public function __construct(
56
        Subject $subject,
57
        array $attributes = [],
58
        ?Issuer $issuer = null,
59
        ?string $id = null,
60
        ?string $version = '2.0',
61
        ?int $issueInstant = null,
62
        ?string $destination = null,
63
        ?string $consent = null,
64
        ?Extensions $extensions = null
65
    ) {
66
        parent::__construct($subject, $issuer, $id, $version, $issueInstant, $destination, $consent, $extensions);
67
68
        $this->setAttributes($attributes);
69
    }
70
71
72
    /**
73
     * Retrieve all requested attributes.
74
     *
75
     * @return \SAML2\XML\saml\Attribute[] All requested attributes, as an associative array.
76
     */
77
    public function getAttributes(): array
78
    {
79
        return $this->attributes;
80
    }
81
82
83
    /**
84
     * Set all requested attributes.
85
     *
86
     * @param \SAML2\XML\saml\Attribute[] $attributes All requested attributes, as an associative array.
87
     * @return void
88
     */
89
    public function setAttributes(array $attributes): void
90
    {
91
        Assert::allIsInstanceOf($attributes, Attribute::class);
92
        $this->attributes = $attributes;
93
    }
94
95
96
    /**
97
     * Create a class from XML
98
     *
99
     * @param \DOMElement $xml
100
     * @return self
101
     */
102
    public static function fromXML(DOMElement $xml): object
103
    {
104
        Assert::same($xml->localName, 'AttributeQuery');
105
        Assert::same($xml->namespaceURI, AttributeQuery::NS);
106
107
        $id = self::getAttribute($xml, 'ID');
108
        $version = self::getAttribute($xml, 'Version');
109
        $issueInstant = Utils::xsDateTimeToTimestamp(self::getAttribute($xml, 'IssueInstant'));
110
        $inResponseTo = self::getAttribute($xml, 'InResponseTo', null);
0 ignored issues
show
Unused Code introduced by
The assignment to $inResponseTo is dead and can be removed.
Loading history...
111
        $destination = self::getAttribute($xml, 'Destination', null);
112
        $consent = self::getAttribute($xml, 'Consent', null);
113
114
        $issuer = Issuer::getChildrenOfClass($xml);
115
        Assert::countBetween($issuer, 0, 1);
116
117
        $extensions = Extensions::getChildrenOfClass($xml);
118
        Assert::maxCount($extensions, 1, 'Only one saml:Extensions element is allowed.');
119
120
        $subject = Subject::getChildrenOfClass($xml);
121
        Assert::notEmpty($subject, 'Missing subject in subject query.');
122
        Assert::maxCount($subject, 1, 'More than one <saml:Subject> in AttributeQuery');
123
124
        $signature = Signature::getChildrenOfClass($xml);
125
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.');
126
127
        $request = new self(
128
            array_pop($subject),
129
            Attribute::getChildrenOfClass($xml),
130
            array_pop($issuer),
131
            $id,
132
            $version,
133
            $issueInstant,
134
            $destination,
135
            $consent,
136
            array_pop($extensions)
137
        );
138
139
        if (!empty($signature)) {
140
            $request->setSignature($signature[0]);
141
        }
142
143
        return $request;
144
    }
145
146
147
    /**
148
     * Convert the attribute query message to an XML element.
149
     *
150
     * @return \DOMElement This attribute query.
151
     */
152
    public function toXML(?DOMElement $parent = null): DOMElement
153
    {
154
        Assert::null($parent);
155
156
        $parent = parent::toXML($parent);
157
158
        foreach ($this->attributes as $attribute) {
159
            $attribute->toXML($parent);
160
        }
161
162
        return $this->signElement($parent);
163
    }
164
}
165