Completed
Push — develop ( 695f05...cce551 )
by Mikaël
98:14 queued 95:30
created

Struct   F

Complexity

Total Complexity 98

Size/Duplication

Total Lines 672
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Test Coverage

Coverage 96.54%

Importance

Changes 9
Bugs 4 Features 3
Metric Value
wmc 98
c 9
b 4
f 3
lcom 1
cbo 12
dl 0
loc 672
ccs 335
cts 347
cp 0.9654
rs 3.6199

46 Methods

Rating   Name   Duplication   Size   Complexity  
A getClassConstants() 0 3 1
A getConstantAnnotationBlock() 0 3 1
A getModelAttributes() 0 4 1
A getClassProperties() 0 8 3
A getPropertyAnnotationBlock() 0 10 2
A getClassMethods() 0 7 1
A addStructMethodConstruct() 0 7 1
A addStructMethodConstructBody() 0 11 3
A addStructMethodConstructBodyForAttribute() 0 5 2
A getStructMethodParametersValues() 0 8 2
A getStructMethodParameter() 0 8 4
A getStructMethodParameterType() 0 4 1
A addStructMethodsSetAndGet() 0 10 2
A addStructMethodAddTo() 0 11 2
A addStructMethodAddToBody() 0 12 2
A addStructMethodSetBodyForAnyType() 0 8 1
A addStructMethodSet() 0 9 1
A addStructMethodSetBody() 0 11 2
A addStructMethodSetBodyAssignment() 0 5 1
A addStructMethodSetBodyReturn() 0 5 1
A addStructMethodSetBodyForRestriction() 0 11 3
B addStructMethodSetBodyForArray() 0 27 3
B getStructMethodSetBodyForArrayItemSanityCheck() 0 24 6
A getStructMethodSetBodyAssignment() 0 9 2
A addStructMethodGetBody() 0 6 1
A addStructMethodGetBodyForXml() 0 15 2
A addStructMethodGetBodyReturn() 0 9 2
A addStructMethodGet() 0 12 2
A getStructMethodGetParameters() 0 8 2
A addStructMethodSetState() 0 9 1
A getMethodAnnotationBlock() 0 4 1
B getStructMethodAnnotationBlock() 0 20 6
A getStructMethodConstructAnnotationBlock() 0 8 1
A getStructMethodSetStateAnnotationBlock() 0 11 1
B getStructMethodsSetAndGetAnnotationBlock() 0 29 6
B addStructMethodsSetAndGetAnnotationBlockFromStructAttribute() 0 21 6
A addStructMethodsSetAndGetAnnotationBlockFromScalar() 0 12 3
A addStructMethodsSetAnnotationBlock() 0 7 1
A addStructMethodsGetAnnotationBlock() 0 5 1
A addStructMethodsGetAnnotationBlockFromXmlAttribute() 0 12 2
A addStructPropertiesToAnnotationBlock() 0 6 1
A addStructPropertiesToAnnotationBlockUses() 0 7 2
A addStructPropertiesToAnnotationBlockParams() 0 7 2
B getStructMethodsAddToAnnotationBlock() 0 23 4
A getModel() 0 4 1
A setModel() 0 7 2

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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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
namespace WsdlToPhp\PackageGenerator\File;
4
5
use WsdlToPhp\PackageGenerator\Model\AbstractModel;
6
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
7
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
8
use WsdlToPhp\PackageGenerator\Container\PhpElement\Method as MethodContainer;
9
use WsdlToPhp\PackageGenerator\Container\PhpElement\Property as PropertyContainer;
10
use WsdlToPhp\PackageGenerator\Container\PhpElement\Constant as ConstantContainer;
11
use WsdlToPhp\PackageGenerator\Container\Model\StructAttribute as StructAttributeContainer;
12
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
13
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
14
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
15
use WsdlToPhp\PhpGenerator\Element\PhpProperty;
16
use WsdlToPhp\PhpGenerator\Element\PhpConstant;
17
use WsdlToPhp\PhpGenerator\Element\PhpFunctionParameter;
18
19
class Struct extends AbstractModelFile
20
{
21
    /**
22
     * @see \WsdlToPhp\PackageGenerator\File\AbstractModelFile::getClassConstants()
23
     */
24 80
    protected function getClassConstants(ConstantContainer $constants)
25
    {
26 80
    }
27
    /**
28
     * @see \WsdlToPhp\PackageGenerator\File\AbstractModelFile::getConstantAnnotationBlock()
29
     */
30
    protected function getConstantAnnotationBlock(PhpConstant $constant)
31
    {
32
    }
33
    /**
34
     * @param bool $includeInheritanceAttributes include the attributes of parent class, default parent attributes are not included. If true, then the array is an associative array containing and index "attribute" for the StructAttribute object and an index "model" for the Struct object.
35
     * @param bool $requiredFirst places the required attributes first, then the not required in order to have the _contrust method with the required attribute at first
36
     * @return StructAttributeContainer
37
     */
38 80
    protected function getModelAttributes($includeInheritanceAttributes = false, $requiredFirst = true)
39
    {
40 80
        return $this->getModel()->getAttributes($includeInheritanceAttributes, $requiredFirst);
41
    }
42
    /**
43
     * @param PropertyContainer
44
     */
45 108
    protected function getClassProperties(PropertyContainer $properties)
46
    {
47 108
        if ($this->getModel()->getAttributes()->count() > 0) {
48 80
            foreach ($this->getModelAttributes() as $attribute) {
49 80
                $properties->add(new PhpProperty($attribute->getCleanName(), PhpProperty::NO_VALUE));
50 80
            }
51 80
        }
52 108
    }
53
    /**
54
     * @return PhpAnnotationBlock
55
     */
56 80
    protected function getPropertyAnnotationBlock(PhpProperty $property)
57
    {
58 80
        $annotationBlock = new PhpAnnotationBlock();
59 80
        $annotationBlock->addChild(sprintf('The %s', $property->getName()));
60 80
        if (($attribute = $this->getModel()->getAttribute($property->getName())) instanceof StructAttributeModel) {
61 80
            $this->defineModelAnnotationsFromWsdl($annotationBlock, $attribute);
62 80
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_VAR, $this->getStructAttributeTypeSetAnnotation($attribute, true)));
63 80
        }
