Completed
Push — 1.x ( 257780...f31d1d )
by Mikaël
42:33 queued 33:38
created

AbstractModelFile   F

Complexity

Total Complexity 76

Size/Duplication

Total Lines 496
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 17

Test Coverage

Coverage 100%

Importance

Changes 7
Bugs 0 Features 0
Metric Value
wmc 76
c 7
b 0
f 0
lcom 1
cbo 17
dl 0
loc 496
rs 2.2388
ccs 199
cts 199
cp 1

40 Methods

Rating   Name   Duplication   Size   Complexity  
A getClassAnnotationBlock() 0 10 1
A addClassElement() 0 12 2
A getModelFromStructAttribute() 0 9 2
A getStructAttributeTypeAsPhpType() 0 9 2
A getRestrictionFromStructAttribute() 0 8 3
D getStructAttributeType() 0 27 10
A getFileDestination() 0 4 2
A getDestinationFolder() 0 4 2
A writeFile() 0 13 2
A addAnnotationBlock() 0 7 1
A setModel() 0 6 1
A getModel() 0 4 1
A getModelByName() 0 4 1
A definePackageAnnotations() 0 11 3
A getPackageName() 0 10 3
A defineGeneralAnnotations() 0 7 2
A getClassDeclarationLine() 0 4 1
A getClassDeclarationLineText() 0 4 1
A defineModelAnnotationsFromWsdl() 0 5 2
A defineNamespace() 0 9 2
A defineUseStatement() 0 9 2
A defineConstants() 0 13 3
A defineProperties() 0 13 3
A defineMethods() 0 13 3
getClassConstants() 0 1 ?
getConstantAnnotationBlock() 0 1 ?
getClassProperties() 0 1 ?
getPropertyAnnotationBlock() 0 1 ?
getClassMethods() 0 1 ?
getMethodAnnotationBlock() 0 1 ?
A defineStringMethod() 0 6 1
A getToStringMethodAnnotationBlock() 0 7 1
A getToStringMethod() 0 6 1
A getStructAttribute() 0 8 4
A getStructAttributeTypeGetAnnotation() 0 5 3
A getStructAttributeTypeSetAnnotation() 0 5 2
A useBrackets() 0 4 2
A getStructAttributeTypeHint() 0 5 3
A getValidType() 0 4 2
A getPhpType() 0 4 2

How to fix   Complexity   

Complex Class

