Completed
Push — feature/issue-47 ( cdce8d...8413b2 )
by Mikaël
24:42
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 76
    protected function getClassConstants(ConstantContainer $constants)
25
    {
26 76
    }
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 76
    protected function getModelAttributes($includeInheritanceAttributes = false, $requiredFirst = true)
39
    {
40 76
        return $this->getModel()->getAttributes($includeInheritanceAttributes, $requiredFirst);
41
    }
42
    /**
43
     * @param PropertyContainer
44
     */
45 104
    protected function getClassProperties(PropertyContainer $properties)
46
    {
47 104
        if ($this->getModel()->getAttributes()->count() > 0) {
48 76
            foreach ($this->getModelAttributes() as $attribute) {
49 76
                $properties->add(new PhpProperty($attribute->getCleanName(), PhpProperty::NO_VALUE));
50 57
            }
51 57
        }
52 104
    }
53
    /**
54
     * @return PhpAnnotationBlock
55
     */
56 76
    protected function getPropertyAnnotationBlock(PhpProperty $property)
57
    {
58 76
        $annotationBlock = new PhpAnnotationBlock();
59 76
        $annotationBlock->addChild(sprintf('The %s', $property->getName()));
60 76
        if (($attribute = $this->getModel()->getAttribute($property->getName())) instanceof StructAttributeModel) {
61 76
            $this->defineModelAnnotationsFromWsdl($annotationBlock, $attribute);
62 76
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_VAR, $this->getStructAttributeTypeSetAnnotation($attribute, true)));
63 57
        }
64 76
        return $annotationBlock;
65
    }
66
    /**
67
     * @param MethodContainer
68
     */
69 76
    protected function getClassMethods(MethodContainer $methods)
70
    {
71 57
        $this
72 76
            ->addStructMethodConstruct($methods)
73 76
            ->addStructMethodsSetAndGet($methods)
74 76
            ->addStructMethodSetState($methods);
75 76
    }
76
    /**
77
     * @param MethodContainer $methods
78
     * @return Struct
79
     */
80 76
    protected function addStructMethodConstruct(MethodContainer $methods)
81
    {
82 76
        $method = new PhpMethod(self::METHOD_CONSTRUCT, $this->getStructMethodParametersValues());
83 76
        $this->addStructMethodConstructBody($method);
84 76
        $methods->add($method);
85 76
        return $this;
86
    }
87
    /**
88
     * @param PhpMethod $method
89
     * @return Struct
90
     */
91 76
    protected function addStructMethodConstructBody(PhpMethod $method)
92
    {
93 76
        $count = $this->getModelAttributes()->count();
94 76
        foreach ($this->getModelAttributes() as $index=>$attribute) {
95 76
            if ($index === 0) {
96 76
                $method->addChild('$this');
97 57
            }
98 76
            $this->addStructMethodConstructBodyForAttribute($method, $attribute, $count - 1 === $index);
99 57
        }
100 76
        return $this;
101
    }
102
    /**
103
     * @param PhpMethod $method
104
     * @param StructAttributeModel $attribute
105
     * @param bool $isLast
106
     * @return Struct
107
     */
108 76
    protected function addStructMethodConstructBodyForAttribute(PhpMethod $method, StructAttributeModel $attribute, $isLast)
109
    {
110 76
        $method->addChild($method->getIndentedString(sprintf('->%s($%s)%s', $attribute->getSetterName(), lcfirst($attribute->getCleanName()), $isLast ? ';' : ''), 1));
111 76
        return $this;
112
    }
113
    /**
114
     * @return PhpFunctionParameter[]
115
     */
116 76
    protected function getStructMethodParametersValues()
117
    {
118 76
        $parametersValues = array();
119 76
        foreach ($this->getModelAttributes() as $attribute) {
120 76
            $parametersValues[] = $this->getStructMethodParameter($attribute, true);
121 57
        }
122 76
        return $parametersValues;
123
    }
124
    /**
125
     * @param StructAttributeModel $attribute
126
     * @param bool $lowCaseFirstLetter
127
     * @param mixed $defaultValue
128
     * @return PhpFunctionParameter
129
     */
