Passed
Push — feature/issue-274 ( 9874b9...6e730f )
by Mikaël
08:08
created

Struct   F

Complexity

Total Complexity 122

Size/Duplication

Total Lines 658
Duplicated Lines 0 %

Test Coverage

Coverage 97.7%

Importance

Changes 9
Bugs 1 Features 2
Metric Value
eloc 342
dl 0
loc 658
ccs 382
cts 391
cp 0.977
rs 2
c 9
b 1
f 2
wmc 122

41 Methods

Rating   Name   Duplication   Size   Complexity  
B getStructMethodParameter() 0 26 9
A fillClassConstants() 0 2 1
A addStructPropertiesToAnnotationBlockParams() 0 7 2
A getModel() 0 3 1
A addStructMethodsSetAndGetAnnotationBlockFromScalar() 0 15 3
A addStructPropertiesToAnnotationBlockUses() 0 7 2
A getStructMethodsAddToAnnotationBlock() 0 25 3
A addStructMethodAddToBody() 0 17 2
A addStructMethodGet() 0 29 6
A defineUseStatements() 0 7 2
A addStructMethodGetBody() 0 3 1
A addStructMethodSetBodyReturn() 0 8 1
B getStructMethodsValidateMethodAnnotationBlock() 0 59 8
A getModelAttributes() 0 3 1
A addStructMethodSet() 0 9 1
A addStructMethodsGetAnnotationBlockFromXmlAttribute() 0 10 2
A getStructMethodParametersValues() 0 8 2
A addStructMethodConstructBodyForAttribute() 0 6 2
A addStructMethodGetBodyReturn() 0 22 6
A addStructMethodSetBody() 0 10 2
A getStructMethodAnnotationBlock() 0 29 6
A getMethodAnnotationBlock() 0 3 1
B addStructMethodsSetAndGetAnnotationBlockFromStructAttribute() 0 48 11
A fillClassMethods() 0 5 1
A addStructPropertiesToAnnotationBlock() 0 5 1
A addStructMethodsGetAnnotationBlock() 0 5 1
A getStructMethodGetParameters() 0 8 2
A getConstantAnnotationBlock() 0 3 1
A getPropertyAnnotationBlock() 0 14 3
A getStructMethodConstructAnnotationBlock() 0 8 1
A getStructMethodSetBodyAssignment() 0 18 4
A addStructMethodSetBodyAssignment() 0 15 4
A setModel() 0 7 2
A addStructMethodAddTo() 0 16 2
A applyRules() 0 8 2
A addStructMethodConstruct() 0 9 2
B getStructMethodsSetAndGetAnnotationBlock() 0 38 8
A addStructMethodConstructBody() 0 11 3
A addStructMethodsSetAndGet() 0 11 2
A addStructMethodsSetAnnotationBlock() 0 8 1
B fillClassProperties() 0 22 7

How to fix   Complexity   

Complex Class

