Passed
Push — feature/issue-124 ( 30f59e...e82cdf )
by Mikaël
11:18
created

Struct   F

Complexity

Total Complexity 113

Size/Duplication

Total Lines 581
Duplicated Lines 0 %

Test Coverage

Coverage 97.08%

Importance

Changes 7
Bugs 1 Features 2
Metric Value
eloc 321
dl 0
loc 581
ccs 332
cts 342
cp 0.9708
rs 2
c 7
b 1
f 2
wmc 113

43 Methods

Rating   Name   Duplication   Size   Complexity  
A getStructMethodParameter() 0 11 2
A fillClassConstants() 0 2 1
A addStructMethodAddToBody() 0 17 3
A addStructMethodGetBody() 0 3 1
A addStructMethodSetBodyReturn() 0 5 1
A getModelAttributes() 0 3 1
A addStructMethodSet() 0 9 1
A addStructMethodConstructBodyForAttribute() 0 5 2
A getStructMethodParametersValues() 0 8 2
A addStructMethodGetBodyReturn() 0 21 6
A getStructMethodParameterType() 0 6 4
A addStructMethodSetBody() 0 12 3
A fillClassMethods() 0 5 1
A getConstantAnnotationBlock() 0 2 1
A getPropertyAnnotationBlock() 0 14 3
A getStructMethodSetBodyAssignment() 0 18 4
A addStructMethodSetBodyAssignment() 0 14 4
A addStructMethodAddTo() 0 16 2
A addStructMethodConstruct() 0 9 2
A addStructMethodConstructBody() 0 11 3
A addStructMethodsSetAndGet() 0 10 2
A fillClassProperties() 0 4 2
A addStructPropertiesToAnnotationBlockParams() 0 7 2
A addStructMethodsSetAndGetAnnotationBlockFromScalar() 0 12 3
A addStructPropertiesToAnnotationBlockUses() 0 7 2
A getStructMethodsValidateUnionAnnotationBlock() 0 9 1
A getStructMethodsAddToAnnotationBlock() 0 21 3
A addStructMethodGet() 0 29 5
A getStructMethodsValidateChoiceAnnotationBlock() 0 9 1
A addStructMethodsGetAnnotationBlockFromXmlAttribute() 0 9 2
A getStructMethodsValidateLengthAnnotationBlock() 0 10 1
B getStructMethodAnnotationBlock() 0 35 11
A getStructMethodsValidateArrayAnnotationBlock() 0 8 1
A getMethodAnnotationBlock() 0 3 1
B addStructMethodsSetAndGetAnnotationBlockFromStructAttribute() 0 42 11
A addStructPropertiesToAnnotationBlock() 0 5 1
A addStructMethodsGetAnnotationBlock() 0 5 1
A getStructMethodGetParameters() 0 8 2
A getStructMethodConstructAnnotationBlock() 0 8 1
A setModel() 0 7 2
A applyRules() 0 5 2
B getStructMethodsSetAndGetAnnotationBlock() 0 39 8
A addStructMethodsSetAnnotationBlock() 0 5 1

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\Model\AbstractModel;
9
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
10
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
11
use WsdlToPhp\PackageGenerator\Container\PhpElement\Property as PropertyContainer;
12
use WsdlToPhp\PackageGenerator\Container\PhpElement\Constant as ConstantContainer;
13
use WsdlToPhp\PackageGenerator\Container\Model\StructAttribute as StructAttributeContainer;
14
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
15
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
16
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
17
use WsdlToPhp\PhpGenerator\Element\PhpProperty;
18
use WsdlToPhp\PhpGenerator\Element\PhpConstant;
19
use WsdlToPhp\PackageGenerator\File\Validation\Rules;
20
use WsdlToPhp\PackageGenerator\File\Element\PhpFunctionParameter;
21
22
class Struct extends AbstractModelFile
23
{
24 105
    protected function fillClassConstants(ConstantContainer $constants): void
25
    {
26 105
    }
27
28
    protected function getConstantAnnotationBlock(PhpConstant $constant): ?PhpAnnotationBlock
29
    {
30
    }
31
32 121
    protected function getModelAttributes(): StructAttributeContainer
33
    {
34 121
        return $this->getModel()->getProperAttributes(true);
0 ignored issues
show
Bug introduced by
The method getProperAttributes() does not exist on WsdlToPhp\PackageGenerator\Model\AbstractModel. It seems like you code against a sub-type of WsdlToPhp\PackageGenerator\Model\AbstractModel such as WsdlToPhp\PackageGenerator\Model\Struct. ( Ignorable by Annotation )

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

34
        return $this->getModel()->/** @scrutinizer ignore-call */ getProperAttributes(true);
Loading history...
35
    }
36
37 121
    protected function fillClassProperties(PropertyContainer $properties): void
38
    {
39 121
        foreach ($this->getModelAttributes() as $attribute) {
40 101
            $properties->add(new PhpProperty($attribute->getCleanName(), null));
41
        }
42 121
    }
43
44 101
    protected function getPropertyAnnotationBlock(PhpProperty $property): ?PhpAnnotationBlock
45
    {
46 101
        $annotationBlock = new PhpAnnotationBlock();
47 101
        $annotationBlock->addChild(sprintf('The %s', $property->getName()));
48 101
        $attribute = $this->getModel()->getAttribute($property->getName());
0 ignored issues
show
Bug introduced by
The method getAttribute() does not exist on WsdlToPhp\PackageGenerator\Model\AbstractModel. It seems like you code against a sub-type of WsdlToPhp\PackageGenerator\Model\AbstractModel such as WsdlToPhp\PackageGenerator\Model\Struct. ( Ignorable by Annotation )

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

48
        $attribute = $this->getModel()->/** @scrutinizer ignore-call */ getAttribute($property->getName());
Loading history...
49 101
        if (!$attribute instanceof StructAttributeModel) {
50 2
            $attribute = $this->getModel()->getAttributeByCleanName($property->getName());
0 ignored issues
show
Bug introduced by
The method getAttributeByCleanName() does not exist on WsdlToPhp\PackageGenerator\Model\AbstractModel. It seems like you code against a sub-type of WsdlToPhp\PackageGenerator\Model\AbstractModel such as WsdlToPhp\PackageGenerator\Model\Struct. ( Ignorable by Annotation )

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

50
            $attribute = $this->getModel()->/** @scrutinizer ignore-call */ getAttributeByCleanName($property->getName());
Loading history...
51
        }
52 101
        if ($attribute instanceof StructAttributeModel) {
53 101
            $this->defineModelAnnotationsFromWsdl($annotationBlock, $attribute);
54 101
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_VAR, $this->getStructAttributeTypeSetAnnotation($attribute, true)));
55
        }
