Completed
Push — develop ( d4f823...2a8a3b )
by Mikaël
46:02
created

Struct::setAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 4
ccs 1
cts 1
cp 1
crap 1
rs 10
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->countAllAttributes() === 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
     * Returns the number of all attributes
227
     * @uses Struct::getAttributes()
228
     * @return int
229
     */
230 1188
    public function countAllAttributes()
231
    {
232 1188
        return $this->getAttributes(true)->count();
233 1188
    }
234
    /**
235
     * Sets the attributes of the struct
236
     * @param StructAttributeContainer $structAttributeContainer
237
     * @return Struct
238
     */
239
    public function setAttributes(StructAttributeContainer $structAttributeContainer)
240
    {
241
        $this->attributes = $structAttributeContainer;
242 426
        return $this;
243
    }
244 426
    /**
245 12
     * Adds attribute based on its original name
246
     * @throws \InvalidArgumentException
247 414
     * @param string $attributeName the attribute name
248 414
     * @param string $attributeType the attribute type
249 414
     * @return Struct
250 207
     */
251 414
    public function addAttribute($attributeName, $attributeType)
252
    {
253
        if (empty($attributeName) || empty($attributeType)) {
254
            throw new \InvalidArgumentException(sprintf('Attribute name "%s" and/or attribute type "%s" is invalid for Struct "%s"', $attributeName, $attributeType, $this->getName()), __LINE__);
255
        }
256
        if ($this->attributes->getStructAttributeByName($attributeName) === null) {
257
            $structAttribute = new StructAttribute($this->getGenerator(), $attributeName, $attributeType, $this);
258
            $this->attributes->add($structAttribute);
259 444
        }
260
        return $this;
261 444
    }
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
    public function getAttribute($attributeName)
269 120
    {
270
        return $this->attributes->getStructAttributeByName($attributeName);
271 120
    }
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 666
     */
278
    public function getAttributeByCleanName($attributeCleanName)
279 666
    {
280
        return $this->attributes->getStructAttributeByCleanName($attributeCleanName);
281
    }
282
    /**
283
     * Returns the isRestriction value
284
     * @return bool
285
     */
286 1188
    public function isRestriction()
287
    {
288 1188
        return $this->isRestriction;
289 1188
    }
290
    /**
291
     * Sets the isRestriction value
292
     * @param bool $isRestriction
293
     * @return Struct
294
     */
295 744
    public function setRestriction($isRestriction = true)
296
    {
297 744
        $this->isRestriction = $isRestriction;
298
        return $this;
299
    }
300
    /**
301
     * Returns the isStruct value
302
     * @return bool
303
     */
304 1188
    public function isStruct()
305
    {
306 1188
        return $this->isStruct;
307 1188
    }
308
    /**
309
     * Sets the isStruct value
310
     * @param bool $isStruct
311
     * @return Struct
312
     */
313 30
    public function setStruct($isStruct = true)
314
    {
315 30
        $this->isStruct = $isStruct;
316
        return $this;
317
    }
318
    /**
319
     * Returns the list value
320
     * @return string
321
     */
322 306
    public function getList()
323
    {
324 306
        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 564
    public function isList()
332
    {
333 564
        return !empty($this->list);
334 564
    }
335
    /**
336
     * Sets the list value
337
     * @param string $list
338
     * @return Struct
339
     */
340 198
    public function setList($list = '')
341
    {
342 198
        $this->list = $list;
343
        return $this;
344
    }
345
    /**
346
     * Returns the values for an enumeration
347
     * @return StructValueContainer
348
     */
349 1188
    public function getValues()
350
    {
351 1188
        return $this->values;
352 1188
    }
353
    /**
354
     * Sets the values for an enumeration
355
     * @param StructValueContainer $structValueContainer
356
     * @return Struct
357
     */
358
    protected function setValues(StructValueContainer $structValueContainer)
359
    {
360
        $this->values = $structValueContainer;
361 108
        return $this;
362
    }
363 108
    /**
364
     * Adds value to values array
365
     * @uses Struct::getValue()
366
     * @uses Struct::getValues()
367 108
     * @param mixed $value the original value
368
     * @return Struct
369
     */
370
    public function addValue($value)
371
    {
372
        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 54
            // this is why enumerations has to be parsed before any other elements by the WSDL parsers
376 108
            if (0 < $this->countOwnAttributes()) {
377 108
                $enum = new static($this->getGenerator(), $this->getName(), true, true);
378 108
                $enum
379
                    ->setInheritance(self::DEFAULT_ENUM_TYPE)
380 54
                    ->getValues()->add(new StructValue($enum->getGenerator(), $value, $enum->getValues()->count(), $enum));
381 108
                $this->getGenerator()->getStructs()->add($enum);
382
                return $enum;
383
            } else {
384
                $this
385
                    ->setStruct(true)
386
                    ->setRestriction(true)
387
                    ->values->add(new StructValue($this->getGenerator(), $value, $this->getValues()->count(), $this));
388
            }
389
        }
390 198
        return $this;
391
    }