Complex classes like Struct often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Struct, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace WsdlToPhp\PackageGenerator\File;
6
7
use InvalidArgumentException;
8
use WsdlToPhp\PackageGenerator\Container\Model\StructAttribute as StructAttributeContainer;
9
use WsdlToPhp\PackageGenerator\Container\PhpElement\Constant as ConstantContainer;
10
use WsdlToPhp\PackageGenerator\Container\PhpElement\Property as PropertyContainer;
11
use WsdlToPhp\PackageGenerator\File\Element\PhpFunctionParameter;
12
use WsdlToPhp\PackageGenerator\File\Validation\ArrayRule;
13
use WsdlToPhp\PackageGenerator\File\Validation\ChoiceRule;
14
use WsdlToPhp\PackageGenerator\File\Validation\LengthRule;
15
use WsdlToPhp\PackageGenerator\File\Validation\MaxLengthRule;
16
use WsdlToPhp\PackageGenerator\File\Validation\MinLengthRule;
17
use WsdlToPhp\PackageGenerator\File\Validation\PatternRule;
18
use WsdlToPhp\PackageGenerator\File\Validation\Rules;
19
use WsdlToPhp\PackageGenerator\File\Validation\UnionRule;
20
use WsdlToPhp\PackageGenerator\Model\AbstractModel;
21
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
22
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
23
use WsdlToPhp\PhpGenerator\Element\AccessRestrictedElementInterface;
24
use WsdlToPhp\PhpGenerator\Element\AssignedValueElementInterface;
25
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
26 140
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
27
use WsdlToPhp\PhpGenerator\Element\PhpConstant;
28 140
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
29 2
use WsdlToPhp\PhpGenerator\Element\PhpProperty;
30
31
class Struct extends AbstractModelFile
32 138
{
33
    public function setModel(AbstractModel $model): self
34
    {
35 136
        if (!$model instanceof StructModel) {
36
            throw new InvalidArgumentException('Model must be an instance of a Struct', __LINE__);
37 136
        }
38
39
        return parent::setModel($model);
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::setModel($model) returns the type WsdlToPhp\PackageGenerator\File\AbstractModelFile which includes types incompatible with the type-hinted return WsdlToPhp\PackageGenerator\File\Struct.
Loading history...
40 108
    }
41
42 108
    public function getModel(): ?StructModel
43 106
    {
44
        return parent::getModel();
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::getModel() could return the type WsdlToPhp\PackageGenerator\Model\AbstractModel which includes types incompatible with the type-hinted return WsdlToPhp\PackageGenerator\Model\Struct|null. Consider adding an additional type-check to rule them out.
Loading history...
45
    }
46 108
47
    protected function defineUseStatements(): self
48
    {
49 108
        if ($this->getGenerator()->getOptionValidation()) {
50
            $this->getFile()->addUse(InvalidArgumentException::class, null, false);
51 108
        }
52
53
        return parent::defineUseStatements();
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::defineUseStatements() returns the type WsdlToPhp\PackageGenerator\File\AbstractModelFile which includes types incompatible with the type-hinted return WsdlToPhp\PackageGenerator\File\Struct.
Loading history...
54
    }
55
56
    protected function fillClassConstants(ConstantContainer $constants): void
57
    {
58 126
    }
59
60 126
    protected function getConstantAnnotationBlock(PhpConstant $constant): ?PhpAnnotationBlock
61
    {
62
        return null;
63 126
    }
64
65
    protected function getModelAttributes(): StructAttributeContainer
66 126
    {
67
        return $this->getModel()->getProperAttributes(true);
68 104
    }
69 4
70
    protected function fillClassProperties(PropertyContainer $properties): void
71 4
    {
72
        /** @var StructAttributeModel $attribute */
73
        foreach ($this->getModelAttributes() as $attribute) {
74 104
            switch (true) {
75
                case $attribute->isXml():
76 104
                    $type = null;
77
78
                    break;
79 104
80 104
                default:
81 104
                    $type = (($attribute->isRequired() && !$attribute->isNullable()) ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute);
82 104
83 104
                    break;
84 104
            }
85 104
86 104
            $properties->add(
87
                new PhpProperty(
88
                    $attribute->getCleanName(),
89
                    $attribute->isRequired() ? AssignedValueElementInterface::NO_VALUE : null,
90 104
                    $this->getGenerator()->getOptionValidation() ? AccessRestrictedElementInterface::ACCESS_PROTECTED : AccessRestrictedElementInterface::ACCESS_PUBLIC,
91
                    $type
92 104
                )
93 104
            );
94 104
        }
95 104
    }
96 2
97
    protected function getPropertyAnnotationBlock(PhpProperty $property): ?PhpAnnotationBlock
98 104
    {
99 104
        $annotationBlock = new PhpAnnotationBlock();
100 104
        $annotationBlock->addChild(sprintf('The %s', $property->getName()));
101
        $attribute = $this->getModel()->getAttribute($property->getName());
102
        if (!$attribute instanceof StructAttributeModel) {
103 104
            $attribute = $this->getModel()->getAttributeByCleanName($property->getName());
104
        }
105
        if ($attribute instanceof StructAttributeModel) {
106 108
            $this->defineModelAnnotationsFromWsdl($annotationBlock, $attribute);
107
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_VAR, $this->getStructAttributeTypeGetAnnotation($attribute)));
108 108
        }