56
57 101
        return $annotationBlock;
58
    }
59
60 105
    protected function fillClassMethods(): void
61
    {
62
        $this
63 105
            ->addStructMethodConstruct()
64 105
            ->addStructMethodsSetAndGet();
65 105
    }
66
67 105
    protected function addStructMethodConstruct(): self
68
    {
69 105
        if (0 < count($parameters = $this->getStructMethodParametersValues())) {
70 101
            $method = new PhpMethod(self::METHOD_CONSTRUCT, $parameters);
71 101
            $this->addStructMethodConstructBody($method);
72 101
            $this->methods->add($method);
73
        }
74
75 105
        return $this;
76
    }
77
78 101
    protected function addStructMethodConstructBody(PhpMethod $method): self
79
    {
80 101
        $count = $this->getModelAttributes()->count();
81 101
        foreach ($this->getModelAttributes() as $index => $attribute) {
82 101
            if (0 === $index) {
83 101
                $method->addChild('$this');
84
            }
85 101
            $this->addStructMethodConstructBodyForAttribute($method, $attribute, $count - 1 === $index);
86
        }
87
88 101
        return $this;
89
    }
90
91 101
    protected function addStructMethodConstructBodyForAttribute(PhpMethod $method, StructAttributeModel $attribute, bool $isLast): self
