Passed
Pull Request — develop (#279)
by Mikaël
10:56 queued 07:51
created

Struct::applyRules()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 4
c 0
b 0
f 0
nc 2
nop 4
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 2
rs 10
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
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
27
use WsdlToPhp\PhpGenerator\Element\PhpConstant;
28
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
29
use WsdlToPhp\PhpGenerator\Element\PhpProperty;
30
31
class Struct extends AbstractModelFile
32
{
33 142
    public function setModel(AbstractModel $model): self
34
    {
35 142
        if (!$model instanceof StructModel) {
36 2
            throw new InvalidArgumentException('Model must be an instance of a Struct', __LINE__);
37
        }
38
39 140
        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
    }
41
42 138
    public function getModel(): ?StructModel
43
    {
44 138
        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
47 110
    protected function defineUseStatements(): self
48
    {
49 110
        if ($this->getGenerator()->getOptionValidation()) {
50 108
            $this->getFile()->addUse(InvalidArgumentException::class, null, false);
51
        }
52
53 110
        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 110
    protected function fillClassConstants(ConstantContainer $constants): void
57
    {
58 110
    }
59
60
    protected function getConstantAnnotationBlock(PhpConstant $constant): ?PhpAnnotationBlock
61
    {
62
        return null;
63
    }
64
65 128
    protected function getModelAttributes(): StructAttributeContainer
66
    {
67 128
        return $this->getModel()->getProperAttributes(true);
68
    }
69
70 128
    protected function fillClassProperties(PropertyContainer $properties): void
71
    {
72
        /** @var StructAttributeModel $attribute */
73 128
        foreach ($this->getModelAttributes() as $attribute) {
74
            switch (true) {
75 106
                case $attribute->isXml():
76 4
                    $type = null;
77
78 4
                    break;
79
80
                default:
81 106
                    $type = (($attribute->isRequired() && !$attribute->isNullable()) ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute);
82
83 106
                    break;
84
            }
85
86 106
            $properties->add(
87 106
                new PhpProperty(
88 106
                    $attribute->getCleanName(),
89 106
                    $attribute->isRequired() ? AssignedValueElementInterface::NO_VALUE : null,
90 106
                    $this->getGenerator()->getOptionValidation() ? AccessRestrictedElementInterface::ACCESS_PROTECTED : AccessRestrictedElementInterface::ACCESS_PUBLIC,
91 106
                    $type
92 106
                )
93 106
            );
94
        }
95
    }
96
97 106
    protected function getPropertyAnnotationBlock(PhpProperty $property): ?PhpAnnotationBlock
98
    {
99 106
        $annotationBlock = new PhpAnnotationBlock();
100 106
        $annotationBlock->addChild(sprintf('The %s', $property->getName()));
101 106
        $attribute = $this->getModel()->getAttribute($property->getName());
102 106
        if (!$attribute instanceof StructAttributeModel) {
103 2
            $attribute = $this->getModel()->getAttributeByCleanName($property->getName());
104
        }
105 106
        if ($attribute instanceof StructAttributeModel) {
106 106
            $this->defineModelAnnotationsFromWsdl($annotationBlock, $attribute);
107 106
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_VAR, $this->getStructAttributeTypeGetAnnotation($attribute)));
108
        }
109
110 106
        return $annotationBlock;
111
    }
112
113 110
    protected function fillClassMethods(): void
114
    {
115 110
        $this
116 110
            ->addStructMethodConstruct()
117 110
            ->addStructMethodsSetAndGet()
118 110
        ;
119
    }
120
121 110
    protected function addStructMethodConstruct(): self
122
    {
123 110
        if (0 < count($parameters = $this->getStructMethodParametersValues())) {
124 106
            $method = new PhpMethod(self::METHOD_CONSTRUCT, $parameters);
125 106
            $this->addStructMethodConstructBody($method);
126 106
            $this->methods->add($method);
127
        }
128
129 110
        return $this;
130
    }
131
132 106
    protected function addStructMethodConstructBody(PhpMethod $method): self
133
    {
134 106
        $count = $this->getModelAttributes()->count();
135 106
        foreach ($this->getModelAttributes() as $index => $attribute) {
136 106
            if (0 === $index) {
137 106
                $method->addChild('$this');
138
            }
139 106
            $this->addStructMethodConstructBodyForAttribute($method, $attribute, $count - 1 === $index);
140
        }
141
142 106
        return $this;
143
    }
144
145 106
    protected function addStructMethodConstructBodyForAttribute(PhpMethod $method, StructAttributeModel $attribute, bool $isLast): self
146
    {
147 106
        $uniqueString = $attribute->getUniqueString($attribute->getCleanName(), 'method');
148 106
        $method->addChild($method->getIndentedString(sprintf('->%s($%s)%s', $attribute->getSetterName(), lcfirst($uniqueString), $isLast ? ';' : ''), 1));
149
150 106
        return $this;
151
    }
152
153 110
    protected function getStructMethodParametersValues(): array
154
    {
155 110
        $parametersValues = [];
156 110
        foreach ($this->getModelAttributes() as $attribute) {
157 106
            $parametersValues[] = $this->getStructMethodParameter($attribute);
158
        }
159
160 110
        return $parametersValues;
161
    }
162
163 106
    protected function getStructMethodParameter(StructAttributeModel $attribute): PhpFunctionParameter
164
    {
165
        switch (true) {
166 106
            case $attribute->isXml():
167 106
            case $attribute->isList():
168 10
                $type = null;
169
170 10
                break;
171
172
            default:
173 106
                $type = (($attribute->isRequired() && !$attribute->isNullable()) ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute);
174
175 106
                break;
176
        }
177
178
        try {
179 106
            $defaultValue = $attribute->getDefaultValue();
180
181 106
            return new PhpFunctionParameter(
182 106
                lcfirst($attribute->getUniqueString($attribute->getCleanName(), 'method')),
183 106
                $attribute->isRequired() && !$attribute->isAChoice() ? AssignedValueElementInterface::NO_VALUE : (str_contains($type ?? '', '?') ? $defaultValue ?? null : $defaultValue),
184 106
                $type,
185 106
                $attribute
186 106
            );
187
        } catch (InvalidArgumentException $exception) {
188
            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
        }
190
    }
191
192 110
    protected function addStructMethodsSetAndGet(): self
193
    {
194 110
        foreach ($this->getModelAttributes() as $attribute) {
195 106
            $this
196 106
                ->addStructMethodGet($attribute)
197 106
                ->addStructMethodSet($attribute)
198 106
                ->addStructMethodAddTo($attribute)
199 106
            ;
200
        }
201
202 110
        return $this;
203
    }
204
205 94
    protected function addStructMethodAddTo(StructAttributeModel $attribute): self
206
    {
207 94
        if ($attribute->isArray()) {
208 40
            $method = new PhpMethod(sprintf('addTo%s', ucfirst($attribute->getCleanName())), [
209 40
                new PhpFunctionParameter(
210 40
                    'item',
211 40
                    AssignedValueElementInterface::NO_VALUE,
212 40
                    $this->getStructAttributeTypeAsPhpType($attribute, false),
213 40
                    $attribute
214 40
                ),
215 40
            ], self::TYPE_SELF);
216 40
            $this->addStructMethodAddToBody($method, $attribute);
217 40
            $this->methods->add($method);
218
        }
219
220 94
        return $this;
221
    }
222
223 40
    protected function addStructMethodAddToBody(PhpMethod $method, StructAttributeModel $attribute): self
224
    {
225 40
        $this->applyRules($method, $attribute, 'item', true);
226
227 40
        if ($attribute->nameIsClean()) {
228 40
            $assignment = sprintf('$this->%s[] = $item;', $attribute->getCleanName());
229
        } else {
230
            $assignment = sprintf('$this->%s[] = $this->{\'%s\'}[] = $item;', $attribute->getCleanName(), addslashes($attribute->getName()));
231
        }
232
233 40
        $method
234 40
            ->addChild($assignment)
235 40
            ->addChild('')
236 40
            ->addChild('return $this;')
237 40
        ;
238
239 40
        return $this;
240
    }
241
242 106
    protected function addStructMethodSet(StructAttributeModel $attribute): self
243
    {
244 106
        $method = new PhpMethod($attribute->getSetterName(), [
245 106
            $this->getStructMethodParameter($attribute),
246 106
        ], self::TYPE_SELF);
247 106
        $this->addStructMethodSetBody($method, $attribute);
248 106
        $this->methods->add($method);
249
250 106
        return $this;
251
    }
252
253 106
    protected function addStructMethodSetBody(PhpMethod $method, StructAttributeModel $attribute): self
254
    {
255 106
        $parameters = $method->getParameters();
256 106
        $parameter = array_shift($parameters);
257 106
        $parameterName = is_string($parameter) ? $parameter : $parameter->getName();
258
259 106
        return $this
260 106
            ->applyRules($method, $attribute, $parameterName)
261 106
            ->addStructMethodSetBodyAssignment($method, $attribute, $parameterName)
262 106
            ->addStructMethodSetBodyReturn($method)
263 106
        ;
264
    }
265
266 106
    protected function addStructMethodSetBodyAssignment(PhpMethod $method, StructAttributeModel $attribute, string $parameterName): self
267
    {
268 106
        if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
269 18
            $method
270 18
                ->addChild(sprintf('if (is_null($%1$s) || (is_array($%1$s) && empty($%1$s))) {', $parameterName))
271 18
                ->addChild($method->getIndentedString(sprintf('unset($this->%1$s%2$s);', $attribute->getCleanName(), $attribute->nameIsClean() ? '' : sprintf(', $this->{\'%s\'}', addslashes($attribute->getName()))), 1))
272 18
                ->addChild('} else {')
273 18
                ->addChild($method->getIndentedString($this->getStructMethodSetBodyAssignment($attribute, $parameterName), 1))
274 18
                ->addChild('}')
275 18
            ;
276
        } else {
277 102
            $method->addChild($this->getStructMethodSetBodyAssignment($attribute, $parameterName));
278
        }
279
280 106
        return $this;
281
    }
282
283 106
    protected function addStructMethodSetBodyReturn(PhpMethod $method): self
284
    {
285 106
        $method
286 106
            ->addChild('')
287 106
            ->addChild('return $this;')
288 106
        ;
289
290 106
        return $this;
291
    }
292
293 106
    protected function getStructMethodSetBodyAssignment(StructAttributeModel $attribute, string $parameterName): string
294
    {
295 106
        $prefix = '$';
296 106
        if ($attribute->isList()) {
297 6
            $prefix = '';
298 6
            $parameterName = sprintf('is_array($%1$s) ? implode(\' \', $%1$s) : $%1$s', $parameterName);
299 106
        } elseif ($attribute->isXml()) {
300 4
            $prefix = '';
301 4
            $parameterName = sprintf('($%1$s instanceof \DOMDocument) ? $%1$s->saveXML($%1$s->hasChildNodes() ? $%1$s->childNodes->item(0) : null) : $%1$s', $parameterName);
302
        }
303
304 106
        if ($attribute->nameIsClean()) {
305 106
            $assignment = sprintf('$this->%s = %s%s;', $attribute->getName(), $prefix, $parameterName);
306
        } else {
307 2
            $assignment = sprintf('$this->%s = $this->{\'%s\'} = %s%s;', $attribute->getCleanName(), addslashes($attribute->getName()), $prefix, $parameterName);
308
        }
309
310 106
        return $assignment;
311
    }
312
313 106
    protected function addStructMethodGetBody(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self
314
    {
315 106
        return $this->addStructMethodGetBodyReturn($method, $attribute, $thisAccess);
316
    }
317
318 106
    protected function addStructMethodGetBodyReturn(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self
319
    {
320 106
        $return = sprintf('return $this->%s;', $thisAccess);
321 106
        if ($attribute->isXml()) {
322 4
            $method
323 4
                ->addChild('$domDocument = null;')
324 4
                ->addChild(sprintf('if (!empty($this->%1$s) && $asDomDocument) {', $thisAccess))
325 4
                ->addChild($method->getIndentedString('$domDocument = new \DOMDocument(\'1.0\', \'UTF-8\');', 1))
326 4
                ->addChild($method->getIndentedString(sprintf('$domDocument->loadXML($this->%s);', $thisAccess), 1))
327 4
                ->addChild('}')
328 4
            ;
329 4
            if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
330
                $return = sprintf('return $asDomDocument ? $domDocument : (isset($this->%1$s) ? $this->%1$s : null);', $thisAccess);
331
            } else {
332 4
                $return = sprintf('return $asDomDocument ? $domDocument : $this->%1$s;', $thisAccess);
333
            }
334 106
        } elseif ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
335 18
            $return = sprintf('return $this->%s ?? null;', $thisAccess);
336
        }
337 106
        $method->addChild($return);
338
339 106
        return $this;
340
    }
341
342 106
    protected function addStructMethodGet(StructAttributeModel $attribute): self
343
    {
344
        switch (true) {
345
            // it can either be a string, a DOMDocument or null...
346 106
            case $attribute->isXml():
347 4
                $returnType = '';
348
349 4
                break;
350
351
            default:
352 106
                $returnType = (!$attribute->getRemovableFromRequest() && !$attribute->isAChoice() && $attribute->isRequired() ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute);
353
354 106
                break;
355
        }
356
357 106
        $method = new PhpMethod(
358 106
            $attribute->getGetterName(),
359 106
            $this->getStructMethodGetParameters($attribute),
360 106
            $returnType
361 106
        );
362 106
        if ($attribute->nameIsClean()) {
363 106
            $thisAccess = sprintf('%s', $attribute->getName());
364
        } else {
365 2
            $thisAccess = sprintf('{\'%s\'}', addslashes($attribute->getName()));
366
        }
367 106
        $this->addStructMethodGetBody($method, $attribute, $thisAccess);
368 106
        $this->methods->add($method);
369
370 106
        return $this;
371
    }
372
373 106
    protected function getStructMethodGetParameters(StructAttributeModel $attribute): array
374
    {
375 106
        $parameters = [];
376 106
        if ($attribute->isXml()) {
377 4
            $parameters[] = new PhpFunctionParameter('asDomDocument', false, self::TYPE_BOOL, $attribute);
378
        }
379
380 106
        return $parameters;
381
    }
382
383 106
    protected function getMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
384
    {
385 106
        return $this->getStructMethodAnnotationBlock($method);
386
    }
387
388 106
    protected function getStructMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
389
    {
390 106
        $annotationBlock = null;
391 106
        $matches = [];
392
393 106
        switch ($method->getName()) {
394 106
            case self::METHOD_CONSTRUCT:
395 106
                $annotationBlock = $this->getStructMethodConstructAnnotationBlock();
396
397 106
                break;
398
399 106
            case 0 === mb_strpos($method->getName(), 'get'):
400 106
            case 0 === mb_strpos($method->getName(), 'set'):
401 106
                $annotationBlock = $this->getStructMethodsSetAndGetAnnotationBlock($method);
402
403 106
                break;
404
405 70
            case 0 === mb_strpos($method->getName(), 'addTo'):
406 40
                $annotationBlock = $this->getStructMethodsAddToAnnotationBlock($method);
407
408 40
                break;
409
410 70
            case 1 === preg_match('/validate(.+)For(.+)ConstraintFrom(.+)/', $method->getName(), $matches):
411 70
                $annotationBlock = $this->getStructMethodsValidateMethodAnnotationBlock($method, $matches[1], $matches[2], $matches[3]);
412
413 70
                break;
414
        }
415
416 106
        return $annotationBlock;
417
    }
418
419 106
    protected function getStructMethodConstructAnnotationBlock(): PhpAnnotationBlock
420
    {
421 106
        $annotationBlock = new PhpAnnotationBlock([
422 106
            sprintf('Constructor method for %s', $this->getModel()->getName()),
423 106
        ]);
424 106
        $this->addStructPropertiesToAnnotationBlock($annotationBlock);
425
426 106
        return $annotationBlock;
427
    }
428
429 106
    protected function getStructMethodsSetAndGetAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
430
    {
431 106
        $parameters = $method->getParameters();
432 106
        $setOrGet = mb_strtolower(mb_substr($method->getName(), 0, 3));
433 106
        $parameter = array_shift($parameters);
434
        // Only set parameter must be based on a potential PhpFunctionParameter
435 106
        if ($parameter instanceof PhpFunctionParameter && 'set' === $setOrGet) {
436 106
            $parameterName = ucfirst($parameter->getName());
437
        } else {
438 106
            $parameterName = mb_substr($method->getName(), 3);
439
        }
440
441
        /**
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
         */
444 106
        $parameterName = preg_replace('/(_\d+)/', '', $parameterName);
445 106
        $attribute = $this->getModel()->getAttribute($parameterName);
446 106
        if (!$attribute instanceof StructAttributeModel) {
447 44
            $attribute = $this->getModel()->getAttributeByCleanName($parameterName);
448
        }
449 106
        if (!$attribute instanceof StructAttributeModel) {
450 44
            $parameterName = lcfirst($parameterName);
451 44
            $attribute = $this->getModel()->getAttribute($parameterName);
452 44
            if (!$attribute instanceof StructAttributeModel) {
453 4
                $attribute = $this->getModel()->getAttributeByCleanName($parameterName);
454
            }
455
        }
456 106
        $setValueAnnotation = '%s %s value';
457 106
        $annotationBlock = new PhpAnnotationBlock();
458 106
        if ($attribute instanceof StructAttributeModel) {
459 106
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), $parameterName));
460 106
            $this->addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, $annotationBlock, $attribute);