109 108
110 108
        return $annotationBlock;
111 108
    }
112
113
    protected function fillClassMethods(): void
114 108
    {
115
        $this
116 108
            ->addStructMethodConstruct()
117 104
            ->addStructMethodsSetAndGet()
118 104
        ;
119 104
    }
120
121
    protected function addStructMethodConstruct(): self
122 108
    {
123
        if (0 < count($parameters = $this->getStructMethodParametersValues())) {
124
            $method = new PhpMethod(self::METHOD_CONSTRUCT, $parameters);
125 104
            $this->addStructMethodConstructBody($method);
126
            $this->methods->add($method);
127 104
        }
128 104
129 104
        return $this;
130 104
    }
131
132 104
    protected function addStructMethodConstructBody(PhpMethod $method): self
133
    {
134
        $count = $this->getModelAttributes()->count();
135 104
        foreach ($this->getModelAttributes() as $index => $attribute) {
136
            if (0 === $index) {
137
                $method->addChild('$this');
138 104
            }
139
            $this->addStructMethodConstructBodyForAttribute($method, $attribute, $count - 1 === $index);
140 104
        }
141 104
142
        return $this;
143 104
    }
144
145
    protected function addStructMethodConstructBodyForAttribute(PhpMethod $method, StructAttributeModel $attribute, bool $isLast): self
146 108
    {
147
        $uniqueString = $attribute->getUniqueString($attribute->getCleanName(), 'method');
148 108
        $method->addChild($method->getIndentedString(sprintf('->%s($%s)%s', $attribute->getSetterName(), lcfirst($uniqueString), $isLast ? ';' : ''), 1));
149 108
150 104
        return $this;
151
    }
152
153 108
    protected function getStructMethodParametersValues(): array
154
    {
155
        $parametersValues = [];
156 104
        foreach ($this->getModelAttributes() as $attribute) {
157
            $parametersValues[] = $this->getStructMethodParameter($attribute);
158
        }
159 104
160 104
        return $parametersValues;
161 10
    }
162
163 10
    protected function getStructMethodParameter(StructAttributeModel $attribute): PhpFunctionParameter
164
    {
165
        switch (true) {
166 104
            case $attribute->isXml():
167
            case $attribute->isList():
168 104
                $type = null;
169
170
                break;
171
172 104
            default:
173
                $type = (($attribute->isRequired() && !$attribute->isNullable()) ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute);
174 104
175 104
                break;
176 104
        }
177 104
178 104
        try {
179 104
            $defaultValue = $attribute->getDefaultValue();
180
181
            return new PhpFunctionParameter(
182
                lcfirst($attribute->getUniqueString($attribute->getCleanName(), 'method')),
183
                $attribute->isRequired() && !$attribute->isAChoice() ? AssignedValueElementInterface::NO_VALUE : (str_contains($type ?? '', '?') ? $defaultValue ?? null : $defaultValue),
184
                $type,
185 108
                $attribute
186
            );
187 108
        } catch (InvalidArgumentException $exception) {
188 104
            throw new InvalidArgumentException(sprintf('Unable to create function parameter for struct "%s" with type "%s" for attribute "%s"', $this->getModel()->getName(), var_export($this->getStructAttributeTypeAsPhpType($attribute), true), $attribute->getName()), __LINE__, $exception);
189 104
        }
190 104
    }
191 104
192 104
    protected function addStructMethodsSetAndGet(): self
193
    {
194
        foreach ($this->getModelAttributes() as $attribute) {
195 108
            $this
196
                ->addStructMethodGet($attribute)
197
                ->addStructMethodSet($attribute)
198 94
                ->addStructMethodAddTo($attribute)
199
            ;
200 94
        }
201 40
202 40
        return $this;
203 40
    }
204 40
205 40
    protected function addStructMethodAddTo(StructAttributeModel $attribute): self