130 76
    protected function getStructMethodParameter(StructAttributeModel $attribute, $lowCaseFirstLetter = false, $defaultValue = null)
131
    {
132
        try {
133 76
            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 76
    protected function getStructMethodParameterType(StructAttributeModel $attribute, $returnArrayType = true)
144
    {
145 76
        return self::getValidType($this->getStructAttributeTypeHint($attribute, $returnArrayType), null);
146
    }
147
    /**
148
     * @param MethodContainer $methods
149
     * @return Struct
150
     */
151 76
    protected function addStructMethodsSetAndGet(MethodContainer $methods)
152
    {
153 76
        foreach ($this->getModelAttributes() as $attribute) {
154 57
            $this
155 76
                ->addStructMethodGet($methods, $attribute)
156 76
                ->addStructMethodSet($methods, $attribute)
157 76
                ->addStructMethodAddTo($methods, $attribute);
158 57
        }
159 76
        return $this;
160
    }
161
    /**
162
     * @param MethodContainer $methods
163
     * @param StructAttributeModel $attribute
164
     * @return Struct
165
     */
166 76
    protected function addStructMethodAddTo(MethodContainer $methods, StructAttributeModel $attribute)
167
    {
168 76
        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 33
            ));
172 44
            $this->addStructMethodAddToBody($method, $attribute);
173 44
            $methods->add($method);
174 33
        }
175 76
        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 12
        } 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 76
    protected function addStructMethodSet(MethodContainer $methods, StructAttributeModel $attribute)
213
    {
214 76
        $method = new PhpMethod($attribute->getSetterName(), array(
215 76
            $this->getStructMethodParameter($attribute, true, null),
216 57
        ));
217 76
        $this->addStructMethodSetBody($method, $attribute);
218 76
        $methods->add($method);
219 76
        return $this;
220
    }
221
    /**
222
     * @param PhpMethod $method
223
     * @param StructAttributeModel $attribute
224
     * @return Struct
225
     */
226 76
    protected function addStructMethodSetBody(PhpMethod $method, StructAttributeModel $attribute)
227
    {
228 76
        if ($attribute->isArray()) {
229 44
            $this->addStructMethodSetBodyForArray($method, $attribute);
230 33
        } else {
231 48
            $this->addStructMethodSetBodyForRestriction($method, $attribute);
232
        }
233 57
        return $this
234 76
            ->addStructMethodSetBodyAssignment($method, $attribute)
235 76
            ->addStructMethodSetBodyReturn($method);
236
    }
237
    /**
238
     * @param PhpMethod $method
239
     * @param StructAttributeModel $attribute
240
     * @return Struct
241
     */
242 76
    protected function addStructMethodSetBodyAssignment(PhpMethod $method, StructAttributeModel $attribute)
243
    {
244 76
        $method->addChild($this->getStructMethodSetBodyAssignment($attribute));
245 76
        return $this;
246
    }
247
    /**
248
     * @param PhpMethod $method
249
     * @return Struct
250
     */
251 76
    protected function addStructMethodSetBodyReturn(PhpMethod $method)
252
    {
253 76
        $method->addChild('return $this;');
254 76
        return $this;
255
    }
256
    /**
257
     * @param PhpMethod $method
258
     * @param StructAttributeModel $attribute
259
     * @param string $parameterName
260
     * @return Struct
261
     */
262 56
    protected function addStructMethodSetBodyForRestriction(PhpMethod $method, StructAttributeModel $attribute, $parameterName = null)
263
    {
264 56
        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 30
        }
271 56
        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 12
            } 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 33
        }
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 21
        } else {
317 24
            switch (self::getPhpType($attribute->getType())) {
318 18
                case 'int':
319 16
                    $sanityCheck = 'is_int($item)';
320 16
                    break;
321 12
                case 'bool':
322
                    $sanityCheck = 'is_bool($item)';
323
                    break;
324 12
                case 'float':
325
                    $sanityCheck = 'is_float($item)';
326
                    break;
327 12
                case 'string':
328 16
                    $sanityCheck = 'is_string($item)';
329 16
                    break;
330 18
            }
331
        }