64 80
        return $annotationBlock;
65
    }
66
    /**
67
     * @param MethodContainer
68
     */
69 80
    protected function getClassMethods(MethodContainer $methods)
70
    {
71 80
        $this
72 80
            ->addStructMethodConstruct($methods)
73 80
            ->addStructMethodsSetAndGet($methods)
74 80
            ->addStructMethodSetState($methods);
75 80
    }
76
    /**
77
     * @param MethodContainer $methods
78
     * @return Struct
79
     */
80 80
    protected function addStructMethodConstruct(MethodContainer $methods)
81
    {
82 80
        $method = new PhpMethod(self::METHOD_CONSTRUCT, $this->getStructMethodParametersValues());
83 80
        $this->addStructMethodConstructBody($method);
84 80
        $methods->add($method);
85 80
        return $this;
86
    }
87
    /**
88
     * @param PhpMethod $method
89
     * @return Struct
90
     */
91 80
    protected function addStructMethodConstructBody(PhpMethod $method)
92
    {
93 80
        $count = $this->getModelAttributes()->count();
94 80
        foreach ($this->getModelAttributes() as $index=>$attribute) {
95 80
            if ($index === 0) {
96 80
                $method->addChild('$this');
97 80
            }
98 80
            $this->addStructMethodConstructBodyForAttribute($method, $attribute, $count - 1 === $index);
99 80
        }
100 80
        return $this;
101
    }
102
    /**
103
     * @param PhpMethod $method
104
     * @param StructAttributeModel $attribute
105
     * @param bool $isLast
106
     * @return Struct
107
     */
108 80
    protected function addStructMethodConstructBodyForAttribute(PhpMethod $method, StructAttributeModel $attribute, $isLast)
109
    {
110 80
        $method->addChild($method->getIndentedString(sprintf('->%s($%s)%s', $attribute->getSetterName(), lcfirst($attribute->getCleanName()), $isLast ? ';' : ''), 1));
111 80
        return $this;
112
    }
113
    /**
114
     * @return PhpFunctionParameter[]
115
     */
116 80
    protected function getStructMethodParametersValues()
117
    {
118 80
        $parametersValues = array();
119 80
        foreach ($this->getModelAttributes() as $attribute) {
120 80
            $parametersValues[] = $this->getStructMethodParameter($attribute, true);
121 80
        }
122 80
        return $parametersValues;
123
    }
