Passed
Push — master ( 66592a...152b2f )
by Tim
02:08
created

ContactPerson::processArrayContents()   B

Complexity

Conditions 11
Paths 128

Size

Total Lines 70
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 11
eloc 43
nc 128
nop 1
dl 0
loc 70
rs 7.0833
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\md;
6
7
use DOMDocument;
8
use DOMElement;
9
use Exception;
10
use SimpleSAML\Assert\Assert;
11
use SimpleSAML\SAML2\Exception\ArrayValidationException;
12
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
13
use SimpleSAML\SAML2\Utils\XPath;
14
use SimpleSAML\SAML2\XML\ExtendableElementTrait;
15
use SimpleSAML\XML\ArrayizableElementInterface;
16
use SimpleSAML\XML\Attribute as XMLAttribute;
17
use SimpleSAML\XML\Constants as C;
18
use SimpleSAML\XML\Exception\InvalidDOMElementException;
19
use SimpleSAML\XML\Exception\TooManyElementsException;
20
use SimpleSAML\XML\ExtendableAttributesTrait;
21
use SimpleSAML\XML\SerializableElementInterface;
22
use SimpleSAML\XML\Utils as XMLUtils;
23
24
use function array_filter;
25
use function array_change_key_case;
26
use function array_key_exists;
27
use function array_keys;
28
use function array_map;
29
use function array_pop;
30
use function count;
31
use function filter_var;
32
use function preg_replace;
33
use function var_export;
34
35
/**
36
 * Class representing SAML 2 ContactPerson.
37
 *
38
 * @package simplesamlphp/saml2
39
 */
