Passed
Push — master ( 6db269...70aff8 )
by Jaime Pérez
02:49
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
c 0
b 0
f 0
nc 1
nop 8
dl 0
loc 18
rs 10

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 SAML2\XML\md;
6
7
use DOMElement;
8
use Exception;
9
use InvalidArgumentException;
10
use SAML2\Constants;
11
use SAML2\Utils;
12
use SAML2\XML\ExtendableAttributesTrait;
13
use SAML2\XML\ExtendableElementTrait;
14
use Webmozart\Assert\Assert;
15
16
/**
17
 * Class representing SAML 2 ContactPerson.
18
 *
19
 * @package simplesamlphp/saml2
20
 */
21
final class ContactPerson extends AbstractMdElement
22
{
23
    use ExtendableElementTrait;
24
    use ExtendableAttributesTrait {
0 ignored issues
show
introduced by
The trait SAML2\XML\ExtendableAttributesTrait requires some properties which are not provided by SAML2\XML\md\ContactPerson: $namespaceURI, $nodeName, $attributes, $value
Loading history...
25
        ExtendableAttributesTrait::setAttributesNS as setAttributesNSConflict;
26
    }
27
28
    /**
29
     * The contact type.
30
     *
31
     * @var string
32
     */
33
    protected $contactType;
34
35
    /**
36
     * The Company of this contact.
37
     *
38
     * @var string|null
39
     */
40
    protected $Company = null;
41
42
    /**
43
     * The GivenName of this contact.
44
     *
45
     * @var string|null
46
     */
47
    protected $GivenName = null;
48
49
    /**
50
     * The SurName of this contact.
51
     *
52
     * @var string|null
53
     */
54
    protected $SurName = null;
55
56
    /**
57
     * The EmailAddresses of this contact.
58
     *
59
     * @var array
60
     */
61
    protected $EmailAddresses = [];
62
63
    /**
64
     * The TelephoneNumbers of this contact.
65
     *
66
     * @var array
67
     */
68
    protected $TelephoneNumbers = [];
69
70
71
    /**
72
     * ContactPerson constructor.
73
     *
74
     * @param string                         $contactType
75
     * @param string|null                    $company
76
     * @param string|null                    $givenName
77
     * @param string|null                    $surName
78
     * @param \SAML2\XML\md\Extensions|null  $extensions
79
     * @param string[]                       $email
80
     * @param string[]                       $telephone
81
     * @param \DOMAttr[]                     $namespacedAttributes
82
     */
83
    public function __construct(
84
        string $contactType,
85
        ?string $company = null,
86
        ?string $givenName = null,
87
        ?string $surName = null,
88
        ?Extensions $extensions = null,
89
        array $email = [],
90
        array $telephone = [],
91
        array $namespacedAttributes = []
92
    ) {
93
        $this->setContactType($contactType);
94
        $this->setCompany($company);
95
        $this->setGivenName($givenName);
96
        $this->setSurName($surName);
97
        $this->setEmailAddresses($email);
98
        $this->setTelephoneNumbers($telephone);
99
        $this->setExtensions($extensions);
100
        $this->setAttributesNS($namespacedAttributes);
101
    }
102
103
104
    /**
105
     * Initialize a ContactPerson element.
106
     *
107
     * @param \DOMElement $xml The XML element we should load.
108
     *
109
     * @return self
110
     * @throws \InvalidArgumentException if the qualified name of the supplied element is wrong
111
     * @throws \InvalidArgumentException if the mandatory contactType attribute is missing
112
     */
113
    public static function fromXML(DOMElement $xml): object
114
    {
115
        Assert::same($xml->localName, 'ContactPerson');
116
        Assert::same($xml->namespaceURI, ContactPerson::NS);
117
        Assert::true($xml->hasAttribute('contactType'), 'Missing contactType on ContactPerson.');
118
119
        $contactType = $xml->getAttribute('contactType');
120
        $company = self::getStringElement($xml, 'Company');
121
        $givenName = self::getStringElement($xml, 'GivenName');
122
        $surName = self::getStringElement($xml, 'SurName');
123
        $email = self::getStringElements($xml, 'EmailAddress');
124
        $telephone = self::getStringElements($xml, 'TelephoneNumber');
125
        $extensions = Extensions::getChildrenOfClass($xml);
126
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.');
127
128
        return new self(
129
            $contactType,
130
            $company,
131
            $givenName,
132
            $surName,
133
            (count($extensions) === 1) ? $extensions[0] : null,
134
            $email,
135
            $telephone,
136
            self::getAttributesNSFromXML($xml)
0 ignored issues
show
Bug introduced by
It seems like self::getAttributesNSFromXML($xml) can also be of type null; however, parameter $namespacedAttributes of SAML2\XML\md\ContactPerson::__construct() 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

136
            /** @scrutinizer ignore-type */ self::getAttributesNSFromXML($xml)
Loading history...
137
        );
138
    }
139
140
141
    /**
142
     * Retrieve the value of a child \DOMElements as an array of strings.
143
     *
144
     * @param \DOMElement $parent The parent element.
145
     * @param string      $name The name of the child elements.
146
     *
147
     * @return string[]   The value of the child elements.
148
     */
149
    private static function getStringElements(DOMElement $parent, string $name): array
150
    {
151
        $e = Utils::xpQuery($parent, './saml_metadata:' . $name);
152
153
        $ret = [];
154
        foreach ($e as $i) {
155
            $ret[] = $i->textContent;
156
        }
157
158
        return $ret;
159
    }
160
161
162
    /**
163
     * Retrieve the value of a child \DOMElement as a string.
164
     *
165
     * @param \DOMElement $parent The parent element.
166
     * @param string      $name The name of the child element.
167
     *
168
     * @return string|null The value of the child element.
169
     * @throws \InvalidArgumentException
170
     */
171
    private static function getStringElement(DOMElement $parent, string $name): ?string
172
    {
173
        $e = self::getStringElements($parent, $name);
174
        if (empty($e)) {
175
            return null;
176
        }
177
178
        Assert::maxCount($e, 1, 'More than one ' . $name . ' in ' . $parent->tagName);
179
        return $e[0];
180
    }
181
182
183
    /**
184
     * Collect the value of the contactType-property
185
     *
186
     * @return string
187
     */
188
    public function getContactType(): string
189
    {
190
        return $this->contactType;
191
    }
192
193
194
    /**
195
     * Set the value of the contactType-property
196
     *
197
     * @param string $contactType
198
     * @return void
199
     * @throws \InvalidArgumentException if $contactType is not one of the predefined values
200
     */
201
    protected function setContactType(string $contactType): void
202
    {
203
        Assert::oneOf($contactType, ['technical', 'support', 'administrative', 'billing', 'other']);
204
        $this->contactType = $contactType;
205
    }
206
207
208
    /**
209
     * Collect the value of the Company-property
210
     *
211
     * @return string|null
212
     */
213
    public function getCompany(): ?string
214
    {
215
        return $this->Company;
216
    }
217
218
219
    /**
220
     * Set the value of the Company-property
221
     *
222
     * @param string|null $company
223
     * @return void
224
     */
225
    protected function setCompany(?string $company): void
226
    {
227
        $this->Company = $company;
228
    }
229
230
231
    /**
232
     * Collect the value of the GivenName-property
233
     *
234
     * @return string|null
235
     */
236
    public function getGivenName(): ?string
237
    {
238
        return $this->GivenName;
239
    }
240
241
242
    /**
243
     * Set the value of the GivenName-property
244
     *
245
     * @param string|null $givenName
246
     * @return void
247
     */
248
    protected function setGivenName(?string $givenName): void
249
    {
250
        $this->GivenName = $givenName;
251
    }
252
253
254
    /**
255
     * Collect the value of the SurName-property
256
     *
257
     * @return string|null
258
     */
259
    public function getSurName(): ?string
260
    {
261
        return $this->SurName;
262
    }
263
264
265
    /**
266
     * Set the value of the SurName-property
267
     *
268
     * @param string|null $surName
269
     * @return void
270
     */
271
    protected function setSurName(?string $surName): void
272
    {
273
        $this->SurName = $surName;
274
    }
275
276
    /**
277
     * Collect the value of the EmailAddress-property.
278
     *
279
     * @return string[]
280
     */
281
    public function getEmailAddresses(): array
282
    {
283
        return $this->EmailAddresses;
284
    }
285
286
    /**
287
     * Remove a "mailto:" prefix on an email address, if present.
288
     * Check the address for syntactical validity. If not, throw an exception.
289
     *
290
     * @param string $emailAddress
291
     * @return string
292
     * @throws \InvalidArgumentException if supplied email address is not valid
293
     */
294
    private function validateEmailAddress(string $emailAddress): string
295
    {
296
        $address = preg_replace('/^mailto:/i', '', $emailAddress);
297
        if (filter_var($address, FILTER_VALIDATE_EMAIL) === false) {
298
            throw new InvalidArgumentException("Invalid email address for ContactPerson: " . var_export($address, true));
299
        }
300
        return $address;
301
    }
302
303
    /**
304
     * Set the value of the EmailAddress-property
305
     *
306
     * @param string[] $emailAddresses
307
     * @return void
308
     * @throws \InvalidArgumentException
309
     */
310
    protected function setEmailAddresses(array $emailAddresses): void
311
    {
312
        $addresses = array_map([$this, 'validateEmailAddress'], $emailAddresses);
313
        Assert::allEmail($addresses, 'Invalid email addresses found.');
314
        $this->EmailAddresses = $addresses;
315
    }
316
317
318
    /**
319
     * Collect the value of the TelephoneNumber property
320
     *
321
     * @return string[]
322
     */
323
    public function getTelephoneNumbers(): array
324
    {
325
        return $this->TelephoneNumbers;
326
    }
327
328
329
    /**
330
     * Set the value of the TelephoneNumber property
331
     *
332
     * @param string[] $telephoneNumbers
333
     * @throws \InvalidArgumentException
334
     */
335
    protected function setTelephoneNumbers(array $telephoneNumbers): void
336
    {
337
        Assert::allString($telephoneNumbers, 'Incorrect type for telephone number.');
338
        $this->TelephoneNumbers = $telephoneNumbers;
339
    }
340
341
342
    /**
343
     * Convert this ContactPerson to XML.
344
     *
345
     * @param \DOMElement|null $parent The element we should add this contact to.
346
     *
347
     * @return \DOMElement The new ContactPerson-element.
348
     */
349
    public function toXML(DOMElement $parent = null): DOMElement
350
    {
351
        $e = $this->instantiateParentElement($parent);
352
353
        $e->setAttribute('contactType', $this->contactType);
354
355
        foreach ($this->getAttributesNS() as $attr) {
356
            $e->setAttributeNS($attr['namespaceURI'], $attr['qualifiedName'], $attr['value']);
357
        }
358
359
        if ($this->Extensions !== null) {
360
            $this->Extensions->toXML($e);
361
        }
362
363
        if ($this->Company !== null) {
364
            Utils::addString($e, Constants::NS_MD, 'md:Company', $this->Company);
365
        }
366
        if ($this->GivenName !== null) {
367
            Utils::addString($e, Constants::NS_MD, 'md:GivenName', $this->GivenName);
368
        }
369
        if ($this->SurName !== null) {
370
            Utils::addString($e, Constants::NS_MD, 'md:SurName', $this->SurName);
371
        }
372
373
        /** @var string[] $addresses */
374
        $addresses = preg_filter('/^/', 'mailto:', $this->EmailAddresses);
375
        Utils::addStrings($e, Constants::NS_MD, 'md:EmailAddress', false, $addresses);
376
377
        Utils::addStrings($e, Constants::NS_MD, 'md:TelephoneNumber', false, $this->TelephoneNumbers);
378
379
        return $e;
380
    }
381
}
382