Completed
Branch feature/issue-82 (fa87e2)
by Mikaël
02:54
created

Struct   C

Complexity

Total Complexity 64

Size/Duplication

Total Lines 399
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 9

Test Coverage

Coverage 94.67%

Importance

Changes 4
Bugs 0 Features 3
Metric Value
wmc 64
lcom 2
cbo 9
dl 0
loc 399
ccs 142
cts 150
cp 0.9467
rs 5.8364
c 4
b 0
f 3

29 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getContextualPart() 0 10 3
A getDocSubPackages() 0 12 3
B isArray() 0 4 5
A getAttributes() 0 9 3
A getAllAttributes() 0 16 4
B addInheritanceAttributes() 0 11 6
B putRequiredFirst() 0 21 5
A countOwnAttributes() 0 4 1
A setAttributes() 0 5 1
A addAttribute() 0 11 4
A getAttribute() 0 4 1
A getAttributeByCleanName() 0 4 1
A getIsRestriction() 0 4 1
A setIsRestriction() 0 5 1
A getIsStruct() 0 4 1
A setIsStruct() 0 5 1
A getValues() 0 4 1
A setValues() 0 5 1
A addValue() 0 9 2
A getValue() 0 4 1
A getExtends() 0 10 4
A getInheritanceStruct() 0 4 1
A getTopInheritance() 0 15 4
A getMeta() 0 5 3
A getReservedMethodsInstance() 0 8 2
A getTypes() 0 4 1
A isUnion() 0 4 1
A setTypes() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Struct often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. 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\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
    private $attributes;
34
    /**
35
     * Is the struct a restriction with defined values  ?
36
     * @var bool
37
     */
38
    private $isRestriction = false;
39
    /**
40
     * If the struct is a restriction with values, then store values
41
     * @var StructValueContainer
42
     */
43
    private $values;
44
    /**
45
     * If the struct is a union with types, then store types
46
     * @var string[]
47
     */
48
    private $types;
49
    /**
50
     * Define if the urrent struct is a concrete struct or just a virtual struct to store meta informations
51
     * @var bool
52
     */
53
    private $isStruct = false;
54
    /**
55
     * Main constructor
56
     * @see AbstractModel::__construct()
57
     * @uses Struct::setIsStruct()
58
     * @param Generator $generator
59
     * @param string $name the original name
60
     * @param bool $isStruct defines if it's a real sruct or not
61
     * @param bool $isRestriction defines if it's an enumeration or not
62
     */
63 552
    public function __construct(Generator $generator, $name, $isStruct = true, $isRestriction = false)
64
    {
65 552
        parent::__construct($generator, $name);
66 552
        $this->setIsStruct($isStruct)->setIsRestriction($isRestriction)->setAttributes(new StructAttributeContainer($generator))->setValues(new StructValueContainer($generator));
67 552
    }
68
    /**
69
     * Returns the contextual part of the class name for the package
70
     * @see AbstractModel::getContextualPart()
71
     * @uses Struct::getIsRestriction()
72
     * @return string
73
     */
74 272
    public function getContextualPart()
75
    {
76 272
        $part = $this->getGenerator()->getOptionStructsFolder();
77 272
        if ($this->getIsRestriction()) {
78 100
            $part = $this->getGenerator()->getOptionEnumsFolder();
79 272
        } elseif ($this->isArray()) {
80 48
            $part = $this->getGenerator()->getOptionArraysFolder();
81 48
        }
82 272
        return $part;
83
    }
84
    /**
85
     * Returns the sub package name which the model belongs to
86
     * Must be overridden by sub classes
87
     * @see AbstractModel::getDocSubPackages()
88
     * @uses Struct::getIsRestriction()
89
     * @return array
90
     */
91 156
    public function getDocSubPackages()
92
    {
93 156
        $package = self::DOC_SUB_PACKAGE_STRUCTS;
94 156
        if ($this->getIsRestriction()) {
95 52
            $package = self::DOC_SUB_PACKAGE_ENUMERATIONS;
96 156
        } elseif ($this->isArray()) {
97 28
            $package = self::DOC_SUB_PACKAGE_ARRAYS;
98 28
        }
99
        return array(
100 156
            $package,
101 156
        );
102
    }
103
    /**
104
     * Returns true if the current struct is a collection of values (like an array)
105
     * @uses AbstractModel::getName()
106
     * @uses Struct::countOwnAttributes()
107
     * @return bool
108
     */
109 300
    public function isArray()
110
    {
111 300
        return ((($this->getIsStruct() && $this->countOwnAttributes() === 1) || (!$this->getIsStruct() && $this->countOwnAttributes() <= 1)) && stripos($this->getName(), 'array') !== false);
112
    }
113
    /**
114
     * Returns the attributes of the struct and potentially from the parent class
115
     * @uses AbstractModel::getInheritance()
116
     * @uses Struct::getIsStruct()
117
     * @uses Struct::getAttributes()
118
     * @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.
119
     * @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
120
     * @return StructAttributeContainer
121
     */
122 312
    public function getAttributes($includeInheritanceAttributes = false, $requiredFirst = false)