124
    /**
125
     * @param StructAttributeModel $attribute
126
     * @param bool $lowCaseFirstLetter
127
     * @param mixed $defaultValue
128
     * @return PhpFunctionParameter
129
     */
130 80
    protected function getStructMethodParameter(StructAttributeModel $attribute, $lowCaseFirstLetter = false, $defaultValue = null)
131
    {
132
        try {
133 80
            return new PhpFunctionParameter($lowCaseFirstLetter ? lcfirst($attribute->getCleanName()) : $attribute->getCleanName(), isset($defaultValue) ? $defaultValue : $attribute->getDefaultValue(), $this->getStructMethodParameterType($attribute));
134
        } catch (\InvalidArgumentException $exception) {
135
            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);
136
        }
137
    }
138
    /**
139
     * @param StructAttributeModel $attribute
140
     * @param bool $returnArrayType
141
     * @return string|null
142
     */
143 80
    protected function getStructMethodParameterType(StructAttributeModel $attribute, $returnArrayType = true)
144
    {
145 80
        return self::getValidType($this->getStructAttributeTypeHint($attribute, $returnArrayType), null);
146
    }
147
    /**
148
     * @param MethodContainer $methods
149
     * @return Struct
150
     */
151 80
    protected function addStructMethodsSetAndGet(MethodContainer $methods)
152
    {
153 80
        foreach ($this->getModelAttributes() as $attribute) {
154 80
            $this
155 80
                ->addStructMethodGet($methods, $attribute)
156 80
                ->addStructMethodSet($methods, $attribute)
157 80
                ->addStructMethodAddTo($methods, $attribute);
158 80
        }
159 80
        return $this;
160
    }
161
    /**
162
     * @param MethodContainer $methods
163
     * @param StructAttributeModel $attribute
164
     * @return Struct
165
     */
166 80
    protected function addStructMethodAddTo(MethodContainer $methods, StructAttributeModel $attribute)
167
    {
168 80
        if ($attribute->isArray()) {
169 44
            $method = new PhpMethod(sprintf('addTo%s', ucfirst($attribute->getCleanName())), array(
170 44
                new PhpFunctionParameter('item', PhpFunctionParameter::NO_VALUE, $this->getStructMethodParameterType($attribute, false)),
171 44
            ));
172 44
            $this->addStructMethodAddToBody($method, $attribute);
173 44
            $methods->add($method);
174 44
        }
175 80
        return $this;
176
    }
177
    /**
178
     * @param PhpMethod $method
179
     * @param StructAttributeModel $attribute
180
     * @return Struct
181
     */
182 44
    protected function addStructMethodAddToBody(PhpMethod $method, StructAttributeModel $attribute)
183
    {
184 44
        if ($this->getRestrictionFromStructAttribute($attribute) instanceof StructModel) {
185 16
            $this->addStructMethodSetBodyForRestriction($method, $attribute, 'item');
186 16
        } else {
187 40
            $this->addStructMethodSetBodyForAnyType($method, $attribute);
188
        }
189
        $method
190 44
            ->addChild(sprintf('$this->%s[] = $item;', $attribute->getCleanName()))
191 44
            ->addChild('return $this;');
192 44
        return $this;
193
    }
194
    /**
195
     * @param PhpMethod $method
196
     * @param StructAttributeModel $attribute
197
     * @return Struct
198
     */
199 40
    protected function addStructMethodSetBodyForAnyType(PhpMethod $method, StructAttributeModel $attribute)
200
    {
201
        $method
202 40
            ->addChild(sprintf('if (!%s) {', $this->getStructMethodSetBodyForArrayItemSanityCheck($attribute)))
203 40
                ->addChild($method->getIndentedString(sprintf('throw new \InvalidArgumentException(sprintf(\'The %s property can only contain items of %s, "%%s" given\', is_object($item) ? get_class($item) : gettype($item)), __LINE__);', $attribute->getCleanName(), $this->getStructAttributeType($attribute, true)), 1))
204 40
            ->addChild('}');
205 40
        return $this;
206
    }
207
    /**
208
     * @param MethodContainer $methods
209
     * @param StructAttributeModel $attribute
210
     * @return Struct
211
     */
212 80
    protected function addStructMethodSet(MethodContainer $methods, StructAttributeModel $attribute)