206 40
    {
207 40
        if ($attribute->isArray()) {
208 40
            $method = new PhpMethod(sprintf('addTo%s', ucfirst($attribute->getCleanName())), [
209 40
                new PhpFunctionParameter(
210 40
                    'item',
211
                    AssignedValueElementInterface::NO_VALUE,
212
                    $this->getStructAttributeTypeAsPhpType($attribute, false),
213 94
                    $attribute
214
                ),
215
            ], self::TYPE_SELF);
216 40
            $this->addStructMethodAddToBody($method, $attribute);
217
            $this->methods->add($method);
218 40
        }
219
220 40
        return $this;
221 40
    }
222
223
    protected function addStructMethodAddToBody(PhpMethod $method, StructAttributeModel $attribute): self
224
    {
225
        $this->applyRules($method, $attribute, 'item', true);
226 40
227 40
        if ($attribute->nameIsClean()) {
228 40
            $assignment = sprintf('$this->%s[] = $item;', $attribute->getCleanName());
229 40
        } else {
230 40
            $assignment = sprintf('$this->%s[] = $this->{\'%s\'}[] = $item;', $attribute->getCleanName(), addslashes($attribute->getName()));
231
        }
232 40
233
        $method
234
            ->addChild($assignment)
235 104
            ->addChild('')
236
            ->addChild('return $this;')
237 104
        ;
238 104
239 104
        return $this;
240 104
    }
241 104
242
    protected function addStructMethodSet(StructAttributeModel $attribute): self
243 104
    {
244
        $method = new PhpMethod($attribute->getSetterName(), [
245
            $this->getStructMethodParameter($attribute),
246 104
        ], self::TYPE_SELF);
247
        $this->addStructMethodSetBody($method, $attribute);
248 104
        $this->methods->add($method);
249 104
250 104
        return $this;
251
    }
252 104
253 104
    protected function addStructMethodSetBody(PhpMethod $method, StructAttributeModel $attribute): self
254 104
    {
255 104
        $parameters = $method->getParameters();
256 104
        $parameter = array_shift($parameters);
257
        $parameterName = is_string($parameter) ? $parameter : $parameter->getName();
258
259 104
        return $this
260
            ->applyRules($method, $attribute, $parameterName)
261 104
            ->addStructMethodSetBodyAssignment($method, $attribute, $parameterName)
262 18
            ->addStructMethodSetBodyReturn($method)
263 18
        ;
264 18
    }
265 18
266 18
    protected function addStructMethodSetBodyAssignment(PhpMethod $method, StructAttributeModel $attribute, string $parameterName): self
267 18
    {
268 18
        if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
269
            $method
270 100
                ->addChild(sprintf('if (is_null($%1$s) || (is_array($%1$s) && empty($%1$s))) {', $parameterName))
271
                ->addChild($method->getIndentedString(sprintf('unset($this->%1$s%2$s);', $attribute->getCleanName(), $attribute->nameIsClean() ? '' : sprintf(', $this->{\'%s\'}', addslashes($attribute->getName()))), 1))
272
                ->addChild('} else {')
273 104
                ->addChild($method->getIndentedString($this->getStructMethodSetBodyAssignment($attribute, $parameterName), 1))
274
                ->addChild('}')
275
            ;
276 104
        } else {
277
            $method->addChild($this->getStructMethodSetBodyAssignment($attribute, $parameterName));
278 104
        }
279 104
280 104
        return $this;
281 104
    }
282
283 104
    protected function addStructMethodSetBodyReturn(PhpMethod $method): self
284
    {
285
        $method
286 104
            ->addChild('')
287
            ->addChild('return $this;')
288 104
        ;
289 104
290 6
        return $this;
291 6
    }
292 104
293 4
    protected function getStructMethodSetBodyAssignment(StructAttributeModel $attribute, string $parameterName): string
