Completed
Push — develop ( acf457...a68de9 )
by Mikaël
63:26 queued 35:59
created

Struct::setValuesFromSerializedJson()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

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