92
    {
93 101
        $uniqueString = $attribute->getUniqueString($attribute->getCleanName(), 'method');
94 101
        $method->addChild($method->getIndentedString(sprintf('->%s($%s)%s', $attribute->getSetterName(), lcfirst($uniqueString), $isLast ? ';' : ''), 1));
95 101
        return $this;
96
    }
97
98 105
    protected function getStructMethodParametersValues(): array
99
    {
100 105
        $parametersValues = [];
101 105
        foreach ($this->getModelAttributes() as $attribute) {
102 101
            $parametersValues[] = $this->getStructMethodParameter($attribute);
103
        }
104
105 105
        return $parametersValues;
106
    }
107
108 101
    protected function getStructMethodParameter(StructAttributeModel $attribute): PhpFunctionParameter
109
    {
110
        try {
111 101
            return new PhpFunctionParameter(
112 101
                lcfirst($attribute->getUniqueString($attribute->getCleanName(), 'method')),
113 101
                $attribute->getDefaultValue(),
114 101
                $this->getStructMethodParameterType($attribute),
115
                $attribute
116
            );
117
        } catch (InvalidArgumentException $exception) {
118
            throw new InvalidArgumentException(sprintf('Unable to create function parameter for struct "%s" with type "%s" for attribute "%s"', $this->getModel()->getName(), var_export($this->getStructMethodParameterType($attribute), true), $attribute->getName()), __LINE__, $exception);
119
        }
120
    }
121
122 101
    protected function getStructMethodParameterType(StructAttributeModel $attribute, bool $returnArrayType = true): ?string
123
    {
124 101
        return self::getPhpType(
125 101
            $this->getStructAttributeTypeHint($attribute, $returnArrayType),
126 101
            $this->getGenerator()->getOptionXsdTypesPath(),
127 101
            $returnArrayType && ($attribute->isList() || $attribute->isArray()) ? self::TYPE_ARRAY : $this->getStructAttributeTypeAsPhpType($attribute)
128
        );
129
    }
130
131 105
    protected function addStructMethodsSetAndGet(): self
132
    {
133 105
        foreach ($this->getModelAttributes() as $attribute) {
134
            $this
135 101
                ->addStructMethodGet($attribute)
136 101
                ->addStructMethodSet($attribute)
137 101
                ->addStructMethodAddTo($attribute);
138
        }
139
140 105
        return $this;
141
    }
142
143 101
    protected function addStructMethodAddTo(StructAttributeModel $attribute): self
144
    {
145 101
        if ($attribute->isArray()) {
146 53
            $method = new PhpMethod(sprintf('addTo%s', ucfirst($attribute->getCleanName())), [
147 53
                new PhpFunctionParameter(
148 53
                    'item',
149 53
                    PhpFunctionParameter::NO_VALUE,
150 53
                    $this->getStructMethodParameterType($attribute, false),
151
                    $attribute
152
                ),
153 53
            ], 'self');
154 53
            $this->addStructMethodAddToBody($method, $attribute);
155 53
            $this->methods->add($method);
156
        }
157
158 101
        return $this;
159
    }
160
161 53
    protected function addStructMethodAddToBody(PhpMethod $method, StructAttributeModel $attribute): self