294 4
    {
295
        $prefix = '$';
296
        if ($attribute->isList()) {
297 104
            $prefix = '';
298 104
            $parameterName = sprintf('is_array($%1$s) ? implode(\' \', $%1$s) : $%1$s', $parameterName);
299
        } elseif ($attribute->isXml()) {
300 2
            $prefix = '';
301
            $parameterName = sprintf('($%1$s instanceof \DOMDocument) ? $%1$s->saveXML($%1$s->hasChildNodes() ? $%1$s->childNodes->item(0) : null) : $%1$s', $parameterName);
302
        }
303 104
304
        if ($attribute->nameIsClean()) {
305
            $assignment = sprintf('$this->%s = %s%s;', $attribute->getName(), $prefix, $parameterName);
306 104
        } else {
307
            $assignment = sprintf('$this->%s = $this->{\'%s\'} = %s%s;', $attribute->getCleanName(), addslashes($attribute->getName()), $prefix, $parameterName);
308 104
        }
309
310
        return $assignment;
311 104
    }
312
313 104
    protected function addStructMethodGetBody(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self
314 104
    {
315 4
        return $this->addStructMethodGetBodyReturn($method, $attribute, $thisAccess);
316 4
    }
317 4
318 4
    protected function addStructMethodGetBodyReturn(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self
319 4
    {
320 4
        $return = sprintf('return $this->%s;', $thisAccess);
321 4
        if ($attribute->isXml()) {
322 4
            $method
323
                ->addChild('$domDocument = null;')
324
                ->addChild(sprintf('if (!empty($this->%1$s) && $asDomDocument) {', $thisAccess))
325 4
                ->addChild($method->getIndentedString('$domDocument = new \DOMDocument(\'1.0\', \'UTF-8\');', 1))
326
                ->addChild($method->getIndentedString(sprintf('$domDocument->loadXML($this->%s);', $thisAccess), 1))
327 104
                ->addChild('}')
328 18
            ;
329
            if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
330 104
                $return = sprintf('return $asDomDocument ? $domDocument : (isset($this->%1$s) ? $this->%1$s : null);', $thisAccess);
331
            } else {
332 104
                $return = sprintf('return $asDomDocument ? $domDocument : $this->%1$s;', $thisAccess);
333
            }
334
        } elseif ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
335 104
            $return = sprintf('return $this->%s ?? null;', $thisAccess);
336
        }
337
        $method->addChild($return);
338
339 104
        return $this;
340 4
    }
341
342 4
    protected function addStructMethodGet(StructAttributeModel $attribute): self
343
    {
344
        switch (true) {
345 104
            // it can either be a string, a DOMDocument or null...
346
            case $attribute->isXml():
347 104
                $returnType = '';
348
349
                break;
350 104
351 104
            default:
352 104
                $returnType = (!$attribute->getRemovableFromRequest() && !$attribute->isAChoice() && $attribute->isRequired() ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute);
353 104
354 104
                break;
355 104
        }
356 104
357
        $method = new PhpMethod(
358 2
            $attribute->getGetterName(),
359
            $this->getStructMethodGetParameters($attribute),
360 104
            $returnType
361 104
        );
362
        if ($attribute->nameIsClean()) {
363 104
            $thisAccess = sprintf('%s', $attribute->getName());
364
        } else {
365
            $thisAccess = sprintf('{\'%s\'}', addslashes($attribute->getName()));
366 104
        }
367
        $this->addStructMethodGetBody($method, $attribute, $thisAccess);
368 104
        $this->methods->add($method);
369 104
370 4
        return $this;
371
    }
372
373 104
    protected function getStructMethodGetParameters(StructAttributeModel $attribute): array
374
    {
375
        $parameters = [];
376 104
        if ($attribute->isXml()) {
377
            $parameters[] = new PhpFunctionParameter('asDomDocument', false, self::TYPE_BOOL, $attribute);
378 104
        }
379
380
        return $parameters;
381 104
    }
382
383 104
    protected function getMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
384
    {
385 104
        return $this->getStructMethodAnnotationBlock($method);
386 104
    }
387 104
388
    protected function getStructMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