213
    {
214 80
        $method = new PhpMethod($attribute->getSetterName(), array(
215 80
            $this->getStructMethodParameter($attribute, true, null),
216 80
        ));
217 80
        $this->addStructMethodSetBody($method, $attribute);
218 80
        $methods->add($method);
219 80
        return $this;
220
    }
221
    /**
222
     * @param PhpMethod $method
223
     * @param StructAttributeModel $attribute
224
     * @return Struct
225
     */
226 80
    protected function addStructMethodSetBody(PhpMethod $method, StructAttributeModel $attribute)
227
    {
228 80
        if ($attribute->isArray()) {
229 44
            $this->addStructMethodSetBodyForArray($method, $attribute);
230 44
        } else {
231 52
            $this->addStructMethodSetBodyForRestriction($method, $attribute);
232
        }
233 80
        return $this
234 80
            ->addStructMethodSetBodyAssignment($method, $attribute)
235 80
            ->addStructMethodSetBodyReturn($method);
236
    }
237
    /**
238
     * @param PhpMethod $method
239
     * @param StructAttributeModel $attribute
240
     * @return Struct
241
     */
242 80
    protected function addStructMethodSetBodyAssignment(PhpMethod $method, StructAttributeModel $attribute)
243
    {
244 80
        $method->addChild($this->getStructMethodSetBodyAssignment($attribute));
245 80
        return $this;
246
    }
247
    /**
248
     * @param PhpMethod $method
249
     * @return Struct
250
     */
251 80
    protected function addStructMethodSetBodyReturn(PhpMethod $method)
252
    {
253 80
        $method->addChild('return $this;');
254 80
        return $this;
255
    }
256
    /**
257
     * @param PhpMethod $method
258
     * @param StructAttributeModel $attribute
259
     * @param string $parameterName
260
     * @return Struct
261
     */
262 60
    protected function addStructMethodSetBodyForRestriction(PhpMethod $method, StructAttributeModel $attribute, $parameterName = null)
263
    {
264 60
        if (($model = $this->getRestrictionFromStructAttribute($attribute)) instanceof StructModel) {
265 40
            $parameterName = empty($parameterName) ? lcfirst($attribute->getCleanName()) : $parameterName;
266
            $method
267 40
                ->addChild(sprintf('if (!%s::%s($%s)) {', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID, $parameterName))
268 40
                    ->addChild($method->getIndentedString(sprintf('throw new \InvalidArgumentException(sprintf(\'Value "%%s" is invalid, please use one of: %%s\', $%s, implode(\', \', %s::%s())), __LINE__);', $parameterName, $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES), 1))
269 40
                ->addChild('}');
270 40
        }
271 60
        return $this;
272
    }
273
    /**
274
     * @param PhpMethod $method
275
     * @param StructAttributeModel $attribute
276
     * @return Struct
277
     */
278 44
    protected function addStructMethodSetBodyForArray(PhpMethod $method, StructAttributeModel $attribute)
279
    {
280 44
        if ($attribute->isArray()) {
281 44
            $model = $this->getRestrictionFromStructAttribute($attribute);
282 44
            $parameterName = lcfirst($attribute->getCleanName());
283 44
            if ($model instanceof StructModel) {
284
                $method
285 16
                    ->addChild('$invalidValues = array();')
286 16
                    ->addChild(sprintf('foreach($%s as $item) {', $parameterName))
287 16
                        ->addChild($method->getIndentedString(sprintf('if (!%s::%s($item)) {', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID), 1))
288 16
                            ->addChild($method->getIndentedString('$invalidValues[] = var_export($item);', 2))
289 16
                        ->addChild($method->getIndentedString('}', 1))
290 16
                    ->addChild('}')
291 16
                    ->addChild('if (!empty($invalidValues)) {')
292 16
                        ->addChild($method->getIndentedString(sprintf('throw new \InvalidArgumentException(sprintf(\'Value(s) "%%s" is/are invalid, please use one of: %%s\', implode(\', \', $invalidValues), implode(\', \', %s::%s())), __LINE__);', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES), 1))
293 16
                    ->addChild('}');
294 16
            } else {
295
                $method
296 40
                    ->addChild(sprintf('foreach($%s as $item) {', $parameterName))
297 40
                        ->addChild($method->getIndentedString(sprintf('if (!%s) {', $this->getStructMethodSetBodyForArrayItemSanityCheck($attribute)), 1))
298 40
                            ->addChild($method->getIndentedString(sprintf('throw new \InvalidArgumentException(sprintf(\'The %s property can only contain items of %s, "%%s" given\', is_object($item) ? get_class($item) : gettype($item)), __LINE__);', $attribute->getCleanName(), $this->getStructAttributeType($attribute, true)), 2))
299 40
                        ->addChild($method->getIndentedString('}', 1))
300 40
                    ->addChild('}');
301
            }
302 44
        }
303 44
        return $this;
304
    }
