1<?php
2
3declare(strict_types=1);
4
5namespace SAML2\XML\saml;
6
7use DOMElement;
8
9use SAML2\Constants;
10use SAML2\Utils;
11
12/**
13 * Class representing SAML 2 Attribute.
14 *
15 * @package SimpleSAMLphp
16 */
17class Attribute
18{
19    /**
20     * The Name of this attribute.
21     *
22     * @var string|null
23     */
24    private $Name = null;
25
26    /**
27     * The NameFormat of this attribute.
28     *
29     * @var string|null
30     */
31    private $NameFormat = null;
32
33    /**
34     * The FriendlyName of this attribute.
35     *
36     * @var string|null
37     */
38    private $FriendlyName = null;
39
40    /**
41     * List of attribute values.
42     *
43     * Array of \SAML2\XML\saml\AttributeValue elements.
44     *
45     * @var \SAML2\XML\saml\AttributeValue[]
46     */
47    private $AttributeValue = [];
48
49
50    /**
51     * Initialize an Attribute.
52     *
53     * @param \DOMElement|null $xml The XML element we should load.
54     * @throws \Exception
55     */
56    public function __construct(DOMElement $xml = null)
57    {
58        if ($xml === null) {
59            return;
60        }
61
62        if (!$xml->hasAttribute('Name')) {
63            throw new \Exception('Missing Name on Attribute.');
64        }
65        $this->setName($xml->getAttribute('Name'));
66
67        if ($xml->hasAttribute('NameFormat')) {
68            $this->setNameFormat($xml->getAttribute('NameFormat'));
69        }
70
71        if ($xml->hasAttribute('FriendlyName')) {
72            $this->setFriendlyName($xml->getAttribute('FriendlyName'));
73        }
74
75        foreach (Utils::xpQuery($xml, './saml_assertion:AttributeValue') as $av) {
76            $this->addAttributeValue(new AttributeValue($av));
77        }
78    }
79
80
81    /**
82     * Collect the value of the Name-property
83     *
84     * @return string|null
85     */
86    public function getName() : ?string
87    {
88        return $this->Name;
89    }
90
91
92    /**
93     * Set the value of the Name-property
94     *
95     * @param string $name
96     * @return void
97     */
98    public function setName(string $name) : void
99    {
100        $this->Name = $name;
101    }
102
103
104    /**
105     * Collect the value of the NameFormat-property
106     *
107     * @return string|null
108     */
109    public function getNameFormat() : ?string
110    {
111        return $this->NameFormat;
112    }
113
114
115    /**
116     * Set the value of the NameFormat-property
117     *
118     * @param string|null $nameFormat
119     * @return void
120     */
121    public function setNameFormat(string $nameFormat = null) : void
122    {
123        $this->NameFormat = $nameFormat;
124    }
125
126
127    /**
128     * Collect the value of the FriendlyName-property
129     *
130     * @return string|null
131     */
132    public function getFriendlyName() : ?string
133    {
134        return $this->FriendlyName;
135    }
136
137
138    /**
139     * Set the value of the FriendlyName-property
140     *
141     * @param string|null $friendlyName
142     * @return void
143     */
144    public function setFriendlyName(string $friendlyName = null) : void
145    {
146        $this->FriendlyName = $friendlyName;
147    }
148
149
150    /**
151     * Collect the value of the AttributeValue-property
152     *
153     * @return \SAML2\XML\saml\AttributeValue[]
154     */
155    public function getAttributeValue() : array
156    {
157        return $this->AttributeValue;
158    }
159
160
161    /**
162     * Set the value of the AttributeValue-property
163     *
164     * @param array $attributeValue
165     * @return void
166     */
167    public function setAttributeValue(array $attributeValue) : void
168    {
169        $this->AttributeValue = $attributeValue;
170    }
171
172
173    /**
174     * Add the value to the AttributeValue-property
175     *
176     * @param \SAML2\XML\saml\AttributeValue $attributeValue
177     * @return void
178     */
179    public function addAttributeValue(AttributeValue $attributeValue) : void
180    {
181        $this->AttributeValue[] = $attributeValue;
182    }
183
184
185    /**
186     * Internal implementation of toXML.
187     * This function allows RequestedAttribute to specify the element name and namespace.
188     *
189     * @param \DOMElement $parent The element we should append this Attribute to.
190     * @param string $namespace The namespace the element should be created in.
191     * @param string $name The name of the element.
192     * @return \DOMElement
193     */
194    protected function toXMLInternal(DOMElement $parent, string $namespace, string $name) : DOMElement
195    {
196        $e = $parent->ownerDocument->createElementNS($namespace, $name);
197        $parent->appendChild($e);
198
199        if (empty($this->Name)) {
200            throw new \Exception('Cannot convert Attribute to XML with no Name set.');
201        }
202        $e->setAttribute('Name', $this->Name);
203
204        if ($this->NameFormat !== null) {
205            $e->setAttribute('NameFormat', $this->NameFormat);
206        }
207
208        if ($this->FriendlyName !== null) {
209            $e->setAttribute('FriendlyName', $this->FriendlyName);
210        }
211
212        foreach ($this->AttributeValue as $av) {
213            $av->toXML($e);
214        }
215
216        return $e;
217    }
218
219
220    /**
221     * Convert this Attribute to XML.
222     *
223     * @param \DOMElement $parent The element we should append this Attribute to.
224     * @return \DOMElement
225     */
226    public function toXML(DOMElement $parent) : \DOMElement
227    {
228        return $this->toXMLInternal($parent, Constants::NS_SAML, 'saml:Attribute');
229    }
230}
231