Passed
Pull Request — master (#317)
by Tim
12:30
created

ContactPerson   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 407
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 126
dl 0
loc 407
rs 10
c 2
b 0
f 0
wmc 30
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use Exception;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
11
use SimpleSAML\SAML2\Utils\XPath;
12
use SimpleSAML\SAML2\XML\ExtendableElementTrait;
13
use SimpleSAML\XML\DOMDocumentFactory;
14
use SimpleSAML\XML\Exception\InvalidDOMElementException;
15
use SimpleSAML\XML\Exception\TooManyElementsException;
16
use SimpleSAML\XML\ExtendableAttributesTrait;
17
use SimpleSAML\XML\Utils as XMLUtils;
18
19
use function array_map;
20
use function array_pop;
21
use function count;
22
use function filter_var;
23
use function preg_replace;
24
use function var_export;
25
26
/**
27
 * Class representing SAML 2 ContactPerson.
28
 *
29
 * @package simplesamlphp/saml2
30
 */
31
final class ContactPerson extends AbstractMdElement
32
{
33
    use ExtendableElementTrait;
34
    use ExtendableAttributesTrait;
35
36
    /**
37
     * The several different contact types as defined per specification
38
     */
39
    public const CONTACT_TYPES = [
40
        'technical',
41
        'support',
42
        'administrative',
43
        'billing',
44
        'other',
45
    ];
46
47
48
    /**
49
     * ContactPerson constructor.
50
     *
51
     * @param string $contactType
52
     * @param \SimpleSAML\SAML2\XML\md\Company|null $company
53
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null $givenName
54
     * @param \SimpleSAML\SAML2\XML\md\SurName|null $surName
55
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
56
     * @param \SimpleSAML\SAML2\XML\md\EmailAddress[] $emailAddress
57
     * @param \SimpleSAML\SAML2\XML\md\TelephoneNumber[] $telephoneNumber
58
     * @param \DOMAttr[] $namespacedAttribute
59
     */
60
    public function __construct(
61
        protected string $contactType,
62
        protected ?Company $company = null,
63
        protected ?GivenName $givenName = null,
64
        protected ?SurName $surName = null,
65
        ?Extensions $extensions = null,
66
        protected array $emailAddress = [],
67
        protected array $telephoneNumber = [],
68
        array $namespacedAttribute = [],
69
    ) {
70
        Assert::oneOf($contactType, self::CONTACT_TYPES);
71
        Assert::allIsInstanceOf($emailAddress, EmailAddress::class);
72
        Assert::allIsInstanceOf($telephoneNumber, TelephoneNumber::class);
73
74
        $this->setExtensions($extensions);
75
        $this->setAttributesNS($namespacedAttribute);
76
    }
77
78
79
    /**
80
     * Collect the value of the contactType-property
81
     *
82
     * @return string
83
     */
84
    public function getContactType(): string
85
    {
86
        return $this->contactType;
87
    }
88
89
90
    /**
91
     * Collect the value of the Company-property
92
     *
93
     * @return \SimpleSAML\SAML2\XML\md\Company|null
94
     */
95
    public function getCompany(): ?Company
96
    {
97
        return $this->company;
98
    }
99
100
101
    /**
102
     * Collect the value of the GivenName-property
103
     *
104
     * @return \SimpleSAML\SAML2\XML\md\GivenName|null
105
     */
106
    public function getGivenName(): ?GivenName
107
    {
108
        return $this->givenName;
109
    }
110
111
112
    /**
113
     * Collect the value of the SurName-property
114
     *
115
     * @return \SimpleSAML\SAML2\XML\md\SurName|null
116
     */
117
    public function getSurName(): ?SurName
118
    {
119
        return $this->surName;
120
    }
121
122
123
    /**
124
     * Collect the value of the EmailAddress-property.
125
     *
126
     * @return \SimpleSAML\SAML2\XML\md\EmailAddress[]
127
     */
128
    public function getEmailAddress(): array
129
    {
130
        return $this->emailAddress;
131
    }
132
133
134
    /**
135
     * Collect the value of the TelephoneNumber property
136
     *
137
     * @return \SimpleSAML\SAML2\XML\md\TelephoneNumber[]
138
     */
139
    public function getTelephoneNumber(): array
140
    {
141
        return $this->telephoneNumber;
142
    }
143
144
145
    /**
146
     * Initialize a ContactPerson element.
147
     *
148
     * @param \DOMElement $xml The XML element we should load.
149
     * @return self
150
     *
151
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
152
     *   if the qualified name of the supplied element is wrong
153
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
154
     *   if the supplied element is missing one of the mandatory attributes
155
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException
156
     *   if too many child-elements of a type are specified
157
     */
158
    public static function fromXML(DOMElement $xml): static
159
    {
160
        Assert::same($xml->localName, 'ContactPerson', InvalidDOMElementException::class);
161
        Assert::same($xml->namespaceURI, ContactPerson::NS, InvalidDOMElementException::class);
162
163
        $contactType = self::getAttribute($xml, 'contactType');
164
165
        $company = Company::getChildrenOfClass($xml);
166
        Assert::maxCount($company, 1, 'More than one Company in md:ContactPerson');
167
168
        $givenName = GivenName::getChildrenOfClass($xml);
169
        Assert::maxCount($givenName, 1, 'More than one GivenName in md:ContactPerson');
170
171
        $surName = SurName::getChildrenOfClass($xml);
172
        Assert::maxCount($surName, 1, 'More than one SurName in md:ContactPerson');
173
174
        $email = EmailAddress::getChildrenOfClass($xml);
175
        $telephone = TelephoneNumber::getChildrenOfClass($xml);
176
177
        $extensions = Extensions::getChildrenOfClass($xml);
178
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
179
180
        return new static(
181
            $contactType,
182
            array_pop($company),
183
            array_pop($givenName),
184
            array_pop($surName),
185
            (count($extensions) === 1) ? $extensions[0] : null,
186
            $email,
187
            $telephone,
188
            self::getAttributesNSFromXML($xml),
189
        );
190
    }
191
192
193
    /**
194
     * Convert this ContactPerson to XML.
195
     *
196
     * @param \DOMElement|null $parent The element we should add this contact to.
197
     *
198
     * @return \DOMElement The new ContactPerson-element.
199
     */
200
    public function toXML(DOMElement $parent = null): DOMElement
201
    {
202
        $e = $this->instantiateParentElement($parent);
203
204
        $e->setAttribute('contactType', $this->getContactType());
205
206
        foreach ($this->getAttributesNS() as $attr) {
207
            $e->setAttributeNS($attr['namespaceURI'], $attr['qualifiedName'], $attr['value']);
208
        }
209
210
        $this->getExtensions()?->toXML($e);
211
        $this->getCompany()?->toXML($e);
212
        $this->getGivenName()?->toXML($e);
213
        $this->getSurName()?->toXML($e);
214
215
        foreach ($this->getEmailAddress() as $mail) {
216
            $mail->toXML($e);
217
        }
218
219
        foreach ($this->getTelephoneNumber() as $telephone) {
220
            $telephone->toXML($e);
221
        }
222
223
        return $e;
224
    }
225
226
227
    /**
228
     * Create a class from an array
229
     *
230
     * @param array $data
231
     * @return self
232
     */
233
    public static function fromArray(array $data): static
234
    {
235
        Assert::keyExists($data, 'ContactType');
236
237
        $ContactType = $data['ContactType'];
238
        $Company = isset($data['Company']) ? new Company($data['Company']) : null;
239
        $GivenName = isset($data['GivenName']) ? new GivenName($data['GivenName']) : null;
240
        $SurName = isset($data['SurName']) ? new SurName($data['SurName']) : null;
241
        $Extensions = $data['Extensions'] ?? null;
242
243
        $EmailAddress = [];
244
        foreach ($data['EmailAddress'] as $mail) {
245
            $EmailAddress[] = new EmailAddress($mail);
246
        }
247
248
        $TelephoneNumber = [];
249
        foreach ($data['TelephoneNumber'] as $telephone) {
250
            $TelephoneNumber[] = new TelephoneNumber($telephone);
251
        }
252
253
        // Anything after this should be (namespaced) attributes
254
        unset(
255
            $data['ContactType'],
256
            $data['Company'],
257
            $data['GivenName'],
258
            $data['SurName'],
259
            $data['Extensions'],
260
            $data['EmailAddress'],
261
            $data['TelephoneNumber'],
262
        );
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected ')' on line 262 at column 8
Loading history...
263
264
        $attributes = [];
265
        foreach ($data as $ns => $attribute) {
266
            $name = array_key_first($attribute);
267
            $value = $attribute[$name];
268
269
            $doc = DOMDocumentFactory::create();
270
            $elt = $doc->createElement("placeholder");
271
            $elt->setAttributeNS($ns, $name, $value);
272
273
            $attributes[] = $elt->getAttributeNode($name);
274
        }
275
276
        return new static(
277
            $ContactType,
278
            $Company,
279
            $GivenName,
280
            $SurName,
281
            $Extensions,
282
            $EmailAddress,
283
            $TelephoneNumber,
284
            $attributes,
285
        );
286
    }
287
288
289
    /**
290
     * Create an array from this class
291
     *
292
     * @return array
293
     */
294
    public function toArray(): array
295
    {
296
        $data = [
297
            'ContactType' => $this->getContactType(),
298
            'Company' => $this->getCompany()?->getContent(),
299
            'GivenName' => $this->getGivenName()?->getContent(),
300
            'SurName' => $this->getSurName()?->getContent(),
301
            'EmailAddress' => [],
302
            'TelephoneNumber' => [],
303
            'Extensions' => $this->Extensions,
304
        ];
305
306
        foreach ($this->getEmailAddress() as $mail) {
307
            $data['EmailAddress'] = array_merge($data['EmailAddress'], $mail->toArray());
308
        }
309
310
        foreach ($this->getTelephoneNumber() as $telephone) {
311
            $data['TelephoneNumber'] = array_merge($data['TelephoneNumber'], $telephone->toArray());
312
        }
313
314
        /** @psalm-suppress PossiblyNullReference */
315
        foreach ($this->getAttributesNS() as $a) {
316
            $data[$a['namespaceURI']] = [$a['qualifiedName'] => $a['value']];
317
        }
318
319
        return $data;
320
    }
321
}
322