461 2
        } elseif (!$attribute) {
0 ignored issues
show
introduced by
$attribute is of type null, thus it always evaluated to false.
Loading history...
462 2
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), lcfirst($parameterName)));
463 2
            $this->addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, $annotationBlock, $parameterName);
464
        }
465
466 106
        return $annotationBlock;
467
    }
468
469 106
    protected function addStructMethodsSetAndGetAnnotationBlockFromStructAttribute(string $setOrGet, PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self
470
    {
471
        switch ($setOrGet) {
472 106
            case 'set':
473 106
                if ($attribute->getRemovableFromRequest()) {
474 10
                    $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
                }
476 106
                if ($attribute->isAChoice()) {
477 8
                    $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
                }
479 106
                if ($attribute->isXml()) {
480 4
                    $annotationBlock
481 4
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::hasChildNodes()'))
482 4
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::saveXML()'))
483 4
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMNode::item()'))
484 4
                    ;
485
                }
486 106
                if ($this->getGenerator()->getOptionValidation()) {
487 104
                    if ($attribute->isAChoice()) {
488 8
                        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class));
489
                    }
490 104
                    if (($model = $this->getRestrictionFromStructAttribute($attribute)) instanceof StructModel) {
491 48
                        $annotationBlock
492 48
                            ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
493 48
                            ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)))