389 104
    {
390
        $annotationBlock = null;
391 104
        $matches = [];
392 104
393 104
        switch ($method->getName()) {
394
            case self::METHOD_CONSTRUCT:
395 104
                $annotationBlock = $this->getStructMethodConstructAnnotationBlock();
396
397 68
                break;
398 40
399
            case 0 === mb_strpos($method->getName(), 'get'):
400 40
            case 0 === mb_strpos($method->getName(), 'set'):
401
                $annotationBlock = $this->getStructMethodsSetAndGetAnnotationBlock($method);
402 68
403 4
                break;
404
405 4
            case 0 === mb_strpos($method->getName(), 'addTo'):
406
                $annotationBlock = $this->getStructMethodsAddToAnnotationBlock($method);
407 64
408 60
                break;
409
410 60
            case 1 === preg_match('/validate(.+)For(.+)ConstraintFrom(.+)/', $method->getName(), $matches):
411
                $annotationBlock = $this->getStructMethodsValidateMethodAnnotationBlock($method, $matches[1], $matches[2], $matches[3]);
412 14
413 8
                break;
414
        }
415 8
416
        return $annotationBlock;
417 6
    }
418 6
419
    protected function getStructMethodConstructAnnotationBlock(): PhpAnnotationBlock
420 6
    {
421
        $annotationBlock = new PhpAnnotationBlock([
422 4
            sprintf('Constructor method for %s', $this->getModel()->getName()),
423 4
        ]);
424
        $this->addStructPropertiesToAnnotationBlock($annotationBlock);
425 4
426
        return $annotationBlock;
427
    }
428
429
    protected function getStructMethodsSetAndGetAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
430
    {
431
        $parameters = $method->getParameters();
432
        $setOrGet = mb_strtolower(mb_substr($method->getName(), 0, 3));
433 104
        $parameter = array_shift($parameters);
434
        // Only set parameter must be based on a potential PhpFunctionParameter
435
        if ($parameter instanceof PhpFunctionParameter && 'set' === $setOrGet) {
436 104
            $parameterName = ucfirst($parameter->getName());
437
        } else {
438 104
            $parameterName = mb_substr($method->getName(), 3);
439 104
        }
440 104
441 104
        /**
442
         * Since properties can be duplicated with different case, we assume that _\d+ is replaceable by an empty string as methods are "duplicated" with this suffix.
443 104
         */
444
        $parameterName = preg_replace('/(_\d+)/', '', $parameterName);
445
        $attribute = $this->getModel()->getAttribute($parameterName);
446 104
        if (!$attribute instanceof StructAttributeModel) {
447
            $attribute = $this->getModel()->getAttributeByCleanName($parameterName);
448 104
        }
449 104
        if (!$attribute instanceof StructAttributeModel) {
450 104
            $parameterName = lcfirst($parameterName);
451
            $attribute = $this->getModel()->getAttribute($parameterName);
452 104
            if (!$attribute instanceof StructAttributeModel) {
453 104
                $attribute = $this->getModel()->getAttributeByCleanName($parameterName);
454
            }
455 104
        }
456
        $setValueAnnotation = '%s %s value';
457
        $annotationBlock = new PhpAnnotationBlock();
458
        if ($attribute instanceof StructAttributeModel) {
459
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), $parameterName));
460
            $this->addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, $annotationBlock, $attribute);
461 104
        } elseif (!$attribute) {
0 ignored issues
show
introduced by
$attribute is of type null, thus it always evaluated to false.
Loading history...
462 104
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), lcfirst($parameterName)));
463 104
            $this->addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, $annotationBlock, $parameterName);
464 42
        }
465
466 104
        return $annotationBlock;
467 42
    }
468 42
469 42
    protected function addStructMethodsSetAndGetAnnotationBlockFromStructAttribute(string $setOrGet, PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self
470 4
    {
471
        switch ($setOrGet) {
472
            case 'set':
473 104
                if ($attribute->getRemovableFromRequest()) {
474 104
                    $annotationBlock->addChild('This property is removable from request (nillable=true+minOccurs=0), therefore if the value assigned to this property is null, it is removed from this object');
475 104
                }
476 104
                if ($attribute->isAChoice()) {
477 104
                    $annotationBlock->addChild('This property belongs to a choice that allows only one property to exist. It is therefore removable from the request, consequently if the value assigned to this property is null, the property is removed from this object');
478 2
                }
479 2
                if ($attribute->isXml()) {
480 2
                    $annotationBlock
481
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::hasChildNodes()'))
482
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::saveXML()'))
483 104
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMNode::item()'))
484
                    ;
485
                }
486 104
                if ($this->getGenerator()->getOptionValidation()) {
487
                    if ($attribute->isAChoice()) {
488
                        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class));
489 104
                    }
490 104
                    if (($model = $this->getRestrictionFromStructAttribute($attribute)) instanceof StructModel) {
491 10
                        $annotationBlock
492
                            ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
493 104
                            ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)))