162
    {
163 53
        if ($this->getGenerator()->getOptionValidation()) {
164 52
            $this->applyRules($method, $attribute, 'item', true);
165
        }
166
167 53
        if ($attribute->nameIsClean()) {
168 53
            $assignment = sprintf('$this->%s[] = $item;', $attribute->getCleanName());
169
        } else {
170
            $assignment = sprintf('$this->%s[] = $this->{\'%s\'}[] = $item;', $attribute->getCleanName(), addslashes($attribute->getName()), $attribute->getCleanName());
171
        }
172
173
        $method
174 53
            ->addChild($assignment)
175 53
            ->addChild('return $this;');
176
177 53
        return $this;
178
    }
179
180 101
    protected function addStructMethodSet(StructAttributeModel $attribute): self
181
    {
182 101
        $method = new PhpMethod($attribute->getSetterName(), [
183 101
            $this->getStructMethodParameter($attribute),
184 101
        ], 'self');
185 101
        $this->addStructMethodSetBody($method, $attribute);
186 101
        $this->methods->add($method);
187
188 101
        return $this;
189
    }
190
191 101
    protected function addStructMethodSetBody(PhpMethod $method, StructAttributeModel $attribute): self
192
    {
193 101
        $parameters = $method->getParameters();
194 101
        $parameter = array_shift($parameters);
195 101
        $parameterName = is_string($parameter) ? $parameter : $parameter->getName();
196 101
        if ($this->getGenerator()->getOptionValidation()) {
197 98
            $this->applyRules($method, $attribute, $parameterName);
198
        }
199
200
        return $this
201 101
            ->addStructMethodSetBodyAssignment($method, $attribute, $parameterName)
202 101
            ->addStructMethodSetBodyReturn($method);
203
    }
204
205 101
    protected function addStructMethodSetBodyAssignment(PhpMethod $method, StructAttributeModel $attribute, string $parameterName): self
206
    {
207 101
        if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
208
            $method
209 18
                ->addChild(sprintf('if (is_null($%1$s) || (is_array($%1$s) && empty($%1$s))) {', $parameterName))
210 18
                ->addChild($method->getIndentedString(sprintf('unset($this->%1$s%2$s);', $attribute->getCleanName(), $attribute->nameIsClean() ? '' : sprintf(', $this->{\'%s\'}', addslashes($attribute->getName()))), 1))
211 18
                ->addChild('} else {')
212 18
                ->addChild($method->getIndentedString($this->getStructMethodSetBodyAssignment($attribute, $parameterName), 1))
213 18
                ->addChild('}');
214
        } else {
215 97
            $method->addChild($this->getStructMethodSetBodyAssignment($attribute, $parameterName));
216
        }
217
218 101
        return $this;
219
    }
220
221 101
    protected function addStructMethodSetBodyReturn(PhpMethod $method): self
222
    {
223 101
        $method->addChild('return $this;');
224
225 101
        return $this;
226
    }
227
228 101
    protected function getStructMethodSetBodyAssignment(StructAttributeModel $attribute, string $parameterName): string
229
    {
230 101
        $prefix = '$';
231 101
        if ($this->isAttributeAList($attribute)) {
232 6
            $prefix = '';
233 6
            $parameterName = sprintf('is_array($%1$s) ? implode(\' \', $%1$s) : null', $parameterName);
234 101
        } elseif ($attribute->isXml()) {
235 2
            $prefix = '';
236 2
            $parameterName = sprintf('($%1$s instanceof \DOMDocument) && $%1$s->hasChildNodes() ? $%1$s->saveXML($%1$s->childNodes->item(0)) : null', $parameterName);
237
        }
238
239 101
        if ($attribute->nameIsClean()) {
240 101
            $assignment = sprintf('$this->%s = %s%s;', $attribute->getName(), $prefix, $parameterName);
241
        } else {
242 2
            $assignment = sprintf('$this->%s = $this->{\'%s\'} = %s%s;', $attribute->getCleanName(), addslashes($attribute->getName()), $prefix, $parameterName);
243
        }
244
245 101
        return $assignment;
246
    }
