Passed
Push — feature/issue-165 ( 2b7e50...101bca )
by Mikaël
14:10
created

Struct   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 478
Duplicated Lines 0 %

Test Coverage

Coverage 95.53%

Importance

Changes 0
Metric Value
eloc 139
dl 0
loc 478
ccs 171
cts 179
cp 0.9553
rs 2.4
c 0
b 0
f 0
wmc 75

35 Methods

Rating   Name   Duplication   Size   Complexity  
B isArray() 0 12 7
A setList() 0 4 1
A getReservedMethodsInstance() 0 7 2
A getTypes() 0 3 1
A __construct() 0 9 1
A getInheritanceStruct() 0 3 2
A isList() 0 3 1
A setTypes() 0 4 1
A getExtends() 0 9 4
A isUnion() 0 3 1
A isRestriction() 0 3 1
A setRestriction() 0 4 1
A putRequiredFirst() 0 20 5
A setAttributesFromSerializedJson() 0 4 2
A getDocSubPackages() 0 10 3
A getAttributeByCleanName() 0 3 1
A addInheritanceAttributes() 0 8 6
A getAllAttributes() 0 15 4
A getTopInheritance() 0 14 4
A getMeta() 0 4 3
A setValues() 0 4 1
A getList() 0 3 1
A addAttribute() 0 10 4
A getAttributes() 0 8 3
A setAttributes() 0 4 1
A toJsonSerialize() 0 9 1
A addValue() 0 9 2
A getAttribute() 0 3 1
A isStruct() 0 3 1
A getContextualPart() 0 9 3
A getValues() 0 3 1
A countOwnAttributes() 0 3 1
A setStruct() 0 4 1
A getValue() 0 3 1
A setValuesFromSerializedJson() 0 4 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.

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\Model;
4
5
use WsdlToPhp\PackageGenerator\Generator\Utils;
6
use WsdlToPhp\PackageGenerator\Container\Model\StructValue as StructValueContainer;
7
use WsdlToPhp\PackageGenerator\Container\Model\StructAttribute as StructAttributeContainer;
8
use WsdlToPhp\PackageGenerator\Generator\Generator;
9
use WsdlToPhp\PackageGenerator\ConfigurationReader\StructReservedMethod;
10
use WsdlToPhp\PackageGenerator\ConfigurationReader\StructArrayReservedMethod;
11
12
/**
13
 * Class Struct stands for an available struct described in the WSDL
14
 */