494 8
                            ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class))
495
                        ;
496 104
                    } elseif ($attribute->isArray()) {
497 4
                        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class));
498 4
                    }
499 4
                }
500 4
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeSetAnnotation($attribute, false), lcfirst($attribute->getCleanName()));
501 4
502
                break;
503 104
504 102
            case 'get':
505 8
                if ($attribute->getRemovableFromRequest()) {
506
                    $annotationBlock->addChild('An additional test has been added (isset) before returning the property value as this property may have been unset before, due to the fact that this property is removable from the request (nillable=true+minOccurs=0)');
507 102
                }
508 48
                $this
509 48
                    ->addStructMethodsGetAnnotationBlockFromXmlAttribute($annotationBlock, $attribute)
510 48
                    ->addStructMethodsGetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeGetAnnotation($attribute, true, $attribute->isAChoice()))
511 48
                ;
512 48
513 100
                break;
514 54
        }
515
516
        return $this;
517 104
    }
518
519 104
    protected function addStructMethodsSetAndGetAnnotationBlockFromScalar(string $setOrGet, PhpAnnotationBlock $annotationBlock, string $attributeName): self
520
    {
521 104
        switch ($setOrGet) {
522 104
            case 'set':
523 10
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, lcfirst($attributeName), lcfirst($attributeName));
524
525 104
                break;
526 104
527 104
            case 'get':
528 104
                $this->addStructMethodsGetAnnotationBlock($annotationBlock, lcfirst($attributeName));
529
530 104
                break;
531
        }
532
533 104
        return $this;
534
    }
535
536 2
    protected function addStructMethodsSetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $type, string $name): self
537
    {
538
        $annotationBlock
539 2
            ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $type, $name)))
540 2
            ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)))
541
        ;
542 2
543
        return $this;
544 2
    }
545 2
546
    protected function addStructMethodsGetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $attributeType): self
547 2
    {
548
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $attributeType));
549
550 2
        return $this;
551
    }
552
553 104
    protected function addStructMethodsGetAnnotationBlockFromXmlAttribute(PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self
554
    {
555 104
        if ($attribute->isXml()) {
556 104
            $annotationBlock
557 104
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::loadXML()'))
558 104
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, 'bool $asDomDocument true: returns \DOMDocument, false: returns XML string'))
559
            ;
560 104
        }
561
562
        return $this;
563 104
    }
564
565 104
    protected function addStructPropertiesToAnnotationBlock(PhpAnnotationBlock $annotationBlock): self
566
    {
567 104
        return $this
568
            ->addStructPropertiesToAnnotationBlockUses($annotationBlock)
569
            ->addStructPropertiesToAnnotationBlockParams($annotationBlock)
570 104
        ;
571
    }
572 104
573 4
    protected function addStructPropertiesToAnnotationBlockUses(PhpAnnotationBlock $annotationBlock): self
574 4
    {
575 4
        foreach ($this->getModelAttributes() as $attribute) {
576 4
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(), $attribute->getSetterName())));
577
        }
578
579 104
        return $this;
580
    }
581
582 104
    protected function addStructPropertiesToAnnotationBlockParams(PhpAnnotationBlock $annotationBlock): self
583
    {
584 104
        foreach ($this->getModelAttributes() as $attribute) {
585 104
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $this->getStructAttributeTypeSetAnnotation($attribute, false), lcfirst($attribute->getCleanName()))));
586 104
        }
587 104
588
        return $this;
589
    }
590 104
591
    protected function getStructMethodsAddToAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