247
248 101
    protected function addStructMethodGetBody(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self
249
    {
250 101
        return $this->addStructMethodGetBodyReturn($method, $attribute, $thisAccess);
251
    }
252
253 101
    protected function addStructMethodGetBodyReturn(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self
254
    {
255 101
        $return = sprintf('return $this->%s;', $thisAccess);
256 101
        if ($attribute->isXml()) {
257
            $method
258 2
                ->addChild('$domDocument = null;')
259 2
                ->addChild(sprintf('if (!empty($this->%1$s) && !$asString) {', $thisAccess))
260 2
                ->addChild($method->getIndentedString('$domDocument = new \DOMDocument(\'1.0\', \'UTF-8\');', 1))
261 2
                ->addChild($method->getIndentedString(sprintf('$domDocument->loadXML($this->%s);', $thisAccess), 1))
262 2
                ->addChild('}');
263 2
            if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
264
                $return = sprintf('return $asString ? (isset($this->%1$s) ? $this->%1$s : null) : $domDocument;', $thisAccess);
265
            } else {
266 2
                $return = sprintf('return $asString ? $this->%1$s : $domDocument;', $thisAccess);
267
            }
268 101
        } elseif ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) {
269 18
            $return = sprintf('return isset($this->%1$s) ? $this->%1$s : null;', $thisAccess);
270
        }
271 101
        $method->addChild($return);
272
273 101
        return $this;
274
    }
275
276 101
    protected function addStructMethodGet(StructAttributeModel $attribute): self
277
    {
278
        switch (true) {
279 101
            case $attribute->isArray() || $attribute->isList():
280 57
                $returnType = '?'.self::TYPE_ARRAY;
281 57
                break;
282
            // it can either be a string, a DOMDocument or null...
283 85
            case $attribute->isXml():
284 2
                $returnType = '';
285 2
                break;
286
            default:
287 85
                $returnType = '?'.$this->getStructAttributeTypeAsPhpType($attribute);
288 85
                break;
289
        }
290
291 101
        $method = new PhpMethod(
292 101
            $attribute->getGetterName(),
293 101
            $this->getStructMethodGetParameters($attribute),
294
            $returnType
295
        );
296 101
        if ($attribute->nameIsClean()) {
297 101
            $thisAccess = sprintf('%s', $attribute->getName());
298
        } else {
299 2
            $thisAccess = sprintf('{\'%s\'}', addslashes($attribute->getName()));
300
        }
301 101
        $this->addStructMethodGetBody($method, $attribute, $thisAccess);
302 101
        $this->methods->add($method);
303
304 101
        return $this;
305
    }
306
307 101
    protected function getStructMethodGetParameters(StructAttributeModel $attribute): array
308
    {
309 101
        $parameters = [];
310 101
        if ($attribute->isXml()) {
311 2
            $parameters[] = new PhpFunctionParameter('asString', true, self::TYPE_BOOL, $attribute);
312
        }
313
314 101
        return $parameters;
315
    }
316
317 101
    protected function getMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
318
    {
319 101
        return $this->getStructMethodAnnotationBlock($method);
320
    }
321
322 101
    protected function getStructMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