Complex classes like AbstractModelFile 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 AbstractModelFile, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace WsdlToPhp\PackageGenerator\File;
4
5
use WsdlToPhp\PackageGenerator\Container\PhpElement\Method;
6
use WsdlToPhp\PackageGenerator\Container\PhpElement\Property;
7
use WsdlToPhp\PackageGenerator\Container\PhpElement\Constant;
8
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
9
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
10
use WsdlToPhp\PackageGenerator\Model\AbstractModel;
11
use WsdlToPhp\PackageGenerator\File\Utils as FileUtils;
12
use WsdlToPhp\PackageGenerator\Generator\Utils as GeneratorUtils;
13
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
14
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
15
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
16
use WsdlToPhp\PhpGenerator\Element\PhpProperty;
17
use WsdlToPhp\PhpGenerator\Element\PhpConstant;
18
use WsdlToPhp\PhpGenerator\Component\PhpClass;
19
use WsdlToPhp\PackageGenerator\ConfigurationReader\XsdTypes;
20
21
abstract class AbstractModelFile extends AbstractFile
22
{
23
    /**
24
     * @var Long annotation string
25
     */
26
    const ANNOTATION_LONG_LENGTH = '250';
27
    /**
28
     * @var string
29
     */
30
    const ANNOTATION_PACKAGE = 'package';
31
    /**
32
     * @var string
33
     */
34
    const ANNOTATION_SUB_PACKAGE = 'subpackage';
35
    /**
36
     * @var string
37
     */
38
    const ANNOTATION_RETURN = 'return';
39
    /**
40
     * @var string
41
     */
42
    const ANNOTATION_USES = 'uses';
43
    /**
44
     * @var string
45
     */
46
    const ANNOTATION_PARAM = 'param';
47
    /**
48
     * @var string
49
     */
50
    const ANNOTATION_VAR = 'var';
51
    /**
52
     * @var string
53
     */
54
    const ANNOTATION_SEE = 'see';
55
    /**
56
     * @var string
57
     */
58
    const ANNOTATION_THROWS = 'throws';
59
    /**
60
     * @var string
61
     */
62
    const METHOD_CONSTRUCT = '__construct';
63
    /**
64
     * @var string
65
     */
66
    const METHOD_SET_STATE = '__set_state';
67
    /**
68
     * @var string
69
     */
70
    const TYPE_STRING = 'string';
71
    /**
72
     * @var string
73
     */
74
    const TYPE_ARRAY = 'array';
75
    /**
76
     * @var string
77
     */
78
    const SRC_FOLDER = 'src/';
79
    /**
80
     * @var AbstractModel
81
     */
82
    protected $model;
83
    /**
84
     * @param bool $withSrc
85
     * @return string
86
     */
87 240
    public function getFileDestination($withSrc = true)
88
    {
89 240
        return sprintf('%s%s%s', $this->getDestinationFolder($withSrc), $this->getModel()->getSubDirectory(), $this->getModel()->getSubDirectory() !== '' ? '/' : '');
90
    }
91
    /**
92
     * @param bool $withSrc
93
     * @return string
94
     */
95 240
    public function getDestinationFolder($withSrc = true)
96
    {
97 240
        return sprintf('%s%s', $this->getGenerator()->getOptionDestination(), $withSrc === true ? self::SRC_FOLDER : '');
98
    }
99
    /**
100
     * @see \WsdlToPhp\PackageGenerator\File\AbstractFile::writeFile()
101
     * @param bool $withSrc
102
     * @return int|bool
103
     */
104 220
    public function writeFile($withSrc = true)
105
    {
106 220
        if (!$this->getModel() instanceof AbstractModel) {
107 4
            throw new \InvalidArgumentException('You MUST define the model before begin able to generate the file', __LINE__);
108
        }
109 216
        GeneratorUtils::createDirectory($this->getFileDestination($withSrc));
110 216
        $this
111 216
            ->defineNamespace()
112 216
            ->defineUseStatement()
113 216
            ->addAnnotationBlock()
114 216
            ->addClassElement();
115 216
        return parent::writeFile();
116
    }
117
    /**
118
     * @return AbstractModelFile
119
     */
120 216
    protected function addAnnotationBlock()
121
    {
122 216
        $this
123 216
            ->getFile()
124 216
                ->addAnnotationBlockElement($this->getClassAnnotationBlock());
125 216
        return $this;
126
    }
127
    /**
128
     * @param AbstractModel $model
129
     * @return AbstractModelFile
130
     */
131 264
    public function setModel(AbstractModel $model)
132
    {
133 264
        $this->model = $model;
134 264
        $this->getFile()->getMainElement()->setName($model->getPackagedName());
135 264
        return $this;
136
    }
137
    /**
138
     * @return AbstractModel
139
     */
140 268
    public function getModel()
141
    {
142 268
        return $this->model;
143
    }
144
    /**
145
     * @param string $name
146
     * @return StructModel|null
147
     */
148 20
    protected function getModelByName($name)
149
    {
150 20
        return $this->getGenerator()->getStruct($name);
151
    }
152
    /**
153
     * @param PhpAnnotationBlock $block
154
     * @return AbstractModelFile
155
     */
156 196
    protected function definePackageAnnotations(PhpAnnotationBlock $block)
157
    {
158 196
        $packageName = $this->getPackageName();
159 196
        if (!empty($packageName)) {
160 164
            $block->addChild(new PhpAnnotation(self::ANNOTATION_PACKAGE, $packageName));
161 164
        }
162 196
        if (count($this->getModel()->getDocSubPackages()) > 0) {
163 196
            $block->addChild(new PhpAnnotation(self::ANNOTATION_SUB_PACKAGE, implode(',', $this->getModel()->getDocSubPackages())));
164 196
        }
165 196
        return $this;
166
    }
167
    /**
168
     * @return string
169
     */
170 196
    protected function getPackageName()
171
    {
172 196
        $packageName = '';
173 196
        if ($this->getGenerator()->getOptionPrefix() !== '') {
174 156
            $packageName = $this->getGenerator()->getOptionPrefix();
175 196
        } elseif ($this->getGenerator()->getOptionSuffix() !== '') {
176 8
            $packageName = $this->getGenerator()->getOptionSuffix();
177 8
        }
178 196
        return $packageName;
179
    }
180
    /**
181
     * @param PhpAnnotationBlock $block
182
     * @return AbstractModelFile
183
     */
184 196
    protected function defineGeneralAnnotations(PhpAnnotationBlock $block)
185
    {
186 196
        foreach ($this->getGenerator()->getOptionAddComments() as $tagName => $tagValue) {
187 176
            $block->addChild(new PhpAnnotation($tagName, $tagValue));
188 196
        }
189 196
        return $this;
190
    }
191
    /**
192
     * @return PhpAnnotationBlock
193
     */
194 196
    protected function getClassAnnotationBlock()
195
    {
196 196
        $block = new PhpAnnotationBlock();
197 196
        $block->addChild($this->getClassDeclarationLine());
198 196
        $this
199 196
            ->defineModelAnnotationsFromWsdl($block)
200 196
            ->definePackageAnnotations($block)
201 196
            ->defineGeneralAnnotations($block);
202 196
        return $block;
203
    }
204
    /**
205
     * @return string
206
     */
207 196
    protected function getClassDeclarationLine()
208
    {
209 196
        return sprintf($this->getClassDeclarationLineText(), $this->getModel()->getName(), $this->getModel()->getContextualPart());
210
    }
211
    /**
212
     * @return string
213
     */
214 180
    protected function getClassDeclarationLineText()
215
    {
216 180
        return 'This class stands for %s %s';
217
    }
218
    /**
219
     * @param PhpAnnotationBlock $block
220
     * @param AbstractModel $model
221
     * @return AbstractModelFile
222
     */
223 196
    protected function defineModelAnnotationsFromWsdl(PhpAnnotationBlock $block, AbstractModel $model = null)
224
    {
225 196
        FileUtils::defineModelAnnotationsFromWsdl($block, $model instanceof AbstractModel ? $model : $this->getModel());
226 196
        return $this;
227
    }
228
    /**
229
     * @return AbstractModelFile
230
     */
231 216
    protected function addClassElement()
232
    {
233 216
        $class = new PhpClass($this->getModel()->getPackagedName(), $this->getModel()->getIsAbstract(), $this->getModel()->getExtendsClassName() === '' ? null : $this->getModel()->getExtendsClassName());
234 216
        $this
235 216
            ->defineConstants($class)
236 216
            ->defineProperties($class)
237 216
            ->defineMethods($class)
238 216
            ->defineStringMethod($class)
239 216
            ->getFile()
240 216
                ->addClassComponent($class);
241 216
        return $this;
242
    }
243
    /**
244
     * @return AbstractModelFile
245
     */
246 216
    protected function defineNamespace()
247
    {
248 216
        if ($this->getModel()->getNamespace() !== '') {
249 208
            $this
250 208
                ->getFile()
251 208
                    ->setNamespace($this->getModel()->getNamespace());
252 208
        }
253 216
        return $this;
254
    }
255
    /**
256
     * @return AbstractModelFile
257
     */
258 216
    protected function defineUseStatement()
259
    {
260 216
        if ($this->getModel()->getExtends() !== '') {
261 168
            $this
262 168
                ->getFile()
263 168
                    ->addUse($this->getModel()->getExtends(), null, true);
264 168
        }
265 216
        return $this;
266
    }
267
    /**
268
     * @param PhpClass $class
269
     * @return AbstractModelFile
270
     */
271 216
    protected function defineConstants(PhpClass $class)
272
    {
273 216
        $constants = new Constant($this->getGenerator());
274 216
        $this->getClassConstants($constants);
275 216
        foreach ($constants as $constant) {
276 48
            $annotationBlock = $this->getConstantAnnotationBlock($constant);
277 48
            if (!empty($annotationBlock)) {
278 48
                $class->addAnnotationBlockElement($annotationBlock);
279 48
            }
280 48
            $class->addConstantElement($constant);
281 216
        }
282 216
        return $this;
283
    }
284
    /**
285
     * @param PhpClass $class
286
     * @return AbstractModelFile
287
     */
288 216
    protected function defineProperties(PhpClass $class)
289
    {
290 216
        $properties = new Property($this->getGenerator());
291 216
        $this->getClassProperties($properties);
292 216
        foreach ($properties as $property) {
293 104
            $annotationBlock = $this->getPropertyAnnotationBlock($property);
294 104
            if (!empty($annotationBlock)) {
295 104
                $class->addAnnotationBlockElement($annotationBlock);
296 104
            }
297 104
            $class->addPropertyElement($property);
298 216
        }
299 216
        return $this;
300
    }
301
    /**
302
     * @param PhpClass $class
303
     * @return AbstractModelFile
304
     */
305 216
    protected function defineMethods(PhpClass $class)
306
    {
307 216
        $methods = new Method($this->getGenerator());
308 216
        $this->getClassMethods($methods);
309 216
        foreach ($methods as $method) {
310 216
            $annotationBlock = $this->getMethodAnnotationBlock($method);
311 216
            if (!empty($annotationBlock)) {
312 216
                $class->addAnnotationBlockElement($annotationBlock);
313 216
            }
314 216
            $class->addMethodElement($method);
315 216
        }
316 216
        return $this;
317
    }
318
    /**
319
     * @param Constant $constants
320
     */
321
    abstract protected function getClassConstants(Constant $constants);
322
    /**
323
     * @param PhpConstant $constant
324
     * @return PhpAnnotationBlock|null
325
     */
326
    abstract protected function getConstantAnnotationBlock(PhpConstant $constant);
327
    /**
328
     * @param Property $properties
329
     */
330
    abstract protected function getClassProperties(Property $properties);
331
    /**
332
     * @param PhpProperty $property
333
     * @return PhpAnnotationBlock|null
334
     */
335
    abstract protected function getPropertyAnnotationBlock(PhpProperty $property);
336
    /**
337
     * @param Method $methods
338
     */
339
    abstract protected function getClassMethods(Method $methods);
340
    /**
341
     * @param PhpMethod $method
342
     * @return PhpAnnotationBlock|null
343
     */
344
    abstract protected function getMethodAnnotationBlock(PhpMethod $method);
345
    /**
346
     * @param PhpClass $class
347
     */
348 196
    protected function defineStringMethod(PhpClass $class)
349
    {
350 196
        $class->addAnnotationBlockElement($this->getToStringMethodAnnotationBlock());
351 196
        $class->addMethodElement($this->getToStringMethod());
352 196
        return $this;
353
    }
354
    /**
355
     * @return PhpAnnotationBlock
356
     */
357 196
    protected function getToStringMethodAnnotationBlock()
358
    {
359 196
        return new PhpAnnotationBlock(array(
360 196
            'Method returning the class name',
361 196
            new PhpAnnotation(self::ANNOTATION_RETURN, 'string __CLASS__'),
362 196
        ));
363
    }
364
    /**
365
     * @return PhpMethod
366
     */
367 196
    protected function getToStringMethod()
368
    {
369 196
        $method = new PhpMethod('__toString');
370 196
        $method->addChild('return __CLASS__;');
371 196
        return $method;
372
    }
373
    /**
374
     * @param StructAttributeModel $attribute
375
     * @return StructAttributeModel
376
     */
377 104
    protected function getStructAttribute(StructAttributeModel $attribute = null)
378
    {
379 104
        $struct = $this->getModel();
380 104
        if (empty($attribute) && $struct instanceof StructModel && $struct->getAttributes()->count() === 1) {
381 28
            $attribute = $struct->getAttributes()->offsetGet(0);
382 28
        }
383 104
        return $attribute;
384
    }
385
    /**
386
     * @param StructAttributeModel $attribute
387
     * @return StructModel|null
388
     */
389 104
    public function getModelFromStructAttribute(StructAttributeModel $attribute = null)
390
    {
391 104
        $model = null;
392 104
        $attribute = $this->getStructAttribute($attribute);
393 104
        if ($attribute instanceof StructAttributeModel) {
394 104
            $model = $attribute->getTypeStruct();
395 104
        }
396 104
        return $model;
397
    }
398
    /**
399
     * @param StructAttributeModel $attribute
400
     * @return StructModel|null
401
     */
402 104
    public function getRestrictionFromStructAttribute(StructAttributeModel $attribute = null)
403
    {
404 104
        $model = $this->getModelFromStructAttribute($attribute);
405 104
        if ($model instanceof StructModel && !$model->getIsRestriction()) {
406 84
            $model = null;
407 84
        }
408 104
        return $model;
409
    }
410
    /**
411
     * @param StructAttributeModel $attribute
412
     * @param bool $namespaced
413
     * @return string
414
     */
415 104
    public function getStructAttributeType(StructAttributeModel $attribute = null, $namespaced = false)
416
    {
417 104
        $attribute = $this->getStructAttribute($attribute);
418 104
        $inheritance = $attribute->getInheritance();
419 104
        if (empty($inheritance)) {
420 104
            $type = $attribute->getType();
421 104
        } else {
422 8
            $type = $inheritance;
423
        }
424 104
        if (!empty($type) && ($struct = $this->getGenerator()->getStruct($type))) {
425 92
            $inheritance = $struct->getTopInheritance();
426 92
            if (!empty($inheritance)) {
427 40
                $type = str_replace('[]', '', $inheritance);
428 40
            }
429 92
        }
430 104
        $model = $this->getModelFromStructAttribute($attribute);
431 104
        if ($model instanceof StructModel) {
432 92
            if ($model->getIsRestriction()) {
433 52
                $type = self::TYPE_STRING;
434 92
            } elseif ($model->getIsStruct()) {
435 72
                $type = $model->getPackagedName($namespaced);
436 84
            } elseif ($model->isArray() && ($inheritanceStruct = $model->getInheritanceStruct()) instanceof StructModel) {
437 12
                $type = $inheritanceStruct->getPackagedName($namespaced);
438 12
            }
439 92
        }
440 104
        return $type;
441
    }
442
    /**
443
     * @param StructAttributeModel $attribute
444
     * @param bool $returnArrayType
445
     * @return string
446
     */
447 104
    protected function getStructAttributeTypeGetAnnotation(StructAttributeModel $attribute = null, $returnArrayType = true)
448
    {
449 104
        $attribute = $this->getStructAttribute($attribute);
450 104
        return sprintf('%s%s%s', $this->getStructAttributeTypeAsPhpType($attribute), $this->useBrackets($attribute, $returnArrayType) ? '[]' : '', $attribute->isRequired() ? '' : '|null');
451
    }
452
    /**
453
     * @param StructAttributeModel $attribute
454
     * @param bool $returnArrayType
455
     * @return string
456
     */
457 104
    protected function getStructAttributeTypeSetAnnotation(StructAttributeModel $attribute = null, $returnArrayType = true)
458
    {
459 104
        $attribute = $this->getStructAttribute($attribute);
460 104
        return sprintf('%s%s', $this->getStructAttributeTypeAsPhpType($attribute), $this->useBrackets($attribute, $returnArrayType) ? '[]' : '');
461
    }
462
    /**
463
     * @param StructAttributeModel $attribute
464
     * @param string $returnArrayType
465
     * @return bool
466
     */
467 104
    protected function useBrackets(StructAttributeModel $attribute, $returnArrayType = true)
468
    {
469 104
        return $returnArrayType && $attribute->isArray();
470
    }
471
    /**
472
     * @param StructAttributeModel $attribute
473
     * @param bool $returnArrayType
474
     * @return string
475
     */
476 104
    protected function getStructAttributeTypeHint(StructAttributeModel $attribute = null, $returnArrayType = true)
477
    {
478 104
        $attribute = $this->getStructAttribute($attribute);
479 104
        return ($returnArrayType && $attribute->isArray()) ? self::TYPE_ARRAY : $this->getStructAttributeType($attribute, true);
480
    }
481
    /**
482
     * @param StructAttributeModel $attribute
483
     * @return string
484
     */
485 104
    public function getStructAttributeTypeAsPhpType(StructAttributeModel $attribute = null)
486
    {
487 104
        $attribute = $this->getStructAttribute($attribute);
488 104
        $attributeType = $this->getStructAttributeType($attribute, true);
489 104
        if (XsdTypes::instance()->isXsd($attributeType)) {
490 88
            $attributeType = self::getPhpType($attributeType);
491 88
        }
492 104
        return $attributeType;
493
    }
494
    /**
495
     * See http://php.net/manual/fr/language.oop5.typehinting.php for these cases
496
     * Also see http://www.w3schools.com/schema/schema_dtypes_numeric.asp
497
     * @param mixed $type
498
     * @param mixed $fallback
499
     * @return mixed
500
     */
501 124
    public static function getValidType($type, $fallback = null)
502
    {
503 124
        return XsdTypes::instance()->isXsd(str_replace('[]', '', $type)) ? $fallback : $type;
504
    }
505
    /**
506
     * See http://php.net/manual/fr/language.oop5.typehinting.php for these cases
507
     * Also see http://www.w3schools.com/schema/schema_dtypes_numeric.asp
508
     * @param mixed $type
509
     * @param mixed $fallback
510
     * @return mixed
511
     */
512 88
    public static function getPhpType($type, $fallback = self::TYPE_STRING)
513
    {
514 88
        return XsdTypes::instance()->isXsd(str_replace('[]', '', $type)) ? XsdTypes::instance()->phpType($type) : $fallback;
515
    }
516
}
517