Passed
Pull Request — master (#267)
by Tim
07:30
created

ContactPerson::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 18
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 8
nc 1
nop 8
dl 0
loc 18
rs 10
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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 string[]
68
     */
69
    protected array $EmailAddresses = [];
70
71
    /**
72
     * The TelephoneNumbers of this contact.
73
     *
74
     * @var string[]
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 string[]                                  $email
88
     * @param string[]                                  $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
     * Collect the value of the contactType-property
114
     *
115
     * @return string
116
     */
117
    public function getContactType(): string
118
    {
119
        return $this->contactType;
120
    }
121
122
123
    /**
124
     * Set the value of the contactType-property
125
     *
126
     * @param string $contactType
127
     * @throws \SimpleSAML\Assert\AssertionFailedException if $contactType is not one of the predefined values
128
     */
129
    protected function setContactType(string $contactType): void
130
    {
131
        Assert::oneOf($contactType, ['technical', 'support', 'administrative', 'billing', 'other']);
132
        $this->contactType = $contactType;
133
    }
134
135
136
    /**
137
     * Collect the value of the Company-property
138
     *
139
     * @return \SimpleSAML\SAML2\XML\md\Company|null
140
     */
141
    public function getCompany(): ?Company
142
    {
143
        return $this->Company;
144
    }
145
146
147
    /**
148
     * Set the value of the Company-property
149
     *
150
     * @param \SimpleSAML\SAML2\XML\md\Company|null $company
151
     */
152
    protected function setCompany(?Company $company): void
153
    {
154
        $this->Company = $company;
155
    }
156
157
158
    /**
159
     * Collect the value of the GivenName-property
160
     *
161
     * @return \SimpleSAML\SAML2\XML\md\GivenName|null
162
     */
163
    public function getGivenName(): ?GivenName
164
    {
165
        return $this->GivenName;
166
    }
167
168
169
    /**
170
     * Set the value of the GivenName-property
171
     *
172
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null $givenName
173
     */
174
    protected function setGivenName(?GivenName $givenName): void
175
    {
176
        $this->GivenName = $givenName;
177
    }
178
179
180
    /**
181
     * Collect the value of the SurName-property
182
     *
183
     * @return \SimpleSAML\SAML2\XML\md\SurName|null
184
     */
185
    public function getSurName(): ?SurName
186
    {
187
        return $this->SurName;
188
    }
189
190
191
    /**
192
     * Set the value of the SurName-property
193
     *
194
     * @param \SimpleSAML\SAML2\XML\md\SurName|null $surName
195
     */
196
    protected function setSurName(?SurName $surName): void
197
    {
198
        $this->SurName = $surName;
199
    }
200
201
    /**
202
     * Collect the value of the EmailAddress-property.
203
     *
204
     * @return string[]
205
     */
206
    public function getEmailAddresses(): array
207
    {
208
        return $this->EmailAddresses;
209
    }
210
211
    /**
212
     * Remove a "mailto:" prefix on an email address, if present.
213
     * Check the address for syntactical validity. If not, throw an exception.
214
     *
215
     * @param string $emailAddress
216
     * @return string
217
     * @throws \InvalidArgumentException if supplied email address is not valid
218
     */
219
    private function validateEmailAddress(string $emailAddress): string
220
    {
221
        $address = preg_replace('/^mailto:/i', '', $emailAddress);
222
        if (filter_var($address, FILTER_VALIDATE_EMAIL) === false) {
223
            throw new InvalidArgumentException("Invalid email address for ContactPerson: " . var_export($address, true));
224
        }
225
        return $address;
226
    }
227
228
    /**
229
     * Set the value of the EmailAddress-property
230
     *
231
     * @param string[] $emailAddresses
232
     * @throws \SimpleSAML\Assert\AssertionFailedException
233
     */
234
    protected function setEmailAddresses(array $emailAddresses): void
235
    {
236
        $addresses = array_map([$this, 'validateEmailAddress'], $emailAddresses);
237
        Assert::allEmail($addresses, 'Invalid email addresses found.');
238
        $this->EmailAddresses = $addresses;
239
    }
240
241
242
    /**
243
     * Collect the value of the TelephoneNumber property
244
     *
245
     * @return string[]
246
     */
247
    public function getTelephoneNumbers(): array
248
    {
249
        return $this->TelephoneNumbers;
250
    }
251
252
253
    /**
254
     * Set the value of the TelephoneNumber property
255
     *
256
     * @param string[] $telephoneNumbers
257
     * @throws \SimpleSAML\Assert\AssertionFailedException
258
     */
259
    protected function setTelephoneNumbers(array $telephoneNumbers): void
260
    {
261
        Assert::allString($telephoneNumbers, 'Incorrect type for telephone number.');
262
        $this->TelephoneNumbers = $telephoneNumbers;
263
    }
264
265
266
    /**
267
     * Initialize a ContactPerson element.
268
     *
269
     * @param \DOMElement $xml The XML element we should load.
270
     * @return self
271
     *
272
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
273
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
274
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
275
     */
276
    public static function fromXML(DOMElement $xml): object
277
    {
278
        Assert::same($xml->localName, 'ContactPerson', InvalidDOMElementException::class);
279
        Assert::same($xml->namespaceURI, ContactPerson::NS, InvalidDOMElementException::class);
280
281
        $contactType = self::getAttribute($xml, 'contactType');
282
283
        $company = Company::getChildrenOfClass($xml);
284
        Assert::maxCount($company, 1, 'More than one Company in md:ContactPerson');
285
286
        $givenName = GivenName::getChildrenOfClass($xml);
287
        Assert::maxCount($givenName, 1, 'More than one GivenName in md:ContactPerson');
288
289
        $surName = SurName::getChildrenOfClass($xml);
290
        Assert::maxCount($surName, 1, 'More than one SurName in md:ContactPerson');
291
292
        $email = EmailAddress::getChildrenOfClass($xml);
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\md\EmailAddress was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
293
        $telephone = TelephoneNumber::getChildrenOfClass($xml);
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\md\TelephoneNumber was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
294
        $extensions = Extensions::getChildrenOfClass($xml);
295
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
296
297
        return new self(
298
            $contactType,
299
            array_pop($company),
300
            array_pop($givenName),
301
            array_pop($surName),
302
            (count($extensions) === 1) ? $extensions[0] : null,
303
            $email,
304
            $telephone,
305
            self::getAttributesNSFromXML($xml)
306
        );
307
    }
308
309
310
    /**
311
     * Convert this ContactPerson to XML.
312
     *
313
     * @param \DOMElement|null $parent The element we should add this contact to.
314
     *
315
     * @return \DOMElement The new ContactPerson-element.
316
     */
317
    public function toXML(DOMElement $parent = null): DOMElement
318
    {
319
        $e = $this->instantiateParentElement($parent);
320
321
        $e->setAttribute('contactType', $this->contactType);
322
323
        foreach ($this->getAttributesNS() as $attr) {
324
            $e->setAttributeNS($attr['namespaceURI'], $attr['qualifiedName'], $attr['value']);
325
        }
326
327
        if ($this->Extensions !== null) {
328
            $this->Extensions->toXML($e);
329
        }
330
331
        if ($this->Company !== null) {
332
            $this->Company->toXML($e);
333
        }
334
335
        if ($this->GivenName !== null) {
336
            $this->GivenName->toXML($e);
337
        }
338
        if ($this->SurName !== null) {
339
            $this->SurName->toXML($e);
340
        }
341
342
        $addresses = preg_filter('/^/', 'mailto:', $this->EmailAddresses);
343
        XMLUtils::addStrings($e, Constants::NS_MD, 'md:EmailAddress', false, $addresses);
0 ignored issues
show
Bug introduced by
It seems like $addresses can also be of type null and string; however, parameter $values of SimpleSAML\XML\Utils::addStrings() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

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

343
        XMLUtils::addStrings($e, Constants::NS_MD, 'md:EmailAddress', false, /** @scrutinizer ignore-type */ $addresses);
Loading history...
344
345
        XMLUtils::addStrings($e, Constants::NS_MD, 'md:TelephoneNumber', false, $this->TelephoneNumbers);
346
347
        return $e;
348
    }
349
350
351
    /**
352
     * Create a class from an array
353
     *
354
     * @param array $data
355
     * @return self
356
     */
357
    public static function fromArray(array $data): object
358
    {
359
        Assert::keyExists($data, 'ContactType');
360
361
        $ContactType = $data['ContactType'];
362
        $Company = isset($data['Company']) ? new Company($data['Company']) : null;
363
        $GivenName = isset($data['GivenName']) ? new GivenName($data['GivenName']) : null;
364
        $SurName = isset($data['SurName']) ? new SurName($data['SurName']) : null;
365
        $Extensions = $data['Extensions'] ?? null;
366
        $EmailAddresses = $data['EmailAddresses'] ?? [];
367
        $TelephoneNumbers = $data['TelephoneNumbers'] ?? [];
368
369
        // Anything after this should be (namespaced) attributes
370
        unset(
371
            $data['ContactType'],
372
            $data['Company'],
373
            $data['GivenName'],
374
            $data['SurName'],
375
            $data['Extensions'],
376
            $data['EmailAddresses'],
377
            $data['TelephoneNumbers']
378
        );
379
380
        $attributes = [];
381
        foreach ($data as $ns => $attribute) {
382
            $name = array_key_first($attribute);
383
            $value = $attribute[$name];
384
385
            $doc = DOMDocumentFactory::create();
386
            $elt = $doc->createElement("placeholder");
387
            $elt->setAttributeNS($ns, $name, $value);
388
389
            $attributes[] = $elt->getAttributeNode($name);
390
        }
391
392
        return new self(
393
            $ContactType,
394
            $Company,
395
            $GivenName,
396
            $SurName,
397
            $Extensions,
398
            $EmailAddresses,
399
            $TelephoneNumbers,
400
            $attributes
401
        );
402
    }
403
404
405
    /**
406
     * Create an array from this class
407
     *
408
     * @return array
409
     */
410
    public function toArray(): array
411
    {
412
        $data = [
413
            'ContactType' => $this->contactType,
414
            '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

414
            '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...
415
            '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

415
            '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...
416
            '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

416
            '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...
417
            'EmailAddresses' => $this->EmailAddresses,
418
            'TelephoneNumbers' => $this->TelephoneNumbers,
419
            'Extensions' => $this->Extensions,
420
        ];
421
422
        foreach ($this->getAttributesNS() as $a) {
423
            $data[$a['namespaceURI']] = [$a['qualifiedName'] => $a['value']];
424
        }
425
426
        return $data;
427
    }
428
}
429