494 48
                            ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class))
495 48
                        ;
496 102
                    } elseif ($attribute->isArray()) {
497 56
                        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class));
498
                    }
499
                }
500 106
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeSetAnnotation($attribute, false), lcfirst($attribute->getCleanName()));
501
502 106
                break;
503
504 106
            case 'get':
505 106
                if ($attribute->getRemovableFromRequest()) {
506 10
                    $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
                }
508 106
                $this
509 106
                    ->addStructMethodsGetAnnotationBlockFromXmlAttribute($annotationBlock, $attribute)
510 106
                    ->addStructMethodsGetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeGetAnnotation($attribute, true, $attribute->isAChoice()))
511 106
                ;
512
513 106
                break;
514
        }
515
516 106
        return $this;
517
    }
518
519 2
    protected function addStructMethodsSetAndGetAnnotationBlockFromScalar(string $setOrGet, PhpAnnotationBlock $annotationBlock, string $attributeName): self
520
    {
521
        switch ($setOrGet) {
522 2
            case 'set':
523 2
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, lcfirst($attributeName), lcfirst($attributeName));
524
525 2
                break;
526
527 2
            case 'get':
528 2
                $this->addStructMethodsGetAnnotationBlock($annotationBlock, lcfirst($attributeName));
529
530 2
                break;
531
        }