305
    /**
306
     * The second case which used PHP native functions is volontary limited by the native functions provided by PHP,
307
     * and the possible types defined in xsd_types.yml
308
     * @param StructAttributeModel $attribute
309
     */
310 40
    protected function getStructMethodSetBodyForArrayItemSanityCheck(StructAttributeModel $attribute)
311
    {
312 40
        $model = $this->getModelFromStructAttribute($attribute);
313 40
        $sanityCheck = 'false';
314 40
        if ($model instanceof StructModel) {
315 28
            $sanityCheck = sprintf('$item instanceof %s', $this->getStructAttributeType($attribute, true));
316 28
        } else {
317 24
            switch (self::getPhpType($attribute->getType())) {
318 24
                case 'int':
319 16
                    $sanityCheck = 'is_int($item)';
320 16
                    break;
321 16
                case 'bool':
322
                    $sanityCheck = 'is_bool($item)';
323
                    break;
324 16
                case 'float':
325
                    $sanityCheck = 'is_float($item)';
326
                    break;
327 16
                case 'string':
328 16
                    $sanityCheck = 'is_string($item)';
329 16
                    break;
330 24
            }
331
        }
332 40
        return $sanityCheck;
333
    }
334
    /**
335
     * @param StructAttributeModel $attribute
336
     * @return string
337
     */
338 80
    protected function getStructMethodSetBodyAssignment(StructAttributeModel $attribute)
339
    {
340 80
        if ($attribute->nameIsClean()) {
341 80
            $assignment = sprintf('$this->%s = $%s;', $attribute->getName(), lcfirst($attribute->getCleanName()));
342 80
        } else {
343
            $assignment = sprintf('$this->%s = $this->{\'%s\'} = $%s;', $attribute->getCleanName(), addslashes($attribute->getName()), lcfirst($attribute->getCleanName()));
344
        }
345 80
        return $assignment;
346
    }
347
    /**
348
     * @param PhpMethod $method
349
     * @param StructAttributeModel $attribute
350
     * @param string $thisAccess
351
     * @return Struct
352
     */
353 80
    protected function addStructMethodGetBody(PhpMethod $method, StructAttributeModel $attribute, $thisAccess)
354
    {
355 80
        return $this
356 80
            ->addStructMethodGetBodyForXml($method, $attribute, $thisAccess)
357 80
            ->addStructMethodGetBodyReturn($method, $attribute, $thisAccess);
358
    }
359
    /**
360
     * @param PhpMethod $method
361
     * @param StructAttributeModel $attribute
362
     * @param string $thisAccess
363
     * @return Struct
364
     */
365 80
    protected function addStructMethodGetBodyForXml(PhpMethod $method, StructAttributeModel $attribute, $thisAccess)
366
    {
367 80
        if ($attribute->isXml()) {
368
            $method
369 4
                ->addChild(sprintf('if (!empty($this->%1$s) && !($this->%1$s instanceof \DOMDocument)) {', $thisAccess))
370 4
                    ->addChild($method->getIndentedString('$dom = new \DOMDocument(\'1.0\', \'UTF-8\');', 1))
371 4
                    ->addChild($method->getIndentedString('$dom->formatOutput = true;', 1))
372 4
                    ->addChild($method->getIndentedString(sprintf('if ($dom->loadXML($this->%s)) {', $thisAccess), 1))
373 4
                    ->addChild($method->getIndentedString(sprintf('$this->%s($dom);', $attribute->getSetterName()), 2))
374 4
                    ->addChild($method->getIndentedString('}', 1))
375 4
                    ->addChild($method->getIndentedString('unset($dom);', 1))
376 4
                ->addChild('}');
377 4
        }
378 80
        return $this;
379
    }
380
    /**
381
     * @param PhpMethod $method
382
     * @param StructAttributeModel $attribute
383
     * @param string $thisAccess
384
     * @return Struct
385
     */
