Passed
Pull Request — master (#267)
by Tim
04:21
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
/**
20
 * Class representing SAML 2 ContactPerson.
21
 *
22
 * @package simplesamlphp/saml2
23
 */
24
final class ContactPerson extends AbstractMdElement
25
{
26
    use ExtendableElementTrait;
27
    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...
28
29
    /**
30
     * The contact type.
31
     *
32
     * @var string
33
     */
34
    protected string $contactType;
35
36
    /**
37
     * The Company of this contact.
38
     *
39
     * @var \SimpleSAML\SAML2\XML\md\Company|null
40
     */
41
    protected ?Company $Company = null;
42
43
    /**
44
     * The GivenName of this contact.
45
     *
46
     * @var \SimpleSAML\SAML2\XML\md\GivenName|null
47
     */
48
    protected ?GivenName $GivenName = null;
49
50
    /**
51
     * The SurName of this contact.
52
     *
53
     * @var \SimpleSAML\SAML2\XML\md\SurName|null
54
     */
55
    protected ?SurName $SurName = null;
56
57
    /**
58
     * The EmailAddresses of this contact.
59
     *
60
     * @var string[]
61
     */
62
    protected array $EmailAddresses = [];
63
64
    /**
65
     * The TelephoneNumbers of this contact.
66
     *
67
     * @var string[]
68
     */
69
    protected array $TelephoneNumbers = [];
70
71
72
    /**
73
     * ContactPerson constructor.
74
     *
75
     * @param string                                    $contactType
76
     * @param \SimpleSAML\SAML2\XML\md\Company|null     $company
77
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null   $givenName
78
     * @param \SimpleSAML\SAML2\XML\md\SurName|null     $surName
79
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null  $extensions
80
     * @param string[]                                  $email
81
     * @param string[]                                  $telephone
82
     * @param \DOMAttr[]                                $namespacedAttributes
83
     */
84
    public function __construct(
85
        string $contactType,
86
        ?Company $company = null,
87
        ?GivenName $givenName = null,
88
        ?SurName $surName = null,
89
        ?Extensions $extensions = null,
90
        array $email = [],
91
        array $telephone = [],
92
        array $namespacedAttributes = []
93
    ) {
94
        $this->setContactType($contactType);
95
        $this->setCompany($company);
96
        $this->setGivenName($givenName);
97
        $this->setSurName($surName);
98
        $this->setEmailAddresses($email);
99
        $this->setTelephoneNumbers($telephone);
100
        $this->setExtensions($extensions);
101
        $this->setAttributesNS($namespacedAttributes);
102
    }
103
104
105
    /**
106
     * Collect the value of the contactType-property
107
     *
108
     * @return string
109
     */
110
    public function getContactType(): string
111
    {
112
        return $this->contactType;
113
    }
114
115
116
    /**
117
     * Set the value of the contactType-property
118
     *
119
     * @param string $contactType
120
     * @throws \SimpleSAML\Assert\AssertionFailedException if $contactType is not one of the predefined values
121
     */
122
    protected function setContactType(string $contactType): void
123
    {
124
        Assert::oneOf($contactType, ['technical', 'support', 'administrative', 'billing', 'other']);
125
        $this->contactType = $contactType;
126
    }
127
128
129
    /**
130
     * Collect the value of the Company-property
131
     *
132
     * @return \SimpleSAML\SAML2\XML\md\Company|null
133
     */
134
    public function getCompany(): ?Company
135
    {
136
        return $this->Company;
137
    }
138
139
140
    /**
141
     * Set the value of the Company-property
142
     *
143
     * @param \SimpleSAML\SAML2\XML\md\Company|null $company
144
     */
145
    protected function setCompany(?Company $company): void
146
    {
147
        $this->Company = $company;
148
    }
149
150
151
    /**
152
     * Collect the value of the GivenName-property
153
     *
154
     * @return \SimpleSAML\SAML2\XML\md\GivenName|null
155
     */
156
    public function getGivenName(): ?GivenName
157
    {
158
        return $this->GivenName;
159
    }
160
161
162
    /**
163
     * Set the value of the GivenName-property
164
     *
165
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null $givenName
166
     */
167
    protected function setGivenName(?GivenName $givenName): void
168
    {
169
        $this->GivenName = $givenName;
170
    }
171
172
173
    /**
174
     * Collect the value of the SurName-property
175
     *
176
     * @return \SimpleSAML\SAML2\XML\md\SurName|null
177
     */
178
    public function getSurName(): ?SurName
179
    {
180
        return $this->SurName;
181
    }
182
183
184
    /**
185
     * Set the value of the SurName-property
186
     *
187
     * @param \SimpleSAML\SAML2\XML\md\SurName|null $surName
188
     */
189
    protected function setSurName(?SurName $surName): void
190
    {
191
        $this->SurName = $surName;
192
    }
193
194
    /**
195
     * Collect the value of the EmailAddress-property.
196
     *
197
     * @return string[]
198
     */
199
    public function getEmailAddresses(): array
200
    {
201
        return $this->EmailAddresses;
202
    }
203
204
    /**
205
     * Remove a "mailto:" prefix on an email address, if present.
206
     * Check the address for syntactical validity. If not, throw an exception.
207
     *
208
     * @param string $emailAddress
209
     * @return string
210
     * @throws \InvalidArgumentException if supplied email address is not valid
211
     */
212
    private function validateEmailAddress(string $emailAddress): string
213
    {
214
        $address = preg_replace('/^mailto:/i', '', $emailAddress);
215
        if (filter_var($address, FILTER_VALIDATE_EMAIL) === false) {
216
            throw new InvalidArgumentException("Invalid email address for ContactPerson: " . var_export($address, true));
217
        }
218
        return $address;
219
    }
220
221
    /**
222
     * Set the value of the EmailAddress-property
223
     *
224
     * @param string[] $emailAddresses
225
     * @throws \SimpleSAML\Assert\AssertionFailedException
226
     */
227
    protected function setEmailAddresses(array $emailAddresses): void
228
    {
229
        $addresses = array_map([$this, 'validateEmailAddress'], $emailAddresses);
230
        Assert::allEmail($addresses, 'Invalid email addresses found.');
231
        $this->EmailAddresses = $addresses;
232
    }
233
234
235
    /**
236
     * Collect the value of the TelephoneNumber property
237
     *
238
     * @return string[]
239
     */
240
    public function getTelephoneNumbers(): array
241
    {
242
        return $this->TelephoneNumbers;
243
    }
244
245
246
    /**
247
     * Set the value of the TelephoneNumber property
248
     *
249
     * @param string[] $telephoneNumbers
250
     * @throws \SimpleSAML\Assert\AssertionFailedException
251
     */
252
    protected function setTelephoneNumbers(array $telephoneNumbers): void
253
    {
254
        Assert::allString($telephoneNumbers, 'Incorrect type for telephone number.');
255
        $this->TelephoneNumbers = $telephoneNumbers;
256
    }
257
258
259
    /**
260
     * Initialize a ContactPerson element.
261
     *
262
     * @param \DOMElement $xml The XML element we should load.
263
     * @return self
264
     *
265
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException if the qualified name of the supplied element is wrong
266
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException if the supplied element is missing one of the mandatory attributes
267
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException if too many child-elements of a type are specified
268
     */
269
    public static function fromXML(DOMElement $xml): object
270
    {
271
        Assert::same($xml->localName, 'ContactPerson', InvalidDOMElementException::class);
272
        Assert::same($xml->namespaceURI, ContactPerson::NS, InvalidDOMElementException::class);
273
274
        $contactType = self::getAttribute($xml, 'contactType');
275
276
        $company = Company::getChildrenOfClass($xml);
277
        Assert::maxCount($company, 1, 'More than one Company in md:ContactPerson');
278
279
        $givenName = GivenName::getChildrenOfClass($xml);
280
        Assert::maxCount($givenName, 1, 'More than one GivenName in md:ContactPerson');
281
282
        $surName = SurName::getChildrenOfClass($xml);
283
        Assert::maxCount($surName, 1, 'More than one SurName in md:ContactPerson');
284
285
        $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...
286
        $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...
287
        $extensions = Extensions::getChildrenOfClass($xml);
288
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
289
290
        return new self(
291
            $contactType,
292
            array_pop($company),
293
            array_pop($givenName),
294
            array_pop($surName),
295
            (count($extensions) === 1) ? $extensions[0] : null,
296
            $email,
297
            $telephone,
298
            self::getAttributesNSFromXML($xml)
299
        );
300
    }
301
302
303
    /**
304
     * Convert this ContactPerson to XML.
305
     *
306
     * @param \DOMElement|null $parent The element we should add this contact to.
307
     *
308
     * @return \DOMElement The new ContactPerson-element.
309
     */
310
    public function toXML(DOMElement $parent = null): DOMElement
311
    {
312
        $e = $this->instantiateParentElement($parent);
313
314
        $e->setAttribute('contactType', $this->contactType);
315
316
        foreach ($this->getAttributesNS() as $attr) {
317
            $e->setAttributeNS($attr['namespaceURI'], $attr['qualifiedName'], $attr['value']);
318
        }
319
320
        if ($this->Extensions !== null) {
321
            $this->Extensions->toXML($e);
322
        }
323
324
        if ($this->Company !== null) {
325
            $this->Company->toXML($e);
326
        }
327
328
        if ($this->GivenName !== null) {
329
            $this->GivenName->toXML($e);
330
        }
331
        if ($this->SurName !== null) {
332
            $this->SurName->toXML($e);
333
        }
334
335
        $addresses = preg_filter('/^/', 'mailto:', $this->EmailAddresses);
336
        XMLUtils::addStrings($e, Constants::NS_MD, 'md:EmailAddress', false, $addresses);
337
338
        XMLUtils::addStrings($e, Constants::NS_MD, 'md:TelephoneNumber', false, $this->TelephoneNumbers);
339
340
        return $e;
341
    }
342
343
344
    /**
345
     * Create a class from an array
346
     *
347
     * @param array $data
348
     * @return self
349
     */
350
    public static function fromArray(array $data): object
351
    {
352
        Assert::keyExists($data, 'ContactType');
353
354
        $ContactType = $data['ContactType'];
355
        $Company = isset($data['Company']) ? new Company($data['Company']) : null;
356
        $GivenName = isset($data['GivenName']) ? new GivenName($data['GivenName']) : null;
357
        $SurName = isset($data['SurName']) ? new SurName($data['SurName']) : null;
358
        $Extensions = $data['Extensions'] ?? null;
359
        $EmailAddresses = $data['EmailAddresses'] ?? [];
360
        $TelephoneNumbers = $data['TelephoneNumbers'] ?? [];
361
362
        // Anything after this should be (namespaced) attributes
363
        unset(
364
            $data['ContactType'],
365
            $data['Company'],
366
            $data['GivenName'],
367
            $data['SurName'],
368
            $data['Extensions'],
369
            $data['EmailAddresses'],
370
            $data['TelephoneNumbers']
371
        );
372
373
        $attributes = [];
374
        foreach ($data as $ns => $attribute) {
375
            $name = array_key_first($attribute);
376
            $value = $attribute[$name];
377
378
            $doc = DOMDocumentFactory::create();
379
            $elt = $doc->createElement("placeholder");
380
            $elt->setAttributeNS($ns, $name, $value);
381
382
            $attributes[] = $elt->getAttributeNode($name);
383
        }
384
385
        return new self(
386
            $ContactType,
387
            $Company,
388
            $GivenName,
389
            $SurName,
390
            $Extensions,
391
            $EmailAddresses,
392
            $TelephoneNumbers,
393
            $attributes
394
        );
395
    }
396
397
398
    /**
399
     * Create an array from this class
400
     *
401
     * @return array
402
     */
403
    public function toArray(): array
404
    {
405
        $data = [
406
            'ContactType' => $this->contactType,
407
            '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

407
            '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...
408
            '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

408
            '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...
409
            '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

409
            '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...
410
            'EmailAddresses' => $this->EmailAddresses,
411
            'TelephoneNumbers' => $this->TelephoneNumbers,
412
            'Extensions' => $this->Extensions,
413
        ];
414
415
        foreach ($this->getAttributesNS() as $a) {
416
            $data[$a['namespaceURI']] = [$a['qualifiedName'] => $a['value']];
417
        }
418
419
        return $data;
420
    }
421
}
422