Completed
Push — master ( 702d5d...4fd471 )
by Mikaël
34:06 queued 12s
created

Struct::countAllAttributes()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 2
cts 2
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 408
                mb_stripos($this->getName(), 'array') !== false
134 204
            ) ||
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 516
            $attributes = $this->attributes;
151 258
        } else {
152 642
            $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 642
    protected function getAllAttributes($includeInheritanceAttributes, $requiredFirst)
162
    {
163 642
        $allAttributes = new StructAttributeContainer($this->getGenerator());
164 642
        if ($includeInheritanceAttributes === true) {
165 642
            $this->addInheritanceAttributes($allAttributes);
166 321
        }
167 642
        foreach ($this->attributes as $attribute) {
168 576
            $allAttributes->add($attribute);
169 321
        }
170 642
        if ($requiredFirst === true) {
171 294
            $attributes = $this->putRequiredFirst($allAttributes);
172 147
        } else {
173 642
            $attributes = $allAttributes;
174
        }
175 642
        return $attributes;
176
    }
177
    /**
178
     * @param StructAttributeContainer $attributes
179
     */
180 642
    protected function addInheritanceAttributes(StructAttributeContainer $attributes)
181
    {
182 642
        if ($this->getInheritance() != '' && ($model = $this->getInheritanceStruct()) instanceof Struct) {
183 114
            while ($model instanceof Struct && $model->isStruct()) {
184 90
                foreach ($model->getAttributes() as $attribute) {
185 84
                    $attributes->add($attribute);
186 45
                }
187 90
                $model = $model->getInheritanceStruct();
188 45
            }
189 57
        }
190 642
    }
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 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 642
    public function countAllAttributes()
231
    {
232 642
        return $this->getAttributes(true)->count();
233
    }
234
    /**
235
     * Sets the attributes of the struct
236
     * @param StructAttributeContainer $structAttributeContainer
237
     * @return Struct
238
     */
239 1188
    public function setAttributes(StructAttributeContainer $structAttributeContainer)
240
    {
241 1188
        $this->attributes = $structAttributeContainer;
242 1188
        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 666
    public function isRestriction()
287
    {
288 666
        return $this->isRestriction;
289
    }
290
    /**
291
     * Sets the isRestriction value
292
     * @param bool $isRestriction
293
     * @return Struct
294
     */
295 1188
    public function setRestriction($isRestriction = true)
296
    {
297 1188
        $this->isRestriction = $isRestriction;
298 1188
        return $this;
299
    }
300
    /**
301
     * Returns the isStruct value
302
     * @return bool
303
     */
304 744
    public function isStruct()
305
    {
306 744
        return $this->isStruct;
307
    }
308
    /**
309
     * Sets the isStruct value
310
     * @param bool $isStruct
311
     * @return Struct
312
     */
313 1188
    public function setStruct($isStruct = true)
314
    {
315 1188
        $this->isStruct = $isStruct;
316 1188
        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 564
    public function setList($list = '')
341
    {
342 564
        $this->list = $list;
343 564
        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 1188
    protected function setValues(StructValueContainer $structValueContainer)
359
    {
360 1188
        $this->values = $structValueContainer;
361 1188
        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 342
    public function getExtends($short = false)
409
    {
410 342
        $extends = '';
411 342
        if ($this->isArray()) {
412 48
            $extends = $this->getGenerator()->getOptionStructArrayClass();
413 327
        } elseif (!$this->isRestriction()) {
414 264
            $extends = $this->getGenerator()->getOptionStructClass();
415 132
        }
416 342
        return $short ? Utils::removeNamespace($extends) : $extends;
417
    }
418
    /**
419
     * @return Struct|null
420
     */
421 480
    public function getInheritanceStruct()
422
    {
423 480
        return $this->getName() === $this->getInheritance() ? null : $this->getGenerator()->getStructByName(str_replace('[]', '', $this->getInheritance()));
424
    }
425
    /**
426
     * @return string
427
     */
428 312
    public function getTopInheritance()
429
    {
430 312
        $inheritance = $this->getInheritance();
431 312
        if (!empty($inheritance)) {
432 240
            $struct = $this->getInheritanceStruct();
433 240
            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 120
        }
441 312
        return $inheritance;
442
    }
443
    /**
444
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::getMeta()
445
     * @return string[]
446
     */
447 450
    public function getMeta()
448
    {
449 450
        $inheritanceStruct = $this->getInheritanceStruct();
450 450
        return $this->mergeMeta(($inheritanceStruct && !$inheritanceStruct->isStruct()) ? $inheritanceStruct->getMeta() : [], parent::getMeta());
451
    }
452
    /**
453
     * @param $filename
454
     * @return StructReservedMethod|StructArrayReservedMethod
455
     */
456 318
    public function getReservedMethodsInstance($filename = null)
457
    {
458 318
        $instance = StructReservedMethod::instance($filename);
459 318
        if ($this->isArray()) {
460 54
            $instance = StructArrayReservedMethod::instance($filename);
461 27
        }
462 318
        return $instance;
463
    }
464
    /**
465
     * @return string[]
466
     */
467 6
    public function getTypes()
468
    {
469 6
        return $this->types;
470
    }
471
    /**
472
     * @return boolean
473
     */
474 294
    public function isUnion()
475
    {
476 294
        return count($this->types) > 0;
477
    }
478
    /**
479
     * @param string[] $types
480
     * @return Struct
481
     */
482 1188
    public function setTypes(array $types)
483
    {
484 1188
        $this->types = $types;
485 1188
        return $this;
486
    }
487
    /**
488
     * {@inheritDoc}
489
     * @see \WsdlToPhp\PackageGenerator\Model\AbstractModel::toJsonSerialize()
490
     */
491 6
    protected function toJsonSerialize()
492
    {
493
        return [
494 6
            'attributes' => $this->attributes,
495 6
            'restriction' => $this->isRestriction,
496 6
            'struct' => $this->isStruct,
497 6
            'types' => $this->types,
498 6
            'values' => $this->values,
499 6
            'list' => $this->list,
500 3
        ];
501
    }
502
    /**
503
     * @param array $attributes
504
     */
505 540
    public function setAttributesFromSerializedJson(array $attributes)
506
    {
507 540
        foreach ($attributes as $attribute) {
508 534
            $this->attributes->add(self::instanceFromSerializedJson($this->generator, $attribute)->setOwner($this));
509 270
        }
510 540
    }
511
    /**
512
     * @param array $values
513
     */
514 540
    public function setValuesFromSerializedJson(array $values)
515
    {
516 540
        foreach ($values as $value) {
517 504
            $this->values->add(self::instanceFromSerializedJson($this->generator, $value)->setOwner($this));
518 270
        }
519 540
    }
520
}
521