386 80
    protected function addStructMethodGetBodyReturn(PhpMethod $method, StructAttributeModel $attribute, $thisAccess)
387
    {
388 80
        $return = sprintf('return $this->%s;', $thisAccess);
389 80
        if ($attribute->isXml()) {
390 4
            $return = sprintf('return ($asString && ($this->%1$s instanceof \DOMDocument) && $this->%1$s->hasChildNodes()) ? $this->%1$s->saveXML($this->%1$s->childNodes->item(0)) : $this->%1$s;', $thisAccess);
391 4
        }
392 80
        $method->addChild($return);
393 80
        return $this;
394
    }
395
    /**
396
     * @param MethodContainer $methods
397
     * @param StructAttributeModel $attribute
398
     * @return Struct
399
     */
400 80
    protected function addStructMethodGet(MethodContainer $methods, StructAttributeModel $attribute)
401
    {
402 80
        $method = new PhpMethod($attribute->getGetterName(), $this->getStructMethodGetParameters($attribute));
403 80
        if ($attribute->nameIsClean()) {
404 80
            $thisAccess = sprintf('%s', $attribute->getName());
405 80
        } else {
406
            $thisAccess = sprintf('{\'%s\'}', addslashes($attribute->getName()));
407
        }
408 80
        $this->addStructMethodGetBody($method, $attribute, $thisAccess);
409 80
        $methods->add($method);
410 80
        return $this;
411
    }
412
    /**
413
     * @param StructAttributeModel $attribute
414
     * @return PhpFunctionParameter[]
415
     */
416 80
    protected function getStructMethodGetParameters(StructAttributeModel $attribute)
417
    {
418 80
        $parameters = array();
419 80
        if ($attribute->isXml()) {
420 4
            $parameters[] = new PhpFunctionParameter('asString', true);
421 4
        }
422 80
        return $parameters;
423
    }
424
    /**
425
     * @param MethodContainer $methods
426
     * @return Struct
427
     */
428 80
    protected function addStructMethodSetState(MethodContainer $methods)
429
    {
430 80
        $method = new PhpMethod(self::METHOD_SET_STATE, array(
431 80
            new PhpFunctionParameter('array', PhpFunctionParameter::NO_VALUE, 'array'),
432 80
        ), PhpMethod::ACCESS_PUBLIC, false, true);
433 80
        $method->addChild(sprintf('return parent::__set_state($array);'));
434 80
        $methods->add($method);
435 80
        return $this;
436
    }
437
    /**
438
     * @return PhpAnnotationBlock|null
439
     */
440 80
    protected function getMethodAnnotationBlock(PhpMethod $method)
441
    {
442 80
        return $this->getStructMethodAnnotationBlock($method);
443
    }
444
    /**
445
     * @param PhpMethod $method
446
     * @return PhpAnnotationBlock|null
447
     */
448 80
    protected function getStructMethodAnnotationBlock(PhpMethod $method)
449
    {
450 80
        $annotationBlock = null;
451 80
        switch ($method->getName()) {
452 80
            case self::METHOD_CONSTRUCT:
453 60
                $annotationBlock = $this->getStructMethodConstructAnnotationBlock();
454 60
                break;
455 80
            case self::METHOD_SET_STATE:
456 60
                $annotationBlock = $this->getStructMethodSetStateAnnotationBlock();
457 60
                break;
458 80
            case strpos($method->getName(), 'get') === 0:
459 80
            case strpos($method->getName(), 'set') === 0:
460 80
                $annotationBlock = $this->getStructMethodsSetAndGetAnnotationBlock($method);
461 80
                break;
462 44
            case strpos($method->getName(), 'addTo') === 0:
463 44
                $annotationBlock = $this->getStructMethodsAddToAnnotationBlock($method);
464 44
                break;
465 80
        }
466 80
        return $annotationBlock;
467
    }
468
    /**
469
     * @return PhpAnnotationBlock
470
     */
471 80
    protected function getStructMethodConstructAnnotationBlock()
472
    {
473 80
        $annotationBlock = new PhpAnnotationBlock(array(
474 80
            sprintf('Constructor method for %s', $this->getModel()->getName()),
475 80
        ));
476 80
        $this->addStructPropertiesToAnnotationBlock($annotationBlock);
477 80
        return $annotationBlock;
478
    }
479
    /**
480
     * @return PhpAnnotationBlock
481
     */
482 80
    protected function getStructMethodSetStateAnnotationBlock()