592 104
    {
593 104
        $methodParameters = $method->getParameters();
594
595
        /** @var PhpFunctionParameter $firstParameter */
596 104
        $firstParameter = array_shift($methodParameters);
597
        $attribute = $this->getModel()->getAttribute($firstParameter->getModel()->getName());
598
        $annotationBlock = new PhpAnnotationBlock();
599 104
        if ($attribute instanceof StructAttributeModel) {
600
            $model = $this->getRestrictionFromStructAttribute($attribute);
601 104
            $annotationBlock->addChild(sprintf('Add item to %s value', $attribute->getCleanName()));
602 104
            if ($model instanceof StructModel) {
603
                $annotationBlock
604
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
605 104
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)))
606
                ;
607
            }
608 40
            $annotationBlock
609
                ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class))
610 40
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $item', $this->getStructAttributeTypeSetAnnotation($attribute, false, true))))
611
                ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)))
612
            ;
613 40
        }
614 40
615 40
        return $annotationBlock;
616 40
    }
617 40
618 40
    protected function getStructMethodsValidateMethodAnnotationBlock(PhpMethod $method, string $propertyName, string $constraintName, string $fromMethodName): PhpAnnotationBlock
0 ignored issues
show
Unused Code introduced by
The parameter $method is not used and could be removed. ( Ignorable by Annotation )

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

618
    protected function getStructMethodsValidateMethodAnnotationBlock(/** @scrutinizer ignore-unused */ PhpMethod $method, string $propertyName, string $constraintName, string $fromMethodName): PhpAnnotationBlock

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
619 40
    {
620 2
        $customConstraintMessage = '';
621 2
622 2
        switch (lcfirst($constraintName)) {
623 2
            case ArrayRule::NAME:
624
                $customConstraintMessage = 'This has to validate that each item contained by the array match the itemType constraint';
625 40
626 40
                break;
627 40
628 40
            case ChoiceRule::NAME:
629 40
                $customConstraintMessage = 'This has to validate that the property which is being set is the only one among the given choices';
630
631
                break;
632 40
633
            case LengthRule::NAME:
634
            case MaxLengthRule::NAME:
635 60
            case MinLengthRule::NAME:
636
                $customConstraintMessage = 'This has to validate that the items contained by the array match the length constraint';
637 60
638
                break;
639 60
640 60
            case PatternRule::NAME:
641 60
                $customConstraintMessage = 'This has to validate that the items contained by the array match the defined pattern';
642 60
643 60
                break;
644 60
645
            case UnionRule::NAME:
646
                $customConstraintMessage = sprintf('This is a set of validation rules based on the union types associated to the property %s', $propertyName);
647 4
648
                break;
649 4
        }
650
651 4
        return new PhpAnnotationBlock([
652 4
            new PhpAnnotation(
653 4
                PhpAnnotation::NO_NAME,
654 4
                sprintf(
655 4
                    'This method is responsible for validating the value(s) passed to the %s method',
656 4
                    $fromMethodName
657 4
                ),
658
                self::ANNOTATION_LONG_LENGTH
659
            ),
660 8
            new PhpAnnotation(
661
                PhpAnnotation::NO_NAME,
662 8
                sprintf(
663
                    'This method is willingly generated in order to preserve the one-line inline validation within the %s method',
664 8
                    $fromMethodName
665 8
                ),
666 8
                self::ANNOTATION_LONG_LENGTH
667 8
            ),
668 8
            new PhpAnnotation(
669 8
                PhpAnnotation::NO_NAME,
670 8
                $customConstraintMessage,
671
                self::ANNOTATION_LONG_LENGTH
672
            ),
673 6
            new PhpAnnotation(self::ANNOTATION_PARAM, 'array $values'),
674
            new PhpAnnotation(
675 6
                self::ANNOTATION_RETURN,
676 6
                'string A non-empty message if the values does not match the validation rules'
677
            ),
678 6
        ]);
679 6
    }
680 6
681 6
    protected function applyRules(PhpMethod $method, StructAttributeModel $attribute, string $parameterName, bool $itemType = false): self
682 6
    {
683 6
        if ($this->getGenerator()->getOptionValidation()) {
684 6
            $rules = new Rules($this, $method, $attribute, $this->methods);
685
            $rules->applyRules($parameterName, $itemType);
686
        }
687 104
688
        return $this;
689 104
    }
690
}
691