323
    {
324 101
        $annotationBlock = null;
325 101
        switch ($method->getName()) {
326 101
            case self::METHOD_CONSTRUCT:
327 101
                $annotationBlock = $this->getStructMethodConstructAnnotationBlock();
328 101
                break;
329 101
            case 0 === mb_strpos($method->getName(), 'get'):
330 101
            case 0 === mb_strpos($method->getName(), 'set'):
331 101
                $annotationBlock = $this->getStructMethodsSetAndGetAnnotationBlock($method);
332 101
                break;
333 67
            case 0 === mb_strpos($method->getName(), 'addTo'):
334 53
                $annotationBlock = $this->getStructMethodsAddToAnnotationBlock($method);
335 53
                break;
336 66
            case false !== mb_strpos($method->getName(), 'ForUnionConstraintsFrom'):
337 4
                $annotationBlock = $this->getStructMethodsValidateUnionAnnotationBlock($method);
338 4
                break;
339 62
            case false !== mb_strpos($method->getName(), 'ForArrayConstraintsFrom'):
340 56
                $annotationBlock = $this->getStructMethodsValidateArrayAnnotationBlock($method);
341 56
                break;
342 12
            case false !== mb_strpos($method->getName(), 'ForChoiceConstraintsFrom'):
343 8
                $annotationBlock = $this->getStructMethodsValidateChoiceAnnotationBlock($method);
344 8
                break;
345 4
            case false !== mb_strpos($method->getName(), 'MaxLengthConstraintFrom'):
346 4
                $annotationBlock = $this->getStructMethodsValidateLengthAnnotationBlock($method, 'max');
347 4
                break;
348 4
            case false !== mb_strpos($method->getName(), 'MinLengthConstraintFrom'):
349 4
                $annotationBlock = $this->getStructMethodsValidateLengthAnnotationBlock($method, 'min');
350 4
                break;
351
            case false !== mb_strpos($method->getName(), 'LengthConstraintFrom'):
352
                $annotationBlock = $this->getStructMethodsValidateLengthAnnotationBlock($method);
353
                break;
354
        }
355
356 101
        return $annotationBlock;
357
    }
358
359 101
    protected function getStructMethodConstructAnnotationBlock(): PhpAnnotationBlock
360
    {
361 101
        $annotationBlock = new PhpAnnotationBlock([
362 101
            sprintf('Constructor method for %s', $this->getModel()->getName()),
363
        ]);
364 101
        $this->addStructPropertiesToAnnotationBlock($annotationBlock);
365
366 101
        return $annotationBlock;
367
    }
368
369 101
    protected function getStructMethodsSetAndGetAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
370
    {
371 101
        $parameters = $method->getParameters();
372 101
        $setOrGet = mb_strtolower(mb_substr($method->getName(), 0, 3));
373 101
        $parameter = array_shift($parameters);
374
        /**
375
         * Only set parameter must be based on a potential PhpFunctionParameter
376
         */
377 101
        if ($parameter instanceof PhpFunctionParameter && 'set' === $setOrGet) {
378 101
            $parameterName = ucfirst($parameter->getName());
379
        } else {
380 101
            $parameterName = mb_substr($method->getName(), 3);
381
        }
382
        /**
383
         * 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
384
         */
385 101
        $parameterName = preg_replace('/(_\d+)/', '', $parameterName);
386 101
        $attribute = $this->getModel()->getAttribute($parameterName);
387 101
        if (!$attribute instanceof StructAttributeModel) {
388 41
            $attribute = $this->getModel()->getAttributeByCleanName($parameterName);
389
        }
390 101
        if (!$attribute instanceof StructAttributeModel) {
391 41
            $parameterName = lcfirst($parameterName);
392 41
            $attribute = $this->getModel()->getAttribute($parameterName);
393 41
            if (!$attribute instanceof StructAttributeModel) {
394 4
                $attribute = $this->getModel()->getAttributeByCleanName($parameterName);
395
            }
396
        }
397 101
        $setValueAnnotation = '%s %s value';
398 101
        $annotationBlock = new PhpAnnotationBlock();
399 101
        if ($attribute instanceof StructAttributeModel) {
400 101
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), $parameterName));
401 101
            $this->addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, $annotationBlock, $attribute);
402
        } elseif (empty($attribute)) {
403 2
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), lcfirst($parameterName)));
404 2
            $this->addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, $annotationBlock, $parameterName);
405
        }
406
407 101
        return $annotationBlock;
408
    }