123
    {
124 312
        if ($includeInheritanceAttributes === false && $requiredFirst === false) {
125 312
            $attributes = $this->attributes;
126 312
        } else {
127 120
            $attributes = $this->getAllAttributes($includeInheritanceAttributes, $requiredFirst);
128
        }
129 312
        return $attributes;
130
    }
131
    /**
132
     * @param bool $includeInheritanceAttributes
133
     * @param bool $requiredFirst
134
     * @return StructAttributeContainer
135
     */
136 120
    protected function getAllAttributes($includeInheritanceAttributes, $requiredFirst)
137
    {
138 120
        $allAttributes = new StructAttributeContainer($this->getGenerator());
139 120
        if ($includeInheritanceAttributes === true) {
140 4
            $this->addInheritanceAttributes($allAttributes);
141 4
        }
142 120
        foreach ($this->attributes as $attribute) {
143 120
            $allAttributes->add($attribute);
144 120
        }
145 120
        if ($requiredFirst === true) {
146 120
            $attributes = $this->putRequiredFirst($allAttributes);
147 120
        } else {
148
            $attributes = $allAttributes;
149
        }
150 120
        return $attributes;
151
    }
152
    /**
153
     * @param StructAttributeContainer $attributes
154
     */
155 4
    protected function addInheritanceAttributes(StructAttributeContainer $attributes)
156
    {
157 4
        if ($this->getInheritance() != '' && ($model = $this->getInheritanceStruct()) instanceof Struct) {
158
            while ($model instanceof Struct && $model->getIsStruct()) {
159
                foreach ($model->getAttributes() as $attribute) {
160
                    $attributes->add($attribute);
161
                }
162
                $model = $model->getInheritanceStruct();
163
            }
164
        }
165 4
    }
166
    /**
167
     * @param StructAttributeContainer $allAttributes
168
     * @return StructAttributeContainer
169
     */
170 120
    protected function putRequiredFirst(StructAttributeContainer $allAttributes)
171
    {
172 120
        $attributes = new StructAttributeContainer($this->getGenerator());
173 120
        $requiredAttributes = new StructAttributeContainer($this->getGenerator());
174 120
        $notRequiredAttributes = new StructAttributeContainer($this->getGenerator());
175 120
        foreach ($allAttributes as $attribute) {
176 120
            if ($attribute->isRequired()) {
177 28
                $requiredAttributes->add($attribute);
178 28
            } else {
179 112
                $notRequiredAttributes->add($attribute);
180
            }
181 120
        }
182 120
        foreach ($requiredAttributes as $attribute) {
183 28
            $attributes->add($attribute);
184 120
        }
185 120
        foreach ($notRequiredAttributes as $attribute) {
186 112
            $attributes->add($attribute);
187 120
        }
188 120
        unset($requiredAttributes, $notRequiredAttributes);
189 120
        return $attributes;
190
    }
191
    /**
192
     * Returns the number of own attributes
193
     * @uses Struct::getAttributes()
194
     * @return int
195
     */
196 300
    public function countOwnAttributes()
197
    {
198 300
        return $this->getAttributes(false, false)->count();
199
    }
200
    /**
201
     * Sets the attributes of the struct
202
     * @param StructAttributeContainer $structAttributeContainer
203
     * @return Struct
204
     */
205 552
    public function setAttributes(StructAttributeContainer $structAttributeContainer)
206
    {
207 552
        $this->attributes = $structAttributeContainer;
208 552
        return $this;
209
    }
210
    /**
211
     * Adds attribute based on its original name
212
     * @throws \InvalidArgumentException
213
     * @param string $attributeName the attribute name
214
     * @param string $attributeType the attribute type
215
     * @return Struct
216
     */
217 504
    public function addAttribute($attributeName, $attributeType)
218
    {
219 504
        if (empty($attributeName) || empty($attributeType)) {
220 8
            throw new \InvalidArgumentException(sprintf('Attribute name "%s" and/or attribute type "%s" is invalid for Struct "%s"', $attributeName, $attributeType, $this->getName()), __LINE__);
221
        }
222 496
        if ($this->attributes->getStructAttributeByName($attributeName) === null) {
223 484
            $structAttribute = new StructAttribute($this->getGenerator(), $attributeName, $attributeType, $this);
224 484
            $this->attributes->add($structAttribute);
225 484
        }
226 496
        return $this;
227
    }
228
    /**
229
     * Returns the attribute by its name, otherwise null
230
     * @uses Struct::getAttributes()
231
     * @param string $attributeName the original attribute name
232
     * @return StructAttribute|null
233
     */
234 360
    public function getAttribute($attributeName)
235
    {
236 360
        return $this->attributes->getStructAttributeByName($attributeName);
237
    }
238
    /**
239
     * Returns the attribute by its cleaned name, otherwise null
240
     * @uses Struct::getAttributes()
241
     * @param string $attributeCleanName the cleaned attribute name
242
     * @return StructAttribute|null
243
     */
244 56
    public function getAttributeByCleanName($attributeCleanName)
245
    {
246 56
        return $this->attributes->getStructAttributeByCleanName($attributeCleanName);
247
    }