532
533 2
        return $this;
534
    }
535
536 106
    protected function addStructMethodsSetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $type, string $name): self
537
    {
538 106
        $annotationBlock
539 106
            ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $type, $name)))
540 106
            ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)))
541 106
        ;
542
543 106
        return $this;
544
    }
545
546 106
    protected function addStructMethodsGetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $attributeType): self
547
    {
548 106
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $attributeType));
549
550 106
        return $this;
551
    }
552
553 106
    protected function addStructMethodsGetAnnotationBlockFromXmlAttribute(PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self
554
    {
555 106
        if ($attribute->isXml()) {
556 4
            $annotationBlock
557 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::loadXML()'))
558 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, 'bool $asDomDocument true: returns \DOMDocument, false: returns XML string'))
559 4
            ;
560
        }
561
562 106
        return $this;
563
    }
564
565 106
    protected function addStructPropertiesToAnnotationBlock(PhpAnnotationBlock $annotationBlock): self
566
    {
567 106
        return $this
568 106
            ->addStructPropertiesToAnnotationBlockUses($annotationBlock)
569 106
            ->addStructPropertiesToAnnotationBlockParams($annotationBlock)
570 106
        ;
571
    }
572
573 106
    protected function addStructPropertiesToAnnotationBlockUses(PhpAnnotationBlock $annotationBlock): self
