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

AttributeQuery   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 130
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 41
dl 0
loc 130
rs 10
c 0
b 0
f 0
wmc 7

5 Methods

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