332 40
        return $sanityCheck;
333
    }
334
    /**
335
     * @param StructAttributeModel $attribute
336
     * @return string
337
     */
338 76
    protected function getStructMethodSetBodyAssignment(StructAttributeModel $attribute)
339
    {
340 76
        if ($attribute->nameIsClean()) {
341 76
            $assignment = sprintf('$this->%s = $%s;', $attribute->getName(), lcfirst($attribute->getCleanName()));
342 57
        } else {
343
            $assignment = sprintf('$this->%s = $this->{\'%s\'} = $%s;', $attribute->getCleanName(), addslashes($attribute->getName()), lcfirst($attribute->getCleanName()));
344
        }
345 76
        return $assignment;
346
    }
347
    /**
348
     * @param PhpMethod $method
349
     * @param StructAttributeModel $attribute
350
     * @param string $thisAccess
351
     * @return Struct
352
     */
353 76
    protected function addStructMethodGetBody(PhpMethod $method, StructAttributeModel $attribute, $thisAccess)
354
    {
355 57
        return $this
356 76
            ->addStructMethodGetBodyForXml($method, $attribute, $thisAccess)
357 76
            ->addStructMethodGetBodyReturn($method, $attribute, $thisAccess);
358
    }
359
    /**
360
     * @param PhpMethod $method
361
     * @param StructAttributeModel $attribute
362
     * @param string $thisAccess
363
     * @return Struct
364
     */
365 76
    protected function addStructMethodGetBodyForXml(PhpMethod $method, StructAttributeModel $attribute, $thisAccess)
366
    {
367 76
        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 3
        }
378 76
        return $this;
379
    }
380
    /**
381
     * @param PhpMethod $method
382
     * @param StructAttributeModel $attribute
383
     * @param string $thisAccess
384
     * @return Struct
385
     */
386 76
    protected function addStructMethodGetBodyReturn(PhpMethod $method, StructAttributeModel $attribute, $thisAccess)
387
    {
388 76
        $return = sprintf('return $this->%s;', $thisAccess);
389 76
        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 3
        }
392 76
        $method->addChild($return);
393 76
        return $this;
394
    }
395
    /**
396
     * @param MethodContainer $methods
397
     * @param StructAttributeModel $attribute
398
     * @return Struct
399
     */
400 76
    protected function addStructMethodGet(MethodContainer $methods, StructAttributeModel $attribute)
401
    {
402 76
        $method = new PhpMethod($attribute->getGetterName(), $this->getStructMethodGetParameters($attribute));
403 76
        if ($attribute->nameIsClean()) {
404 76
            $thisAccess = sprintf('%s', $attribute->getName());
405 57
        } else {
406
            $thisAccess = sprintf('{\'%s\'}', addslashes($attribute->getName()));
407
        }
408 76
        $this->addStructMethodGetBody($method, $attribute, $thisAccess);
409 76
        $methods->add($method);
410 76
        return $this;
411
    }
412
    /**
413
     * @param StructAttributeModel $attribute
414
     * @return PhpFunctionParameter[]
415
     */
416 76
    protected function getStructMethodGetParameters(StructAttributeModel $attribute)
417
    {
418 76
        $parameters = array();
419 76
        if ($attribute->isXml()) {
420 4
            $parameters[] = new PhpFunctionParameter('asString', true);
421 3
        }
422 76
        return $parameters;
423
    }
424
    /**
425
     * @param MethodContainer $methods
426
     * @return Struct
427
     */
428 76
    protected function addStructMethodSetState(MethodContainer $methods)
429
    {
430 76
        $method = new PhpMethod(self::METHOD_SET_STATE, array(
431 76
            new PhpFunctionParameter('array', PhpFunctionParameter::NO_VALUE, 'array'),
432 76
        ), PhpMethod::ACCESS_PUBLIC, false, true);
433 76
        $method->addChild(sprintf('return parent::__set_state($array);'));
434 76
        $methods->add($method);
435 76
        return $this;
436
    }