483
    {
484 80
        return new PhpAnnotationBlock(array(
485 80
            'Method called when an object has been exported with var_export() functions',
486 80
            'It allows to return an object instantiated with the values',
487 80
            new PhpAnnotation(self::ANNOTATION_SEE, sprintf('%s::__set_state()', $this->getModel()->getExtends(true))),
488 80
            new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::__set_state()', $this->getModel()->getExtends(true))),
489 80
            new PhpAnnotation(self::ANNOTATION_PARAM, 'array $array the exported values'),
490 80
            new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)),
491 80
        ));
492
    }
493
    /**
494
     * @param PhpMethod $method
495
     * @return PhpAnnotationBlock
496
     */
497 80
    protected function getStructMethodsSetAndGetAnnotationBlock(PhpMethod $method)
498
    {
499 80
        $parameters = $method->getParameters();
500 80
        $setOrGet = strtolower(substr($method->getName(), 0, 3));
501 80
        $parameter = array_shift($parameters);
502
        /**
503
         * Only set parameter must be based on a potential PhpFunctionParameter
504
         */
505 80
        if ($parameter instanceof PhpFunctionParameter && $setOrGet === 'set') {
506 80
            $parameterName = ucfirst($parameter->getName());
507 80
        } else {
508 80
            $parameterName = substr($method->getName(), 3);
509
        }
510 80
        $attribute = $this->getModel()->getAttribute($parameterName);
511 80
        if (!$attribute instanceof StructAttributeModel) {
512 44
            $parameterName = lcfirst($parameterName);
513 44
            $attribute = $this->getModel()->getAttribute($parameterName);
514 44
        }
515 80
        $setValueAnnotation = '%s %s value';
516 80
        $annotationBlock = new PhpAnnotationBlock();
517 80
        if ($attribute instanceof StructAttributeModel) {
518 80
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), $parameterName));
519 80
            $this->addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, $annotationBlock, $attribute);
520 80
        } elseif (empty($attribute)) {
521 4
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), lcfirst($parameterName)));
522 4
            $this->addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, $annotationBlock, $parameterName);
523 4
        }
524 80
        return $annotationBlock;
525
    }
526
    /**
527
     * @param string $setOrGet
528
     * @param PhpAnnotationBlock $annotationBlock
529
     * @param StructAttributeModel $attribute
530
     * @return Struct
531
     */
532 80
    protected function addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute)
533
    {
534
        switch ($setOrGet) {
535 80
            case 'set':
536 80
                if (($model = $this->getRestrictionFromStructAttribute($attribute)) instanceof StructModel && !$this->getModel()->isArray()) {
537
                    $annotationBlock
538 36
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
539 36
                        ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)))
540 36
                        ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'));
541 80
                } elseif ($attribute->isArray()) {
542 44
                    $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'));
543 44
                }
544 80
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeSetAnnotation($attribute), lcfirst($attribute->getCleanName()));
545 80
                break;
546 80
            case 'get':
547 80
                $this->addStructMethodsGetAnnotationBlockFromXmlAttribute($annotationBlock, $attribute);
548 80
                $this->addStructMethodsGetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeGetAnnotation($attribute));
549 80
                break;
550
        }
551 80
        return $this;
552
    }
553
    /**
554
     * @param string $setOrGet
555
     * @param PhpAnnotationBlock $annotationBlock
556
     * @param string $attributeName
557
     * @return Struct
558
     */
559 4
    protected function addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, PhpAnnotationBlock $annotationBlock, $attributeName)
560
    {
561
        switch ($setOrGet) {
562 4
            case 'set':
563
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, lcfirst($attributeName), lcfirst($attributeName));
564
                break;
565 4
            case 'get':
566 4
                $this->addStructMethodsGetAnnotationBlock($annotationBlock, lcfirst($attributeName));
567 4
                break;
568
        }
569 4
        return $this;
570
    }
571
    /**
572
     * @param PhpAnnotationBlock $annotationBlock
573
     * @param string $type
574
     * @param string $name
575
     * @return Struct
576
     */
577 80
    protected function addStructMethodsSetAnnotationBlock(PhpAnnotationBlock $annotationBlock, $type, $name)
578
    {
579
        $annotationBlock
580 80
            ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $type, $name)))
581 80
            ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)));
582 80
        return $this;
583
    }