248
    /**
249
     * Returns the isRestriction value
250
     * @return bool
251
     */
252 304
    public function getIsRestriction()
253
    {
254 304
        return $this->isRestriction;
255
    }
256
    /**
257
     * Sets the isRestriction value
258
     * @param bool $isRestriction
259
     * @return Struct
260
     */
261 552
    public function setIsRestriction($isRestriction = true)
262
    {
263 552
        $this->isRestriction = $isRestriction;
264 552
        return $this;
265
    }
266
    /**
267
     * Returns the isStruct value
268
     * @return bool
269
     */
270 328
    public function getIsStruct()
271
    {
272 328
        return $this->isStruct;
273
    }
274
    /**
275
     * Sets the isStruct value
276
     * @param bool $isStruct
277
     * @return Struct
278
     */
279 552
    public function setIsStruct($isStruct = true)
280
    {
281 552
        $this->isStruct = $isStruct;
282 552
        return $this;
283
    }
284
    /**
285
     * Returns the values for an enumeration
286
     * @return StructValueContainer
287
     */
288 312
    public function getValues()
289
    {
290 312
        return $this->values;
291
    }
292
    /**
293
     * Sets the values for an enumeration
294
     * @param StructValueContainer $structValueContainer
295
     * @return Struct
296
     */
297 552
    private function setValues(StructValueContainer $structValueContainer)
298
    {
299 552
        $this->values = $structValueContainer;
300 552
        return $this;
301
    }
302
    /**
303
     * Adds value to values array
304
     * @uses Struct::getValue()
305
     * @uses Struct::getValues()
306
     * @param mixed $value the original value
307
     * @return Struct
308
     */
309 324
    public function addValue($value)
310
    {
311 324
        if ($this->getValue($value) === null) {
312 312
            $this->values->add(new StructValue($this->getGenerator(), $value, $this->getValues()->count(), $this));
313 312
            $this->setIsRestriction(true);
314 312
            $this->setIsStruct(true);
315 312
        }
316 324
        return $this;
317
    }
318
    /**
319
     * Gets the value object for the given value
320
     * @uses Struct::getValues()
321
     * @uses AbstractModel::getName()
322
     * @param string $value Value name
323
     * @return StructValue|null
324
     */
325 324
    public function getValue($value)
326
    {
327 324
        return $this->values->getStructValueByName($value);
328
    }
329
    /**
330
     * Allows to define from which class the curent model extends
331
     * @param bool $short
332
     * @return string
333
     */
334 148
    public function getExtends($short = false)
335
    {
336 148
        $extends = '';
337 148
        if ($this->isArray()) {
338 28
            $extends = $this->getGenerator()->getOptionStructArrayClass();
339 148
        } elseif (!$this->getIsRestriction()) {
340 100
            $extends = $this->getGenerator()->getOptionStructClass();
341 100
        }
342 148
        return $short ? Utils::removeNamespace($extends) : $extends;
343
    }
344
    /**
345
     * @return Struct|null
346
     */
347 184
    public function getInheritanceStruct()
348
    {
349 184
        return $this->getGenerator()->getStruct(str_replace('[]', '', $this->getInheritance()));
350
    }
351
    /**
352
     * @return string
353
     */
354 112
    public function getTopInheritance()
355
    {
356 112
        $inheritance = $this->getInheritance();
357 112
        if (!empty($inheritance)) {
358 60
            $struct = $this->getInheritanceStruct();
359 60
            while ($struct instanceof Struct) {
360 44
                $structInheritance = $struct->getInheritance();
361 44
                if (!empty($structInheritance)) {
362 20
                    $inheritance = $structInheritance;
363 20
                }
364 44
                $struct = $struct->getInheritanceStruct();
365 44
            }
366 60
        }
367 112
        return $inheritance;
368
    }
369
    /**
370
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::getMeta()
371
     * @return string[]
372
     */
373 176
    public function getMeta()
374
    {
375 176
        $inheritanceStruct = $this->getInheritanceStruct();
376 176
        return array_merge_recursive(parent::getMeta(), ($inheritanceStruct && !$inheritanceStruct->getIsStruct()) ? $inheritanceStruct->getMeta() : array());
377
    }
378
    /**
379
     * @param $filename
380
     * @return StructReservedMethod|StructArrayReservedMethod
381
     */
382 132
    public function getReservedMethodsInstance($filename = null)
383
    {
384 132
        $instance = StructReservedMethod::instance($filename);
385 132
        if ($this->isArray()) {
386 32
            $instance = StructArrayReservedMethod::instance($filename);
387 32
        }
388 132
        return $instance;
389
    }
390
    /**
391
     * @return string[]
392
     */
393 4
    public function getTypes()
394
    {
395 4
        return $this->types;
396
    }
397
    /**
398
     * @return boolean
399
     */
400 104
    public function isUnion()
401
    {
402 104
        return count($this->types) > 0;
403
    }
404
    /**
405
     * @param string[] $types
406
     * @return Struct
407
     */
408 28
    public function setTypes($types)
409
    {
410 28
        $this->types = $types;
411 28
        return $this;
412
    }
413
}
414