437
    /**
438
     * @return PhpAnnotationBlock|null
439
     */
440 76
    protected function getMethodAnnotationBlock(PhpMethod $method)
441
    {
442 76
        return $this->getStructMethodAnnotationBlock($method);
443
    }
444
    /**
445
     * @param PhpMethod $method
446
     * @return PhpAnnotationBlock|null
447
     */
448 76
    protected function getStructMethodAnnotationBlock(PhpMethod $method)
449
    {
450 76
        $annotationBlock = null;
451 76
        switch ($method->getName()) {
452 76
            case self::METHOD_CONSTRUCT:
453 56
                $annotationBlock = $this->getStructMethodConstructAnnotationBlock();
454 56
                break;
455 76
            case self::METHOD_SET_STATE:
456 56
                $annotationBlock = $this->getStructMethodSetStateAnnotationBlock();
457 56
                break;
458 76
            case strpos($method->getName(), 'get') === 0:
459 76
            case strpos($method->getName(), 'set') === 0:
460 76
                $annotationBlock = $this->getStructMethodsSetAndGetAnnotationBlock($method);
461 76
                break;
462 44
            case strpos($method->getName(), 'addTo') === 0:
463 44
                $annotationBlock = $this->getStructMethodsAddToAnnotationBlock($method);
464 44
                break;
465 57
        }
466 76
        return $annotationBlock;
467
    }
468
    /**
469
     * @return PhpAnnotationBlock
470
     */
471 76
    protected function getStructMethodConstructAnnotationBlock()
472
    {
473 76
        $annotationBlock = new PhpAnnotationBlock(array(
474 76
            sprintf('Constructor method for %s', $this->getModel()->getName()),
475 57
        ));
476 76
        $this->addStructPropertiesToAnnotationBlock($annotationBlock);
477 76
        return $annotationBlock;
478
    }
479
    /**
480
     * @return PhpAnnotationBlock
481
     */
482 76
    protected function getStructMethodSetStateAnnotationBlock()
483
    {
484 76
        return new PhpAnnotationBlock(array(
485 76
            'Method called when an object has been exported with var_export() functions',
486 76
            'It allows to return an object instantiated with the values',
487 76
            new PhpAnnotation(self::ANNOTATION_SEE, sprintf('%s::__set_state()', $this->getModel()->getExtends(true))),
488 76
            new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::__set_state()', $this->getModel()->getExtends(true))),
489 76
            new PhpAnnotation(self::ANNOTATION_PARAM, 'array $array the exported values'),
490 76
            new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)),
491 57
        ));
492
    }
493
    /**
494
     * @param PhpMethod $method
495
     * @return PhpAnnotationBlock
496
     */
497 76
    protected function getStructMethodsSetAndGetAnnotationBlock(PhpMethod $method)
498
    {
499 76
        $parameters = $method->getParameters();
500 76
        $setOrGet = strtolower(substr($method->getName(), 0, 3));
501 76
        $parameter = array_shift($parameters);
502
        /**
503
         * Only set parameter must be based on a potential PhpFunctionParameter
504
         */
505 76
        if ($parameter instanceof PhpFunctionParameter && $setOrGet === 'set') {
506 76
            $parameterName = ucfirst($parameter->getName());
507 57
        } else {
508 76
            $parameterName = substr($method->getName(), 3);
509
        }
510 76
        $attribute = $this->getModel()->getAttribute($parameterName);
511 76
        if (!$attribute instanceof StructAttributeModel) {
512 40
            $parameterName = lcfirst($parameterName);
513 40
            $attribute = $this->getModel()->getAttribute($parameterName);
514 30
        }
515 76
        $setValueAnnotation = '%s %s value';
516 76
        $annotationBlock = new PhpAnnotationBlock();
517 76
        if ($attribute instanceof StructAttributeModel) {
518 76
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), $parameterName));
519 76
            $this->addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, $annotationBlock, $attribute);
520 57
        } elseif (empty($attribute)) {
521 4
            $annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), lcfirst($parameterName)));
522 4
            $this->addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, $annotationBlock, $parameterName);
523 3
        }
524 76
        return $annotationBlock;