409
410 101
    protected function addStructMethodsSetAndGetAnnotationBlockFromStructAttribute(string $setOrGet, PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self
411
    {
412 101
        switch ($setOrGet) {
413 101
            case 'set':
414 101
                if ($attribute->getRemovableFromRequest()) {
415 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');
416
                }
417 101
                if ($attribute->isAChoice()) {
418 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');
419
                }
420 101
                if ($attribute->isXml()) {
421
                    $annotationBlock
422 2
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::hasChildNodes()'))
423 2
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::saveXML()'))
424 2
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMNode::item()'));
425
                }
426 101
                if ($this->getGenerator()->getOptionValidation()) {
427 98
                    if ($attribute->isAChoice()) {
428 8
                        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'));
429
                    }
430 98
                    if (($model = $this->getRestrictionFromStructAttribute($attribute)) instanceof StructModel) {
431
                        $annotationBlock
432 46
                            ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
433 46
                            ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)))
434 46
                            ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'));
435 96
                    } elseif ($attribute->isArray()) {
436 50
                        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'));
437
                    }
438
                }
439 101
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeSetAnnotation($attribute), lcfirst($attribute->getCleanName()));
440 101
                break;
441 101
            case 'get':
442 101
                if ($attribute->getRemovableFromRequest()) {
443 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)');
444
                }
445
                $this
446 101
                    ->addStructMethodsGetAnnotationBlockFromXmlAttribute($annotationBlock, $attribute)
447 101
                    ->addStructMethodsGetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeGetAnnotation($attribute));
448 101
                break;
449
        }
450
451 101
        return $this;
452
    }
453
454 2
    protected function addStructMethodsSetAndGetAnnotationBlockFromScalar(string $setOrGet, PhpAnnotationBlock $annotationBlock, string $attributeName): self
455
    {
456 2
        switch ($setOrGet) {
457 2
            case 'set':
458 2
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, lcfirst($attributeName), lcfirst($attributeName));
459 2
                break;
460 2
            case 'get':
461 2
                $this->addStructMethodsGetAnnotationBlock($annotationBlock, lcfirst($attributeName));
462 2
                break;
463
        }
464
465 2
        return $this;
466
    }
467
468 101
    protected function addStructMethodsSetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $type, string $name): self
469
    {
470 101
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $type, $name)))->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)));
471
472 101
        return $this;
473
    }
474
475 101
    protected function addStructMethodsGetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $attributeType): self
476
    {
477 101
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $attributeType));
478
479 101
        return $this;
480
    }
481
482 101
    protected function addStructMethodsGetAnnotationBlockFromXmlAttribute(PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self
483
    {
484 101
        if ($attribute->isXml()) {
485
            $annotationBlock
486 2
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::loadXML()'))
487 2
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, 'bool $asString true: returns XML string, false: returns \DOMDocument'));
488
        }
489
490 101
        return $this;
491
    }
492
493 101
    protected function addStructPropertiesToAnnotationBlock(PhpAnnotationBlock $annotationBlock): self
494
    {
495
        return $this
496 101
            ->addStructPropertiesToAnnotationBlockUses($annotationBlock)
497 101
            ->addStructPropertiesToAnnotationBlockParams($annotationBlock);
498
    }
499
500 101
    protected function addStructPropertiesToAnnotationBlockUses(PhpAnnotationBlock $annotationBlock): self
501
    {
502 101
        foreach ($this->getModelAttributes() as $attribute) {
503 101
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(), $attribute->getSetterName())));
504
        }
505
506 101
        return $this;
507
    }
508
509 101
    protected function addStructPropertiesToAnnotationBlockParams(PhpAnnotationBlock $annotationBlock): self
510
    {
511 101
        foreach ($this->getModelAttributes() as $attribute) {
512 101
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $this->getStructAttributeTypeSetAnnotation($attribute), lcfirst($attribute->getCleanName()))));
513
        }
514
515 101
        return $this;
516
    }
517
518 53
    protected function getStructMethodsAddToAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