574
    {
575 106
        foreach ($this->getModelAttributes() as $attribute) {
576 106
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(), $attribute->getSetterName())));
577
        }
578
579 106
        return $this;
580
    }
581
582 106
    protected function addStructPropertiesToAnnotationBlockParams(PhpAnnotationBlock $annotationBlock): self
583
    {
584 106
        foreach ($this->getModelAttributes() as $attribute) {
585 106
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $this->getStructAttributeTypeSetAnnotation($attribute, false), lcfirst($attribute->getCleanName()))));
586
        }
587
588 106
        return $this;
589
    }
590
591 40
    protected function getStructMethodsAddToAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
592
    {
593 40
        $methodParameters = $method->getParameters();
594
595
        /** @var PhpFunctionParameter $firstParameter */
596 40
        $firstParameter = array_shift($methodParameters);
597 40
        $attribute = $this->getModel()->getAttribute($firstParameter->getModel()->getName());
598 40
        $annotationBlock = new PhpAnnotationBlock();
599 40
        if ($attribute instanceof StructAttributeModel) {
600 40
            $model = $this->getRestrictionFromStructAttribute($attribute);
601 40
            $annotationBlock->addChild(sprintf('Add item to %s value', $attribute->getCleanName()));
602 40
            if ($model instanceof StructModel) {
603 2
                $annotationBlock
604 2
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
605 2
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)))
606 2
                ;