584
    /**
585
     * @param PhpAnnotationBlock $annotationBlock
586
     * @param string $attribute
587
     * @return Struct
588
     */
589 80
    protected function addStructMethodsGetAnnotationBlock(PhpAnnotationBlock $annotationBlock, $attribute)
590
    {
591 80
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $attribute));
592 80
        return $this;
593
    }
594
    /**
595
     * @param PhpAnnotationBlock $annotationBlock
596
     * @param StructAttributeModel $attribute
597
     */
598 80
    protected function addStructMethodsGetAnnotationBlockFromXmlAttribute(PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute)
599
    {
600 80
        if ($attribute->isXml()) {
601
            $annotationBlock
602 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::loadXML()'))
603 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::hasChildNodes()'))
604 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::saveXML()'))
605 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMNode::item()'))
606 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(true), $attribute->getSetterName())))
607 4
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, 'bool $asString true: returns XML string, false: returns \DOMDocument'));
608 4
        }
609 80
    }
610
    /**
611
     * @param PhpAnnotationBlock $annotationBlock
612
     * @return Struct
613
     */
614 80
    protected function addStructPropertiesToAnnotationBlock(PhpAnnotationBlock $annotationBlock)
615
    {
616 80
        return $this
617 80
            ->addStructPropertiesToAnnotationBlockUses($annotationBlock)
618 80
            ->addStructPropertiesToAnnotationBlockParams($annotationBlock);
619
    }
620
    /**
621
     * @param PhpAnnotationBlock $annotationBlock
622
     * @return Struct
623
     */
624 80
    protected function addStructPropertiesToAnnotationBlockUses(PhpAnnotationBlock $annotationBlock)
625
    {
626 80
        foreach ($this->getModelAttributes() as $attribute) {
627 80
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(), $attribute->getSetterName())));
628 80
        }
629 80
        return $this;
630
    }
631
    /**
632
     * @param PhpAnnotationBlock $annotationBlock
633
     * @return Struct
634
     */
635 80
    protected function addStructPropertiesToAnnotationBlockParams(PhpAnnotationBlock $annotationBlock)
636
    {
637 80
        foreach ($this->getModelAttributes() as $attribute) {
638 80
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $this->getStructAttributeTypeSetAnnotation($attribute), lcfirst($attribute->getCleanName()))));
639 80
        }
640 80
        return $this;
641
    }
642
    /**
643
     * @param PhpMethod $method
644
     * @return PhpAnnotationBlock
645
     */
646 44
    protected function getStructMethodsAddToAnnotationBlock(PhpMethod $method)
647
    {
648 44
        $attributeName = str_replace('addTo', '', $method->getName());
649 44
        $attribute = $this->getModel()->getAttribute($attributeName);
650 44
        if (!$attribute instanceof StructAttributeModel) {
651 20
            $attribute = $this->getModel()->getAttribute(lcfirst($attributeName));
652 20
        }
653 44
        $model = $this->getRestrictionFromStructAttribute($attribute);
654 44
        $annotationBlock = new PhpAnnotationBlock();
655 44
        if ($attribute instanceof StructAttributeModel) {
656 44
            $annotationBlock->addChild(sprintf('Add item to %s value', $attribute->getCleanName()));
657 44
            if ($model instanceof StructModel) {
658
                $annotationBlock
659 16
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID)))
660 16
                    ->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES)));
661 16
            }
662
            $annotationBlock
663 44
                ->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'))
664 44
                ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $item', $this->getStructAttributeTypeSetAnnotation($attribute, false))))
665 44
                ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)));
666 44
        }
667 44
        return $annotationBlock;
668
    }
669
    /**
670
     * @see \WsdlToPhp\PackageGenerator\File\AbstractModelFile::getModel()
671
     * @return StructModel
672
     */
673 128
    public function getModel()
674
    {
675 128
        return parent::getModel();
676
    }
677
    /**
678
     * @see \WsdlToPhp\PackageGenerator\File\AbstractModelFile::setModel()
679
     * @throws \InvalidaArgumentException
680
     * @param AbstractModel $model
681
     * @return StructArray
682
     */
683 128
    public function setModel(AbstractModel $model)
684
    {
685 128
        if (!$model instanceof StructModel) {
686 4
            throw new \InvalidArgumentException('Model must be an instance of a Struct', __LINE__);
687
        }
688 124
        return parent::setModel($model);
689
    }
690
}
691