Completed
Push — master ( ad8621...702d5d )
by Mikaël
52:05 queued 47:20
created

Struct::getAllAttributes()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.0072

Importance

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