607
            }
608 40
            $annotationBlock
609 40
                ->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 40
                ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)))
612 40
            ;
613
        }
614
615 40
        return $annotationBlock;
616
    }
617
618 70
    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
    {
620 70
        $customConstraintMessage = '';
621
622 70
        switch (lcfirst($constraintName)) {
623 70
            case ArrayRule::NAME:
624 58
                $customConstraintMessage = 'This has to validate that each item contained by the array match the itemType constraint';
625
626 58
                break;
627
628 30
            case ChoiceRule::NAME:
629 8
                $customConstraintMessage = 'This has to validate that the property which is being set is the only one among the given choices';
630
631 8
                break;
632
633 22
            case LengthRule::NAME:
634 22
            case MaxLengthRule::NAME:
635 20
            case MinLengthRule::NAME:
636 6
                $customConstraintMessage = 'This has to validate that the items contained by the array match the length constraint';
637
638 6
                break;
639
640 16
            case PatternRule::NAME:
641 6
                $customConstraintMessage = 'This has to validate that the items contained by the array match the defined pattern';
642
643 6
                break;
644
645 10
            case UnionRule::NAME:
646 4
                $customConstraintMessage = sprintf('This is a set of validation rules based on the union types associated to the property %s', $propertyName);
647
648 4
                break;
649
        }
650
651 70
        return new PhpAnnotationBlock([
652 70
            new PhpAnnotation(
653 70
                PhpAnnotation::NO_NAME,
654 70
                sprintf(
655 70
                    'This method is responsible for validating the value(s) passed to the %s method',
656 70
                    $fromMethodName
657 70
                ),
658 70
                self::ANNOTATION_LONG_LENGTH
659 70
            ),
660 70
            new PhpAnnotation(
661 70
                PhpAnnotation::NO_NAME,
662 70
                sprintf(
663 70
                    'This method is willingly generated in order to preserve the one-line inline validation within the %s method',
664 70
                    $fromMethodName
665 70
                ),
666 70
                self::ANNOTATION_LONG_LENGTH
667 70
            ),
668 70
            new PhpAnnotation(
669 70
                PhpAnnotation::NO_NAME,
670 70
                $customConstraintMessage,
671 70
                self::ANNOTATION_LONG_LENGTH
672 70
            ),
673 70
            new PhpAnnotation(self::ANNOTATION_PARAM, 'array $values'),
674 70
            new PhpAnnotation(
675 70
                self::ANNOTATION_RETURN,
676 70
                'string A non-empty message if the values does not match the validation rules'
677 70
            ),
678 70
        ]);
679
    }
680
681 106
    protected function applyRules(PhpMethod $method, StructAttributeModel $attribute, string $parameterName, bool $itemType = false): self
682
    {
683 106
        if ($this->getGenerator()->getOptionValidation()) {
684 104
            $rules = new Rules($this, $method, $attribute, $this->methods);
685 104
            $rules->applyRules($parameterName, $itemType);
686
        }
687
688 106
        return $this;
689
    }
690
}
691