525
    }
526
    /**
527
     * @param string $setOrGet
528
     * @param PhpAnnotationBlock $annotationBlock
529
     * @param StructAttributeModel $attribute
530
     * @return Struct
531
     */
532 76
    protected function addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute)
533
    {
534
        switch ($setOrGet) {
535 76
            case 'set':
536 76
                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 76
                } elseif ($attribute->isArray()) {
542 44
                    $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, '\InvalidArgumentException'));
543 33
                }
544 76
                $this->addStructMethodsSetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeSetAnnotation($attribute), lcfirst($attribute->getCleanName()));
545 76
                break;
546 57
            case 'get':
547 76
                $this->addStructMethodsGetAnnotationBlockFromXmlAttribute($annotationBlock, $attribute);
548 76
                $this->addStructMethodsGetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeGetAnnotation($attribute));
549 76
                break;
550
        }
551 76
        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 3
            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 76
    protected function addStructMethodsSetAnnotationBlock(PhpAnnotationBlock $annotationBlock, $type, $name)
578
    {
579
        $annotationBlock
580 76
            ->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $type, $name)))
581 76
            ->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true)));
582 76
        return $this;
583
    }
584
    /**
585
     * @param PhpAnnotationBlock $annotationBlock
586
     * @param string $attribute
587
     * @return Struct
588
     */
589 76
    protected function addStructMethodsGetAnnotationBlock(PhpAnnotationBlock $annotationBlock, $attribute)
590
    {
591 76
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $attribute));
592 76
        return $this;
593
    }
594
    /**
595
     * @param PhpAnnotationBlock $annotationBlock
596
     * @param StructAttributeModel $attribute
597
     */
598 76
    protected function addStructMethodsGetAnnotationBlockFromXmlAttribute(PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute)
599
    {
600 76
        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 3
        }
609 76
    }
610
    /**
611
     * @param PhpAnnotationBlock $annotationBlock
612
     * @return Struct
613
     */
614 76
    protected function addStructPropertiesToAnnotationBlock(PhpAnnotationBlock $annotationBlock)
615
    {
616 57
        return $this
617 76
            ->addStructPropertiesToAnnotationBlockUses($annotationBlock)
618 76
            ->addStructPropertiesToAnnotationBlockParams($annotationBlock);
619
    }
620
    /**
621
     * @param PhpAnnotationBlock $annotationBlock
622
     * @return Struct
623
     */
624 76
    protected function addStructPropertiesToAnnotationBlockUses(PhpAnnotationBlock $annotationBlock)
625
    {
626 76
        foreach ($this->getModelAttributes() as $attribute) {
627 76
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(), $attribute->getSetterName())));
628 57
        }
629 76
        return $this;
630
    }
631
    /**
632
     * @param PhpAnnotationBlock $annotationBlock
633
     * @return Struct
634
     */
635 76
    protected function addStructPropertiesToAnnotationBlockParams(PhpAnnotationBlock $annotationBlock)
636
    {
637 76
        foreach ($this->getModelAttributes() as $attribute) {
638 76
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $this->getStructAttributeTypeSetAnnotation($attribute), lcfirst($attribute->getCleanName()))));
639 57
        }
640 76
        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 15
        }
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 12
            }
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 33
        }
667 44
        return $annotationBlock;
668
    }
669
    /**
670
     * @see \WsdlToPhp\PackageGenerator\File\AbstractModelFile::getModel()
671
     * @return StructModel
672
     */
673 124
    public function getModel()
674
    {
675 124
        return parent::getModel();
676
    }
677
    /**
678
     * @see \WsdlToPhp\PackageGenerator\File\AbstractModelFile::setModel()
679
     * @throws \InvalidaArgumentException
680
     * @param AbstractModel $model
681
     * @return StructArray
682
     */
683 124
    public function setModel(AbstractModel $model)
684
    {
685 124
        if (!$model instanceof StructModel) {
686 4
            throw new \InvalidArgumentException('Model must be an instance of a Struct', __LINE__);
687
        }
688 120
        return parent::setModel($model);
689
    }
690
}
691