392 198
    /**
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 342
    public function getValue($value)
400
    {
401 342
        return $this->values->getStructValueByName($value);
402 342
    }
403 48
    /**
404 327
     * Allows to define from which class the current model extends
405 264
     * @param bool $short
406 132
     * @return string
407 342
     */
408
    public function getExtends($short = false)
409
    {
410
        $extends = '';
411
        if ($this->isArray()) {
412 462
            $extends = $this->getGenerator()->getOptionStructArrayClass();
413
        } elseif (!$this->isRestriction()) {
414 462
            $extends = $this->getGenerator()->getOptionStructClass();
415
        }
416
        return $short ? Utils::removeNamespace($extends) : $extends;
417
    }
418
    /**
419 312
     * @return Struct|null
420
     */
421 312
    public function getInheritanceStruct()
422 312
    {
423 240
        return $this->getName() === $this->getInheritance() ? null : $this->getGenerator()->getStructByName(str_replace('[]', '', $this->getInheritance()));
424 240
    }
425 138
    /**
426 138
     * @return string
427 84
     */
428 42
    public function getTopInheritance()
429 138
    {
430 69
        $inheritance = $this->getInheritance();
431 120
        if (!empty($inheritance)) {
432 312
            $struct = $this->getInheritanceStruct();
433
            while ($struct instanceof Struct) {
434
                $structInheritance = $struct->getInheritance();
435
                if (!empty($structInheritance)) {
436
                    $inheritance = $structInheritance;
437
                }
438 450
                $struct = $struct->getInheritanceStruct();
439
            }
440 450
        }
441 450
        return $inheritance;
442
    }
443
    /**
444
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::getMeta()
445
     * @return string[]
446
     */
447 318
    public function getMeta()
448
    {
449 318
        $inheritanceStruct = $this->getInheritanceStruct();
450 318
        return $this->mergeMeta(($inheritanceStruct && !$inheritanceStruct->isStruct()) ? $inheritanceStruct->getMeta() : [], parent::getMeta());
451 54
    }
452 27
    /**
453 318
     * @param $filename
454
     * @return StructReservedMethod|StructArrayReservedMethod
455
     */
456
    public function getReservedMethodsInstance($filename = null)
457
    {
458 6
        $instance = StructReservedMethod::instance($filename);
459
        if ($this->isArray()) {
460 6
            $instance = StructArrayReservedMethod::instance($filename);
461
        }
462
        return $instance;
463
    }
464
    /**
465 294
     * @return string[]
466
     */
467 294
    public function getTypes()
468
    {
469
        return $this->types;
470
    }
471
    /**
472
     * @return boolean
473 1188
     */
474
    public function isUnion()
475 1188
    {
476 1188
        return count($this->types) > 0;
477
    }
478
    /**
479
     * @param string[] $types
480
     * @return Struct
481
     */
482 6
    public function setTypes(array $types)
483
    {
484
        $this->types = $types;
485 6
        return $this;
486 6
    }
487 6
    /**
488 6
     * {@inheritDoc}
489 6
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::toJsonSerialize()
490 6
     */
491 3
    protected function toJsonSerialize()
492
    {
493
        return [
494
            'attributes' => $this->attributes,
495
            'restriction' => $this->isRestriction,
496 540
            'struct' => $this->isStruct,
497
            'types' => $this->types,
498 540
            'values' => $this->values,
499 534
            'list' => $this->list,
500 270
        ];
501 540
    }
502
    /**
503
     * @param array $attributes
504
     */
505 540
    public function setAttributesFromSerializedJson(array $attributes)
506
    {
507 540
        foreach ($attributes as $attribute) {
508 504
            $this->attributes->add(self::instanceFromSerializedJson($this->generator, $attribute)->setOwner($this));
509 270
        }
510 540
    }
511
    /**
512
     * @param array $values
513
     */
514
    public function setValuesFromSerializedJson(array $values)
515
    {
516
        foreach ($values as $value) {
517
            $this->values->add(self::instanceFromSerializedJson($this->generator, $value)->setOwner($this));
518
        }
519
    }
520
}
521