15
class Struct extends AbstractModel
16
{
17
    /**
18
     * @var string
19
     */
20
    const DOC_SUB_PACKAGE_STRUCTS = 'Structs';
21
    /**
22
     * @var string
23
     */
24
    const DOC_SUB_PACKAGE_ENUMERATIONS = 'Enumerations';
25
    /**
26
     * @var string
27
     */
28
    const DOC_SUB_PACKAGE_ARRAYS = 'Arrays';
29
    /**
30
     * Attributes of the struct
31
     * @var StructAttributeContainer
32
     */
33
    protected $attributes;
34
    /**
35
     * Is the struct a restriction with defined values  ?
36
     * @var bool
37
     */
38
    protected $isRestriction = false;
39
    /**
40
     * If the struct is a restriction with values, then store values
41
     * @var StructValueContainer
42
     */
43
    protected $values;
44
    /**
45
     * If the struct is a union with types, then store types
46
     * @var string[]
47
     */
48
    protected $types;
49
    /**
50
     * Defines if the current struct is a concrete struct or just a virtual struct to store meta informations
51
     * @var bool
52
     */
53
    protected $isStruct = false;
54
    /**
55
     * Defines if the current struct is a list of a type or not.
56
     * If it is a list of a type, then the list property value is the type
57
     * @var string
58
     */
59
    protected $list = '';
60
    /**
61
     * Main constructor
62
     * @see AbstractModel::__construct()
63 1530
     * @uses Struct::setStruct()
64
     * @param Generator $generator
65 1530
     * @param string $name the original name
66 765
     * @param bool $isStruct defines if it's a real struct or not
67 1530
     * @param bool $isRestriction defines if it's an enumeration or not
68 1530
     */
69 1530
    public function __construct(Generator $generator, $name, $isStruct = true, $isRestriction = false)
70 1530
    {
71 1530
        parent::__construct($generator, $name);
72 1530
        $this
73
            ->setStruct($isStruct)
74
            ->setRestriction($isRestriction)
75
            ->setAttributes(new StructAttributeContainer($generator))
76
            ->setValues(new StructValueContainer($generator))
77
            ->setTypes([]);
78
    }
79 444
    /**
80
     * Returns the contextual part of the class name for the package
81 444
     * @see AbstractModel::getContextualPart()
82 444
     * @uses Struct::isRestriction()
83 162
     * @return string
84 417
     */
85 78
    public function getContextualPart()
86 39
    {
87 444
        $part = $this->getGenerator()->getOptionStructsFolder();
88
        if ($this->isRestriction()) {
89
            $part = $this->getGenerator()->getOptionEnumsFolder();
90
        } elseif ($this->isArray()) {
91
            $part = $this->getGenerator()->getOptionArraysFolder();
92
        }
93
        return $part;
94
    }
95
    /**
96 252
     * Returns the sub package name which the model belongs to
97
     * Must be overridden by sub classes
98 252
     * @see AbstractModel::getDocSubPackages()
99 252
     * @uses Struct::isRestriction()
100 84
     * @return array
101 228
     */
102 48
    public function getDocSubPackages()
103 24
    {
104
        $package = self::DOC_SUB_PACKAGE_STRUCTS;
105 252
        if ($this->isRestriction()) {
106 126
            $package = self::DOC_SUB_PACKAGE_ENUMERATIONS;
107
        } elseif ($this->isArray()) {
108
            $package = self::DOC_SUB_PACKAGE_ARRAYS;
109
        }
110
        return [
111
            $package,
112
        ];
113
    }
114 498
    /**
115
     * Returns true if the current struct is a collection of values (like an array or a list of values)
116
     * @uses AbstractModel::getName()
117
     * @uses Struct::countOwnAttributes()
118
     * @return bool
119
     */
120 498
    public function isArray()
121 474
    {
122 249
        return
123 324
        (
124 162
            (
125 483
                (
126 249
                    ($this->isStruct() && $this->countOwnAttributes() === 1) ||
127
                    (!$this->isStruct() && $this->countOwnAttributes() <= 1)
128
                ) &&
129
                stripos($this->getName(), 'array') !== false
130
            ) ||
131
            (!$this->isStruct() && $this->getMetaValueFirstSet(['arraytype', 'arrayType'], false) !== false)
132
        );
133
    }
134
    /**
135
     * Returns the attributes of the struct and potentially from the parent class
136
     * @uses AbstractModel::getInheritance()
137 516
     * @uses Struct::isStruct()
138
     * @uses Struct::getAttributes()
139 516
     * @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.
140 516
     * @param bool $requiredFirst places the required attributes first, then the not required in order to have the _construct method with the required attribute at first
141 258
     * @return StructAttributeContainer
142 198
     */
143
    public function getAttributes($includeInheritanceAttributes = false, $requiredFirst = false)
144 516
    {
145
        if ($includeInheritanceAttributes === false && $requiredFirst === false) {
146
            $attributes = $this->attributes;
147
        } else {
148
            $attributes = $this->getAllAttributes($includeInheritanceAttributes, $requiredFirst);
149
        }
150
        return $attributes;
151 198
    }
152
    /**
153 198
     * @param bool $includeInheritanceAttributes
154 198
     * @param bool $requiredFirst
155 6
     * @return StructAttributeContainer
156 3
     */
157 198
    protected function getAllAttributes($includeInheritanceAttributes, $requiredFirst)
158 198
    {
159 99
        $allAttributes = new StructAttributeContainer($this->getGenerator());
160 198
        if ($includeInheritanceAttributes === true) {
161 198
            $this->addInheritanceAttributes($allAttributes);
162 99
        }
163
        foreach ($this->attributes as $attribute) {
164
            $allAttributes->add($attribute);
165 198
        }
166
        if ($requiredFirst === true) {
167
            $attributes = $this->putRequiredFirst($allAttributes);
168
        } else {
169
            $attributes = $allAttributes;
170 6
        }
171
        return $attributes;
172 6
    }
173
    /**
174
     * @param StructAttributeContainer $attributes
175
     */
176
    protected function addInheritanceAttributes(StructAttributeContainer $attributes)
177
    {
178
        if ($this->getInheritance() != '' && ($model = $this->getInheritanceStruct()) instanceof Struct) {
179
            while ($model instanceof Struct && $model->isStruct()) {
180 6
                foreach ($model->getAttributes() as $attribute) {
181
                    $attributes->add($attribute);
182
                }
183
                $model = $model->getInheritanceStruct();
184
            }
185 198
        }
186
    }
187 198
    /**
188 198
     * @param StructAttributeContainer $allAttributes
189 198
     * @return StructAttributeContainer
190 198
     */
191 198
    protected function putRequiredFirst(StructAttributeContainer $allAttributes)
192 48
    {
193 24
        $attributes = new StructAttributeContainer($this->getGenerator());
194 190
        $requiredAttributes = new StructAttributeContainer($this->getGenerator());
195
        $notRequiredAttributes = new StructAttributeContainer($this->getGenerator());
196 99
        foreach ($allAttributes as $attribute) {
197 198
            if ($attribute->isRequired()) {
198 48
                $requiredAttributes->add($attribute);
199 99
            } else {
200 198
                $notRequiredAttributes->add($attribute);
201 186
            }
202 99
        }
203 198
        foreach ($requiredAttributes as $attribute) {
204 198
            $attributes->add($attribute);
205
        }
206
        foreach ($notRequiredAttributes as $attribute) {
207
            $attributes->add($attribute);
208
        }
209
        unset($requiredAttributes, $notRequiredAttributes);
210
        return $attributes;
211 498
    }
212
    /**
213 498
     * Returns the number of own attributes
214
     * @uses Struct::getAttributes()
215
     * @return int
216
     */
217
    public function countOwnAttributes()
218
    {
219
        return $this->getAttributes(false, false)->count();
220 1530
    }
221
    /**
222 1530
     * Sets the attributes of the struct
223 1530
     * @param StructAttributeContainer $structAttributeContainer
224
     * @return Struct
225
     */
226
    public function setAttributes(StructAttributeContainer $structAttributeContainer)
227
    {
228
        $this->attributes = $structAttributeContainer;
229
        return $this;
230
    }
231
    /**
232 396
     * Adds attribute based on its original name
233
     * @throws \InvalidArgumentException
234 396
     * @param string $attributeName the attribute name
235 12
     * @param string $attributeType the attribute type
236
     * @return Struct
237 384
     */
238 384
    public function addAttribute($attributeName, $attributeType)
239 384
    {
240 192
        if (empty($attributeName) || empty($attributeType)) {
241 384
            throw new \InvalidArgumentException(sprintf('Attribute name "%s" and/or attribute type "%s" is invalid for Struct "%s"', $attributeName, $attributeType, $this->getName()), __LINE__);
242
        }
243
        if ($this->attributes->getStructAttributeByName($attributeName) === null) {
244
            $structAttribute = new StructAttribute($this->getGenerator(), $attributeName, $attributeType, $this);
245
            $this->attributes->add($structAttribute);
246
        }
247
        return $this;
248
    }
249 324
    /**
250
     * Returns the attribute by its name, otherwise null
251 324
     * @uses Struct::getAttributes()
252
     * @param string $attributeName the original attribute name
253
     * @return StructAttribute|null
254
     */
255
    public function getAttribute($attributeName)
256
    {
257
        return $this->attributes->getStructAttributeByName($attributeName);
258
    }
259 90
    /**
260
     * Returns the attribute by its cleaned name, otherwise null
261 90
     * @uses Struct::getAttributes()
262
     * @param string $attributeCleanName the cleaned attribute name
263
     * @return StructAttribute|null
264
     */
265
    public function getAttributeByCleanName($attributeCleanName)
266
    {
267 492
        return $this->attributes->getStructAttributeByCleanName($attributeCleanName);
268
    }
269 492
    /**
270
     * Returns the isRestriction value
271
     * @return bool
272
     */
273
    public function isRestriction()
274
    {
275
        return $this->isRestriction;
276 1530
    }
277
    /**
278 1530
     * Sets the isRestriction value
279 1530
     * @param bool $isRestriction
280
     * @return Struct
281
     */
282
    public function setRestriction($isRestriction = true)
283
    {
284
        $this->isRestriction = $isRestriction;
285 546
        return $this;
286
    }
287 546
    /**
288
     * Returns the isStruct value
289
     * @return bool
290
     */
291
    public function isStruct()
292
    {
293
        return $this->isStruct;
294 1530
    }
295
    /**
296 1530
     * Sets the isStruct value
297 1530
     * @param bool $isStruct
298
     * @return Struct
299
     */
300
    public function setStruct($isStruct = true)
301
    {
302
        $this->isStruct = $isStruct;
303 144
        return $this;
304
    }
305 144
    /**
306
     * Returns the list value
307
     * @return string
308
     */
309
    public function getList()
310
    {
311
        return $this->list;
312 1530
    }
313
    /**
314 1530
     * Returns if the current struct is a list
315 1530
     * List are a set of basic-type values
316
     * @return bool
317
     */
318
    public function isList()
319
    {
320
        return !empty($this->list);
321
    }
322
    /**
323
     * Sets the list value
324 102
     * @param string $list
325
     * @return Struct
326 102
     */
327 102
    public function setList($list = '')
328 51
    {
329 102
        $this->list = $list;
330 102
        return $this;
331 51
    }
332 102
    /**
333
     * Returns the values for an enumeration
334
     * @return StructValueContainer
335
     */
336
    public function getValues()
337
    {
338
        return $this->values;
339
    }
340
    /**
341 144
     * Sets the values for an enumeration
342
     * @param StructValueContainer $structValueContainer
343 144
     * @return Struct
344
     */
345
    protected function setValues(StructValueContainer $structValueContainer)
346
    {
347
        $this->values = $structValueContainer;
348
        return $this;
349
    }
350 240
    /**
351
     * Adds value to values array
352 240
     * @uses Struct::getValue()
353 240
     * @uses Struct::getValues()
354 48
     * @param mixed $value the original value
355 225
     * @return Struct
356 168
     */
357 84
    public function addValue($value)
358 240
    {
359
        if ($this->getValue($value) === null) {
360
            $this->values->add(new StructValue($this->getGenerator(), $value, $this->getValues()->count(), $this));
361
            $this
362
                ->setRestriction(true)
363 354
                ->setStruct(true);
364
        }
365 354
        return $this;
366
    }
367
    /**
368
     * Gets the value object for the given value
369
     * @uses Struct::getValues()
370 222
     * @uses AbstractModel::getName()
371
     * @param string $value Value name
372 222
     * @return StructValue|null
373 222
     */
374 156
    public function getValue($value)
375 156
    {
376 66
        return $this->values->getStructValueByName($value);
377 66
    }
378 30
    /**
379 15
     * Allows to define from which class the current model extends
380 66
     * @param bool $short
381 33
     * @return string
382 78
     */
383 222
    public function getExtends($short = false)
384
    {
385
        $extends = '';
386
        if ($this->isArray()) {
387
            $extends = $this->getGenerator()->getOptionStructArrayClass();
388
        } elseif (!$this->isRestriction()) {
389 342
            $extends = $this->getGenerator()->getOptionStructClass();
390
        }
391 342
        return $short ? Utils::removeNamespace($extends) : $extends;
392 342
    }
393
    /**
394
     * @return Struct|null
395
     */
396
    public function getInheritanceStruct()
397
    {
398 222
        return $this->getName() === $this->getInheritance() ? null : $this->getGenerator()->getStructByName(str_replace('[]', '', $this->getInheritance()));
399
    }
400 222
    /**
401 222
     * @return string
402 54
     */
403 27
    public function getTopInheritance()
404 222
    {
405
        $inheritance = $this->getInheritance();
406
        if (!empty($inheritance)) {
407
            $struct = $this->getInheritanceStruct();
408
            while ($struct instanceof Struct) {
409 6
                $structInheritance = $struct->getInheritance();
410
                if (!empty($structInheritance)) {
411 6
                    $inheritance = $structInheritance;
412
                }
413
                $struct = $struct->getInheritanceStruct();
414
            }
415
        }
416 204
        return $inheritance;
417
    }
418 204
    /**
419
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::getMeta()
420
     * @return string[]
421
     */
422
    public function getMeta()
423
    {
424 1530
        $inheritanceStruct = $this->getInheritanceStruct();
425
        return array_merge_recursive(parent::getMeta(), ($inheritanceStruct && !$inheritanceStruct->isStruct()) ? $inheritanceStruct->getMeta() : []);
426 1530
    }
427 1530
    /**
428
     * @param $filename
429
     * @return StructReservedMethod|StructArrayReservedMethod
430
     */
431
    public function getReservedMethodsInstance($filename = null)
432
    {
433 6
        $instance = StructReservedMethod::instance($filename);
434
        if ($this->isArray()) {
435
            $instance = StructArrayReservedMethod::instance($filename);
436 6
        }
437 6
        return $instance;
438 6
    }
439 6
    /**
440 6
     * @return string[]
441 3
     */
442
    public function getTypes()
443
    {
444
        return $this->types;
445
    }
446 486
    /**
447
     * @return boolean
448 486
     */
449 480
    public function isUnion()
450 243
    {
451 486
        return count($this->types) > 0;
452
    }
453
    /**
454
     * @param string[] $types
455 486
     * @return Struct
456
     */
457 486
    public function setTypes($types)
458 450
    {
459 243
        $this->types = $types;
460 486
        return $this;
461
    }
462
    /**
463
     * {@inheritDoc}
464
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::toJsonSerialize()
465
     */
466
    protected function toJsonSerialize()
467
    {
468
        return [
469
            'attributes' => $this->attributes,
470
            'restriction' => $this->isRestriction,
471
            'struct' => $this->isStruct,
472
            'types' => $this->types,
473
            'values' => $this->values,
474
            'list' => $this->list,
475
        ];
476
    }
477
    /**
478
     * @param array $attributes
479
     */
480
    public function setAttributesFromSerializedJson(array $attributes)
481
    {
482
        foreach ($attributes as $attribute) {
483
            $this->attributes->add(self::instanceFromSerializedJson($this->generator, $attribute)->setOwner($this));
484
        }
485
    }
486
    /**
487
     * @param array $values
488
     */
489
    public function setValuesFromSerializedJson(array $values)
490
    {
491
        foreach ($values as $value) {
492
            $this->values->add(self::instanceFromSerializedJson($this->generator, $value)->setOwner($this));
493
        }
494
    }
495
}
496