40
final class ContactPerson extends AbstractMdElement implements ArrayizableElementInterface
41
{
42
    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: $localName, $nodeValue, $namespaceURI, $prefix, $attributes
Loading history...
43
    use ExtendableElementTrait;
44
45
    /** The namespace-attribute for the xs:anyAttribute element */
46
    public const XS_ANY_ATTR_NAMESPACE = C::XS_ANY_NS_OTHER;
47
48
49
    /**
50
     * The several different contact types as defined per specification
51
     */
52
    public const CONTACT_TYPES = [
53
        'technical',
54
        'support',
55
        'administrative',
56
        'billing',
57
        'other',
58
    ];
59
60
61
    /**
62
     * ContactPerson constructor.
63
     *
64
     * @param string $contactType
65
     * @param \SimpleSAML\SAML2\XML\md\Company|null $company
66
     * @param \SimpleSAML\SAML2\XML\md\GivenName|null $givenName
67
     * @param \SimpleSAML\SAML2\XML\md\SurName|null $surName
68
     * @param \SimpleSAML\SAML2\XML\md\Extensions|null $extensions
69
     * @param \SimpleSAML\SAML2\XML\md\EmailAddress[] $emailAddress
70
     * @param \SimpleSAML\SAML2\XML\md\TelephoneNumber[] $telephoneNumber
71
     * @param list<\SimpleSAML\XML\Attribute> $namespacedAttribute
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\md\list 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...
72
     */
73
    public function __construct(
74
        protected string $contactType,
75
        protected ?Company $company = null,
76
        protected ?GivenName $givenName = null,
77
        protected ?SurName $surName = null,
78
        ?Extensions $extensions = null,
79
        protected array $emailAddress = [],
80
        protected array $telephoneNumber = [],
81
        array $namespacedAttribute = [],
82
    ) {
83
        Assert::oneOf($contactType, self::CONTACT_TYPES);
84
        Assert::allIsInstanceOf($emailAddress, EmailAddress::class);
85
        Assert::allIsInstanceOf($telephoneNumber, TelephoneNumber::class);
86
87
        $this->setExtensions($extensions);
88
        $this->setAttributesNS($namespacedAttribute);
89
    }
90
91
92
    /**
93
     * Collect the value of the contactType-property
94
     *
95
     * @return string
96
     */
97
    public function getContactType(): string
98
    {
99
        return $this->contactType;
100
    }
101
102
103
    /**
104
     * Collect the value of the Company-property
105
     *
106
     * @return \SimpleSAML\SAML2\XML\md\Company|null
107
     */
108
    public function getCompany(): ?Company
109
    {
110
        return $this->company;
111
    }
112
113
114
    /**
115
     * Collect the value of the GivenName-property
116
     *
117
     * @return \SimpleSAML\SAML2\XML\md\GivenName|null
118
     */
119
    public function getGivenName(): ?GivenName
120
    {
121
        return $this->givenName;
122
    }
123
124
125
    /**
126
     * Collect the value of the SurName-property
127
     *
128
     * @return \SimpleSAML\SAML2\XML\md\SurName|null
129
     */
130
    public function getSurName(): ?SurName
131
    {
132
        return $this->surName;
133
    }
134
135
136
    /**
137
     * Collect the value of the EmailAddress-property.
138
     *
139
     * @return \SimpleSAML\SAML2\XML\md\EmailAddress[]
140
     */
141
    public function getEmailAddress(): array
142
    {
143
        return $this->emailAddress;
144
    }
145
146
147
    /**
148
     * Collect the value of the TelephoneNumber property
149
     *
150
     * @return \SimpleSAML\SAML2\XML\md\TelephoneNumber[]
151
     */
152
    public function getTelephoneNumber(): array
153
    {
154
        return $this->telephoneNumber;
155
    }
156
157
158
    /**
159
     * Initialize a ContactPerson element.
160
     *
161
     * @param \DOMElement $xml The XML element we should load.
162
     * @return static
163
     *
164
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
165
     *   if the qualified name of the supplied element is wrong
166
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
167
     *   if the supplied element is missing one of the mandatory attributes
168
     * @throws \SimpleSAML\XML\Exception\TooManyElementsException
169
     *   if too many child-elements of a type are specified
170
     */
171
    public static function fromXML(DOMElement $xml): static
172
    {
173
        Assert::same($xml->localName, 'ContactPerson', InvalidDOMElementException::class);
174
        Assert::same($xml->namespaceURI, ContactPerson::NS, InvalidDOMElementException::class);
175
176
        $contactType = self::getAttribute($xml, 'contactType');
177
178
        $company = Company::getChildrenOfClass($xml);
179
        Assert::maxCount($company, 1, 'More than one Company in md:ContactPerson');
180
181
        $givenName = GivenName::getChildrenOfClass($xml);
182
        Assert::maxCount($givenName, 1, 'More than one GivenName in md:ContactPerson');
183
184
        $surName = SurName::getChildrenOfClass($xml);
185
        Assert::maxCount($surName, 1, 'More than one SurName in md:ContactPerson');
186
187
        $email = EmailAddress::getChildrenOfClass($xml);
188
        $telephone = TelephoneNumber::getChildrenOfClass($xml);
189
190
        $extensions = Extensions::getChildrenOfClass($xml);
191
        Assert::maxCount($extensions, 1, 'Only one md:Extensions element is allowed.', TooManyElementsException::class);
192
193
        return new static(
194
            $contactType,
195
            array_pop($company),
196
            array_pop($givenName),
197
            array_pop($surName),
198
            (count($extensions) === 1) ? $extensions[0] : null,
199
            $email,
200
            $telephone,
201
            self::getAttributesNSFromXML($xml),
202
        );
203
    }
204
205
206
    /**
207
     * Convert this ContactPerson to XML.
208
     *
209
     * @param \DOMElement|null $parent The element we should add this contact to.
210
     *
211
     * @return \DOMElement The new ContactPerson-element.
212
     */
213
    public function toXML(DOMElement $parent = null): DOMElement
214
    {
215
        $e = $this->instantiateParentElement($parent);
216
217
        $e->setAttribute('contactType', $this->getContactType());
218
219
        foreach ($this->getAttributesNS() as $attr) {
220
            $attr->toXML($e);
221
        }
222
223
        $this->getExtensions()?->toXML($e);
224
        $this->getCompany()?->toXML($e);
225
        $this->getGivenName()?->toXML($e);
226
        $this->getSurName()?->toXML($e);
227
228
        foreach ($this->getEmailAddress() as $mail) {
229
            $mail->toXML($e);
230
        }
231
232
        foreach ($this->getTelephoneNumber() as $telephone) {
233
            $telephone->toXML($e);
234
        }
235
236
        return $e;
237
    }
238
239
240
    /**
241
     * Create a class from an array
242
     *
243
     * @param array $data
244
     * @return static
245
     */
246
    public static function fromArray(array $data): static
247
    {
248
        $data = self::processArrayContents($data);
249
250
        return new static(
251
            $data['contactType'],
252
            $data['Company'] ?? null,
253
            $data['GivenName'] ?? null,
254
            $data['SurName'] ?? null,
255
            $data['Extensions'] ?? null,
256
            $data['EmailAddress'] ?? [],
257
            $data['TelephoneNumber'] ?? [],
258
            $data['attributes'] ?? null,
0 ignored issues
show
Bug introduced by
It seems like $data['attributes'] ?? null can also be of type null; however, parameter $namespacedAttribute of SimpleSAML\SAML2\XML\md\...ctPerson::__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

258
            /** @scrutinizer ignore-type */ $data['attributes'] ?? null,
Loading history...
259
        );
260
    }
261
262
263
    /**
264
     * Validates an array representation of this object and returns the same array with
265
     * rationalized keys (casing) and parsed sub-elements.
266
     *
267
     * @param array $data
268
     * @return array $data
269
     */
270
    private static function processArrayContents(array $data): array
271
    {
272
        $data = array_change_key_case($data, CASE_LOWER);
273
274
        // Make sure the array keys are known for this kind of object
275
        Assert::allOneOf(
276
            array_keys($data),
277
            [
278
                'contacttype',
279
                'company',
280
                'givenname',
281
                'surname',
282
                'emailaddress',
283
                'telephonenumber',
284
                'extensions',
285
                'attributes',
286
            ],
287
            ArrayValidationException::class,
288
        );
289
290
        Assert::keyExists($data, 'contacttype', ArrayValidationException::class);
291
        Assert::string($data['contacttype'], ArrayValidationException::class);
292
293
        $retval = ['contactType' => $data['contacttype']];
294
295
        if (array_key_exists('company', $data)) {
296
            Assert::string($data['company'], ArrayValidationException::class);
297
            $retval['Company'] = new Company($data['company']);
298
        }
299
300
        if (array_key_exists('givenname', $data)) {
301
            Assert::string($data['givenname'], ArrayValidationException::class);
302
            $retval['GivenName'] = new GivenName($data['givenname']);
303
        }
304
305
        if (array_key_exists('surname', $data)) {
306
            Assert::string($data['surname'], ArrayValidationException::class);
307
            $retval['SurName'] = new SurName($data['surname']);
308
        }
309
310
        if (array_key_exists('emailaddress', $data)) {
311
            Assert::isArray($data['emailaddress'], ArrayValidationException::class);
312
            Assert::allString($data['emailaddress'], ArrayValidationException::class);
313
            foreach ($data['emailaddress'] as $email) {
314
                $retval['EmailAddress'][] = new EmailAddress($email);
315
            }
316
        }
317
318
        if (array_key_exists('telephonenumber', $data)) {
319
            Assert::isArray($data['telephonenumber'], ArrayValidationException::class);
320
            Assert::allString($data['telephonenumber'], ArrayValidationException::class);
321
            foreach ($data['telephonenumber'] as $telephone) {
322
                $retval['TelephoneNumber'][] = new TelephoneNumber($telephone);
323
            }
324
        }
325
326
        if (array_key_exists('extensions', $data)) {
327
            Assert::isArray($data['extensions'], ArrayValidationException::class);
328
            $retval['Extensions'] = new Extensions($data['extensions']);
329
        }
330
331
        if (array_key_exists('attributes', $data)) {
332
            Assert::isArray($data['attributes'], ArrayValidationException::class);
333
            Assert::allIsArray($data['attributes'], ArrayValidationException::class);
334
            foreach ($data['attributes'] as $i => $attr) {
335
                $retval['attributes'][] = XMLAttribute::fromArray($attr);
336
            }
337
        }
338
339
        return $retval;
340
    }
341
342
343
    /**
344
     * Create an array from this class
345
     *
346
     * @return array
347
     */
348
    public function toArray(): array
349
    {
350
        $data = [
351
            'ContactType' => $this->getContactType(),
352
            'Company' => $this->getCompany()?->getContent(),
353
            'GivenName' => $this->getGivenName()?->getContent(),
354
            'SurName' => $this->getSurName()?->getContent(),
355
            'EmailAddress' => [],
356
            'TelephoneNumber' => [],
357
            'Extensions' => $this?->Extensions->getList(),
0 ignored issues
show
Bug introduced by
The method getList() does not exist on SimpleSAML\XML\AbstractElement. It seems like you code against a sub-type of SimpleSAML\XML\AbstractElement such as SimpleSAML\SAML2\XML\md\Extensions or SimpleSAML\SAML2\XML\samlp\Extensions. ( Ignorable by Annotation )

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

357
            'Extensions' => $this?->Extensions->/** @scrutinizer ignore-call */ getList(),
Loading history...
Bug introduced by
The method getList() 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

357
            'Extensions' => $this?->Extensions->/** @scrutinizer ignore-call */ getList(),

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...
358
            'attributes' => [],
359
        ];
360
361
        foreach ($this->getEmailAddress() as $mail) {
362
            $data['EmailAddress'] = array_merge($data['EmailAddress'], $mail->toArray());
363
        }
364
365
        foreach ($this->getTelephoneNumber() as $telephone) {
366
            $data['TelephoneNumber'] = array_merge($data['TelephoneNumber'], $telephone->toArray());
367
        }
368
369
        foreach ($this->getAttributesNS() as $attr) {
370
            $data['attributes'][] = $attr->toArray();
371
        }
372
373
        return array_filter($data);
374
    }
375
}
376