Passed
Pull Request — master (#276)
by Tim
06:47 queued 04:32
created

ContactPerson::setContactType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMElement;
8
use Exception;
9
use InvalidArgumentException;
10
use SimpleSAML\Assert\Assert;
11
use SimpleSAML\SAML2\Constants;
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;
1 ignored issue
show
introduced by
The trait SimpleSAML\XML\ExtendableAttributesTrait requires some properties which are not provided by SimpleSAML\SAML2\XML\md\ContactPerson: $namespaceURI, $nodeName, $attributes, $value
Loading history...
35
36
    /**
37
     * The contact type.
38
     *
39
     * @var string
40
     */
41
    protected string $contactType;
42
43
    /**
44
     * The Company of this contact.
45
     *
46
     * @var \SimpleSAML\SAML2\XML\md\Company|null
47
     */
48
    protected ?Company $Company = null;
49
50
    /**
51
     * The GivenName of this contact.
52
     *
53
     * @var \SimpleSAML\SAML2\XML\md\GivenName|null
54
     */
55
    protected ?GivenName $GivenName = null;
56
57
    /**
58
     * The SurName of this contact.
59
     *
60
     * @var \SimpleSAML\SAML2\XML\md\SurName|null
61
     */
62
    protected ?SurName $SurName = null;
63
64
    /**
65
     * The EmailAddresses of this contact.
66
     *
67
     * @var \SimpleSAML\SAML2\XML\md\EmailAddress[]
68
     */
69
    protected array $EmailAddresses = [];
70
71
    /**
72
     * The TelephoneNumbers of this contact.
73
     *
74
     * @var \SimpleSAML\SAML2\XML\md\TelephoneNumber[]
75
     */
76
    protected array $TelephoneNumbers = [];
77
78
79
    /**
80
     * ContactPerson constructor.
81
     *
82
     * @param string                                      $contactType
83
     * @param \SimpleSAML\SAML2\XML\md\Company|null       $company
84
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null     $givenName
85
     * @param \SimpleSAML\SAML2\XML\md\SurName|null       $surName
86
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null    $extensions
87
     * @param \SimpleSAML\SAML2\XML\md\EmailAddress[]     $email
88
     * @param \SimpleSAML\SAML2\XML\md\TelephoneNumber[]  $telephone
89
     * @param \DOMAttr[]                                  $namespacedAttributes
90
     */
91
    public function __construct(
92
        string $contactType,
93
        ?Company $company = null,
94
        ?GivenName $givenName = null,
95
        ?SurName $surName = null,
96
        ?Extensions $extensions = null,
97
        array $email = [],
98
        array $telephone = [],
99
        array $namespacedAttributes = []
100
    ) {
101
        $this->setContactType($contactType);
102
        $this->setCompany($company);
103
        $this->setGivenName($givenName);
104
        $this->setSurName($surName);
105
        $this->setEmailAddresses($email);
106
        $this->setTelephoneNumbers($telephone);
107
        $this->setExtensions($extensions);
108
        $this->setAttributesNS($namespacedAttributes);
109
    }
110
111
112
    /**
113
     * Retrieve the value of a child \DOMElements as an array of strings.
114
     *
115
     * @param \DOMElement $parent The parent element.
116
     * @param string      $name The name of the child elements.
117
     *
118
     * @return string[]   The value of the child elements.
119
     */
120
    private static function getStringElements(DOMElement $parent, string $name): array
121
    {
122
        $e = XMLUtils::xpQuery($parent, './saml_metadata:' . $name);
123
124
        $ret = [];
125
        foreach ($e as $i) {
126
            $ret[] = $i->textContent;
127
        }
128
129
        return $ret;
130
    }
131
132
133
    /**
134
     * Retrieve the value of a child \DOMElement as a string.
135
     *
136
     * @param \DOMElement $parent The parent element.
137
     * @param string      $name The name of the child element.
138
     *
139
     * @return string|null The value of the child element.
140
     * @throws \SimpleSAML\Assert\AssertionFailedException
141
     */
142
    private static function getStringElement(DOMElement $parent, string $name): ?string
0 ignored issues
show
Unused Code introduced by
The method getStringElement() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
143
    {
144
        $e = self::getStringElements($parent, $name);
145
        if (empty($e)) {
146
            return null;
147
        }
148
149
        Assert::maxCount($e, 1, 'More than one ' . $name . ' in ' . $parent->tagName);
150
        return $e[0];
151
    }
152
153
154
    /**
155
     * Collect the value of the contactType-property
156
     *
157
     * @return string
158
     */
159
    public function getContactType(): string
160
    {
161
        return $this->contactType;
162
    }
163
164
165
    /**
166
     * Set the value of the contactType-property
167
     *
168
     * @param string $contactType
169
     * @throws \SimpleSAML\Assert\AssertionFailedException if $contactType is not one of the predefined values
170
     */
171
    protected function setContactType(string $contactType): void
172
    {
173
        Assert::oneOf($contactType, ['technical', 'support', 'administrative', 'billing', 'other']);
174
        $this->contactType = $contactType;
175
    }
176
177
178
    /**
179
     * Collect the value of the Company-property
180
     *
181
     * @return \SimpleSAML\SAML2\XML\md\Company|null
182
     */
183
    public function getCompany(): ?Company
184
    {
185
        return $this->Company;
186
    }
187
188
189
    /**
190
     * Set the value of the Company-property
191
     *
192
     * @param \SimpleSAML\SAML2\XML\md\Company|null $company
193
     */
194
    protected function setCompany(?Company $company): void
195
    {
196
        $this->Company = $company;
197
    }
198
199
200
    /**
201
     * Collect the value of the GivenName-property
202
     *
203
     * @return \SimpleSAML\SAML2\XML\md\GivenName|null
204
     */
205
    public function getGivenName(): ?GivenName
206
    {
207
        return $this->GivenName;
208
    }
209
210
211
    /**
212
     * Set the value of the GivenName-property
213
     *
214
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null $givenName
215
     */
216
    protected function setGivenName(?GivenName $givenName): void
217
    {
218
        $this->GivenName = $givenName;
219
    }
220
221
222
    /**
223
     * Collect the value of the SurName-property
224
     *
225
     * @return \SimpleSAML\SAML2\XML\md\SurName|null
226
     */
227
    public function getSurName(): ?SurName
228
    {
229
        return $this->SurName;
230
    }
231
232
233
    /**
234
     * Set the value of the SurName-property
235
     *
236
     * @param \SimpleSAML\SAML2\XML\md\SurName|null $surName
237
     */
238
    protected function setSurName(?SurName $surName): void
239
    {
240
        $this->SurName = $surName;
241
    }
242
243
244
    /**
245
     * Collect the value of the EmailAddress-property.
246
     *
247
     * @return \SimpleSAML\SAML2\XML\md\EmailAddress[]
248
     */
249
    public function getEmailAddresses(): array
250
    {
251
        return $this->EmailAddresses;
252
    }
253
254
255
    /**
256
     * Set the value of the EmailAddress-property
257
     *
258
     * @param \SimpleSAML\SAML2\XML\md\EmailAddress[] $emailAddresses
259
     * @throws \SimpleSAML\Assert\AssertionFailedException
260
     */
261
    protected function setEmailAddresses(array $emailAddresses): void
262
    {
263
        Assert::allIsInstanceOf($emailAddresses, EmailAddress::class);
264
        $this->EmailAddresses = $emailAddresses;
265
    }
266
267
268
    /**
269
     * Collect the value of the TelephoneNumber property
270
     *
271
     * @return \SimpleSAML\SAML2\XML\md\TelephoneNumber[]
272
     */
273
    public function getTelephoneNumbers(): array
274
    {
275
        return $this->TelephoneNumbers;
276
    }
277
278
279
    /**
280
     * Set the value of the TelephoneNumber property
281
     *
282
     * @param \SimpleSAML\SAML2\XML\md\TelephoneNumber[] $telephoneNumbers
283
     * @throws \SimpleSAML\Assert\AssertionFailedException
284
     */
285
    protected function setTelephoneNumbers(array $telephoneNumbers): void
286
    {
287
        Assert::allIsInstanceOf($telephoneNumbers, TelephoneNumber::class);
288
        $this->TelephoneNumbers = $telephoneNumbers;
289
    }
290
291
292
    /**
293
     * Initialize a ContactPerson element.
294
     *
295
     * @param \DOMElement $xml The XML element we should load.
296
     * @return self
297
     *
298
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
299
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
300
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
301
     */
302
    public static function fromXML(DOMElement $xml): object
303
    {
304
        Assert::same($xml->localName, 'ContactPerson', InvalidDOMElementException::class);
305
        Assert::same($xml->namespaceURI, ContactPerson::NS, InvalidDOMElementException::class);
306
307
        $contactType = self::getAttribute($xml, 'contactType');
308
309
        $company = Company::getChildrenOfClass($xml);
310
        Assert::maxCount($company, 1, 'More than one Company in md:ContactPerson');
311
312
        $givenName = GivenName::getChildrenOfClass($xml);
313
        Assert::maxCount($givenName, 1, 'More than one GivenName in md:ContactPerson');
314
315
        $surName = SurName::getChildrenOfClass($xml);
316
        Assert::maxCount($surName, 1, 'More than one SurName in md:ContactPerson');
317
318
        $email = EmailAddress::getChildrenOfClass($xml);
319
        $telephone = TelephoneNumber::getChildrenOfClass($xml);
320
321
        $extensions = Extensions::getChildrenOfClass($xml);
322
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
323
324
        return new self(
325
            $contactType,
326
            array_pop($company),
327
            array_pop($givenName),
328
            array_pop($surName),
329
            (count($extensions) === 1) ? $extensions[0] : null,
330
            $email,
331
            $telephone,
332
            self::getAttributesNSFromXML($xml)
333
        );
334
    }
335
336
337
    /**
338
     * Convert this ContactPerson to XML.
339
     *
340
     * @param \DOMElement|null $parent The element we should add this contact to.
341
     *
342
     * @return \DOMElement The new ContactPerson-element.
343
     */
344
    public function toXML(DOMElement $parent = null): DOMElement
345
    {
346
        $e = $this->instantiateParentElement($parent);
347
348
        $e->setAttribute('contactType', $this->contactType);
349
350
        foreach ($this->getAttributesNS() as $attr) {
351
            $e->setAttributeNS($attr['namespaceURI'], $attr['qualifiedName'], $attr['value']);
352
        }
353
354
        if ($this->Extensions !== null) {
355
            $this->Extensions->toXML($e);
356
        }
357
358
        if ($this->Company !== null) {
359
            $this->Company->toXML($e);
360
        }
361
362
        if ($this->GivenName !== null) {
363
            $this->GivenName->toXML($e);
364
        }
365
        if ($this->SurName !== null) {
366
            $this->SurName->toXML($e);
367
        }
368
369
        foreach ($this->EmailAddresses as $mail) {
370
            $mail->toXML($e);
371
        }
372
373
        foreach ($this->TelephoneNumbers as $telephone) {
374
            $telephone->toXML($e);
375
        }
376
377
        return $e;
378
    }
379
380
381
    /**
382
     * Create a class from an array
383
     *
384
     * @param array $data
385
     * @return self
386
     */
387
    public static function fromArray(array $data): object
388
    {
389
        Assert::keyExists($data, 'ContactType');
390
391
        $ContactType = $data['ContactType'];
392
        $Company = isset($data['Company']) ? new Company($data['Company']) : null;
393
        $GivenName = isset($data['GivenName']) ? new GivenName($data['GivenName']) : null;
394
        $SurName = isset($data['SurName']) ? new SurName($data['SurName']) : null;
395
        $Extensions = $data['Extensions'] ?? null;
396
397
        $EmailAddresses = [];
398
        foreach ($data['EmailAddresses'] as $mail) {
399
            $EmailAddresses[] = new EmailAddress($mail);
400
        }
401
402
        $TelephoneNumbers = [];
403
        foreach ($data['TelephoneNumbers'] as $telephone) {
404
            $TelephoneNumbers[] = new TelephoneNumber($telephone);
405
        }
406
407
        // Anything after this should be (namespaced) attributes
408
        unset(
409
            $data['ContactType'],
410
            $data['Company'],
411
            $data['GivenName'],
412
            $data['SurName'],
413
            $data['Extensions'],
414
            $data['EmailAddresses'],
415
            $data['TelephoneNumbers']
416
        );
417
418
        $attributes = [];
419
        foreach ($data as $ns => $attribute) {
420
            $name = array_key_first($attribute);
421
            $value = $attribute[$name];
422
423
            $doc = DOMDocumentFactory::create();
424
            $elt = $doc->createElement("placeholder");
425
            $elt->setAttributeNS($ns, $name, $value);
426
427
            $attributes[] = $elt->getAttributeNode($name);
428
        }
429
430
        return new self(
431
            $ContactType,
432
            $Company,
433
            $GivenName,
434
            $SurName,
435
            $Extensions,
436
            $EmailAddresses,
437
            $TelephoneNumbers,
438
            $attributes
439
        );
440
    }
441
442
443
    /**
444
     * Create an array from this class
445
     *
446
     * @return array
447
     */
448
    public function toArray(): array
449
    {
450
        $data = [
451
            'ContactType' => $this->contactType,
452
            'Company' => $this->Company->getContent(),
0 ignored issues
show
Bug introduced by
The method getContent() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

452
            'Company' => $this->Company->/** @scrutinizer ignore-call */ getContent(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
453
            'GivenName' => $this->GivenName->getContent(),
0 ignored issues
show
Bug introduced by
The method getContent() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

453
            'GivenName' => $this->GivenName->/** @scrutinizer ignore-call */ getContent(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
454
            'SurName' => $this->SurName->getContent(),
0 ignored issues
show
Bug introduced by
The method getContent() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

454
            'SurName' => $this->SurName->/** @scrutinizer ignore-call */ getContent(),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
455
            'EmailAddresses' => $this->EmailAddresses,
456
            'TelephoneNumbers' => $this->TelephoneNumbers,
457
            'EmailAddresses' => [],
458
            'TelephoneNumbers' => [],
459
            'Extensions' => $this->Extensions,
460
        ];
461
462
        foreach ($this->EmailAddresses as $mail) {
463
            $data['EmailAddresses'] = array_merge($data['EmailAddresses'], $mail->toArray());
464
        }
465
466
        foreach ($this->TelephoneNumbers as $telephone) {
467
            $data['TelephoneNumbers'] = array_merge($data['TelephoneNumbers'], $telephone->toArray());
468
        }
469
470
        foreach ($this->getAttributesNS() as $a) {
471
            $data[$a['namespaceURI']] = [$a['qualifiedName'] => $a['value']];
472
        }
473
474
        return $data;
475
    }
476
}
477