519
    {
520 53
        $methodParameters = $method->getParameters();
521 53
        $firstParameter = array_shift($methodParameters);
522 53
        $attribute = $this->getModel()->getAttribute($firstParameter->getModel()->getName());
523 53
        $annotationBlock = new PhpAnnotationBlock();
524 53
        if ($attribute instanceof StructAttributeModel) {
525 53
            $model = $this->getRestrictionFromStructAttribute($attribute);
526 53
            $annotationBlock->addChild(sprintf('Add item to %s value', $attribute->getCleanName()));
527 53
            if ($model instanceof StructModel) {
528
                $annotationBlock
529 9
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
530 9
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)));
531
            }
532
            $annotationBlock
533 53
                ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'))
534 53
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $item', $this->getStructAttributeTypeSetAnnotation($attribute, false))))
535 53
                ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)));
536
        }
537
538 53
        return $annotationBlock;
539
    }
540
541 56
    protected function getStructMethodsValidateArrayAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
542
    {
543 56
        $methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), 'ForArrayConstraintsFrom') + mb_strlen('ForArrayConstraintsFrom')));
544 56
        return new PhpAnnotationBlock([
545 56
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the values passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
546 56
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
547 56
            new PhpAnnotation(self::ANNOTATION_PARAM, 'array $values'),
548 56
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'),
549
        ]);
550
    }
551
552 4
    protected function getStructMethodsValidateUnionAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
553
    {
554 4
        $methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), 'ForUnionConstraintsFrom') + mb_strlen('ForUnionConstraintsFrom')));
555 4
        return new PhpAnnotationBlock([
556 4
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the value passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
557 4
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
558 4
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This is a set of validation rules based on the union types associated to the property being set by the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
559 4
            new PhpAnnotation(self::ANNOTATION_PARAM, 'mixed $value'),
560 4
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'),
561
        ]);
562
    }
563
564 8
    protected function getStructMethodsValidateChoiceAnnotationBlock(PhpMethod $method): PhpAnnotationBlock
565
    {
566 8
        $methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), 'ForChoiceConstraintsFrom') + mb_strlen('ForChoiceConstraintsFrom')));
567 8
        return new PhpAnnotationBlock([
568 8
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the value passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
569 8
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
570 8
            new PhpAnnotation(PhpAnnotation::NO_NAME, 'This has to validate that the property which is being set is the only one among the given choices', self::ANNOTATION_LONG_LENGTH),
571 8
            new PhpAnnotation(self::ANNOTATION_PARAM, 'mixed $value'),
572 8
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'),
573
        ]);
574
    }
575
576 4
    protected function getStructMethodsValidateLengthAnnotationBlock(PhpMethod $method, string $type = ''): PhpAnnotationBlock
577
    {
578 4
        $replace = sprintf('%sLengthConstraintFrom', ucfirst($type));
579 4
        $methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), $replace) + mb_strlen($replace)));
580 4
        return new PhpAnnotationBlock([
581 4
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the value passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
582 4
            new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH),
583 4
            new PhpAnnotation(PhpAnnotation::NO_NAME, 'This has to validate that the items contained by the array match the length constraint', self::ANNOTATION_LONG_LENGTH),
584 4
            new PhpAnnotation(self::ANNOTATION_PARAM, 'mixed $values'),
585 4
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'),
586
        ]);
587
    }
588
589 131
    public function setModel(AbstractModel $model): self
590
    {
591 131
        if (!$model instanceof StructModel) {
592 2
            throw new InvalidArgumentException('Model must be an instance of a Struct', __LINE__);
593
        }
594
595 129
        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...
596
    }
597
598 98
    protected function applyRules(PhpMethod $method, StructAttributeModel $attribute, string $parameterName, bool $itemType = false): void
599
    {
600 98
        if ($this->getGenerator()->getOptionValidation()) {
601 98
            $rules = new Rules($this, $method, $attribute, $this->methods);
602 98
            $rules->applyRules($parameterName, $itemType);
603
        }
604 98
    }
605
}
606