Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
109 / 109
100.00% covered (success)
100.00%
22 / 22
CRAP
100.00% covered (success)
100.00%
1 / 1
StructArray
100.00% covered (success)
100.00%
109 / 109
100.00% covered (success)
100.00%
22 / 22
35
100.00% covered (success)
100.00%
1 / 1
 addStructMethodsSetAndGet
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
1
 setModel
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
3
 addClassElement
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addStructMethodAddTo
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodCurrent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodItem
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodFirst
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodLast
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodOffsetGet
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodGetAttributeName
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
1
 addArrayMethodAdd
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
3
 addArrayMethodGenericMethod
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodGetAttributeNameAnnotationBlock
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodCurrentAnnotationBlock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodFirstAnnotationBlock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodLastAnnotationBlock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodItemAnnotationBlock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodOffsetGetAnnotationBlock
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodAddAnnotationBlock
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 getArrayMethodGenericAnnotationBlock
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
2
 getStructMethodAnnotationBlock
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
9
 getArrayMethodBody
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace WsdlToPhp\PackageGenerator\File;
6
7use WsdlToPhp\PackageGenerator\File\Element\PhpFunctionParameter;
8use WsdlToPhp\PackageGenerator\File\Validation\Rules;
9use WsdlToPhp\PackageGenerator\Model\AbstractModel;
10use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
11use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
12use WsdlToPhp\PhpGenerator\Element\AssignedValueElementInterface;
13use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
14use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
15use WsdlToPhp\PhpGenerator\Element\PhpMethod;
16
17final class StructArray extends Struct
18{
19    public const METHOD_GET_ATTRIBUTE_NAME = 'getAttributeName';
20    public const METHOD_CURRENT = 'current';
21    public const METHOD_ITEM = 'item';
22    public const METHOD_FIRST = 'first';
23    public const METHOD_LAST = 'last';
24    public const METHOD_OFFSET_GET = 'offsetGet';
25    public const METHOD_ADD = 'add';
26
27    public function addStructMethodsSetAndGet(): self
28    {
29        parent::addStructMethodsSetAndGet();
30        $this
31            ->addArrayMethodCurrent()
32            ->addArrayMethodItem()
33            ->addArrayMethodFirst()
34            ->addArrayMethodLast()
35            ->addArrayMethodOffsetGet()
36            ->addArrayMethodAdd()
37            ->addArrayMethodGetAttributeName()
38        ;
39
40        return $this;
41    }
42
43    /**
44     * @throws \InvalidArgumentException
45     */
46    public function setModel(AbstractModel $model): self
47    {
48        if ($model instanceof StructModel && !$model->isArray()) {
49            throw new \InvalidArgumentException('The model is not a valid array struct (name must contain Array and the model must contain only one property', __LINE__);
50        }
51
52        return parent::setModel($model);
53    }
54
55    protected function addClassElement(): AbstractModelFile
56    {
57        return AbstractModelFile::addClassElement();
58    }
59
60    /**
61     * Disable this feature within StructArray class.
62     */
63    protected function addStructMethodAddTo(StructAttributeModel $attribute): Struct
64    {
65        return $this;
66    }
67
68    protected function addArrayMethodCurrent(): self
69    {
70        return $this->addArrayMethodGenericMethod(self::METHOD_CURRENT, $this->getArrayMethodBody(self::METHOD_CURRENT), [], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
71    }
72
73    protected function addArrayMethodItem(): self
74    {
75        return $this->addArrayMethodGenericMethod(self::METHOD_ITEM, $this->getArrayMethodBody(self::METHOD_ITEM, '$index'), [
76            'index',
77        ], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
78    }
79
80    protected function addArrayMethodFirst(): self
81    {
82        return $this->addArrayMethodGenericMethod(self::METHOD_FIRST, $this->getArrayMethodBody(self::METHOD_FIRST), [], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
83    }
84
85    protected function addArrayMethodLast(): self
86    {
87        return $this->addArrayMethodGenericMethod(self::METHOD_LAST, $this->getArrayMethodBody(self::METHOD_LAST), [], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
88    }
89
90    protected function addArrayMethodOffsetGet(): self
91    {
92        return $this->addArrayMethodGenericMethod(self::METHOD_OFFSET_GET, $this->getArrayMethodBody(self::METHOD_OFFSET_GET, '$offset'), [
93            'offset',
94        ], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
95    }
96
97    protected function addArrayMethodGetAttributeName(): self
98    {
99        /** @var StructModel $model */
100        $model = $this->getModel();
101
102        return $this->addArrayMethodGenericMethod(
103            self::METHOD_GET_ATTRIBUTE_NAME,
104            sprintf(
105                'return \'%s\';',
106                $model
107                    ->getAttributes()
108                    ->offsetGet(0)
109                    ->getName()
110            ),
111            [],
112            self::TYPE_STRING
113        );
114    }
115
116    protected function addArrayMethodAdd(): self
117    {
118        if ($this->getModelFromStructAttribute() instanceof StructModel) {
119            $method = new PhpMethod(self::METHOD_ADD, [
120                new PhpFunctionParameter(
121                    'item',
122                    AssignedValueElementInterface::NO_VALUE,
123                    null,
124                    $this->getStructAttribute()
125                ),
126            ], self::TYPE_SELF);
127
128            if ($this->getGenerator()->getOptionValidation()) {
129                $rules = new Rules($this, $method, $this->getStructAttribute(), $this->methods);
130                $rules->applyRules('item', true);
131            }
132
133            $method->addChild('return parent::add($item);');
134            $this->methods->add($method);
135        }
136
137        return $this;
138    }
139
140    protected function addArrayMethodGenericMethod(string $name, string $body, array $methodParameters = [], ?string $returnType = null): self
141    {
142        $method = new PhpMethod($name, $methodParameters, $returnType);
143        $method->addChild($body);
144        $this->methods->add($method);
145
146        return $this;
147    }
148
149    protected function getArrayMethodGetAttributeNameAnnotationBlock(): PhpAnnotationBlock
150    {
151        /** @var StructModel $model */
152        $model = $this->getModel();
153
154        return new PhpAnnotationBlock([
155            'Returns the attribute name',
156            new PhpAnnotation(self::ANNOTATION_SEE, sprintf('%s::%s()', $model->getExtends(true), self::METHOD_GET_ATTRIBUTE_NAME)),
157            new PhpAnnotation(self::ANNOTATION_RETURN, sprintf('string %s', $model->getAttributes()->offsetGet(0)->getName())),
158        ]);
159    }
160
161    protected function getArrayMethodCurrentAnnotationBlock(): PhpAnnotationBlock
162    {
163        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_CURRENT, 'Returns the current element');
164    }
165
166    protected function getArrayMethodFirstAnnotationBlock(): PhpAnnotationBlock
167    {
168        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_FIRST, 'Returns the first element');
169    }
170
171    protected function getArrayMethodLastAnnotationBlock(): PhpAnnotationBlock
172    {
173        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_LAST, 'Returns the last element');
174    }
175
176    protected function getArrayMethodItemAnnotationBlock(): PhpAnnotationBlock
177    {
178        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_ITEM, 'Returns the indexed element', 'int $index');
179    }
180
181    protected function getArrayMethodOffsetGetAnnotationBlock(): PhpAnnotationBlock
182    {
183        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_OFFSET_GET, 'Returns the element at the offset', 'int $offset');
184    }
185
186    protected function getArrayMethodAddAnnotationBlock(): PhpAnnotationBlock
187    {
188        return new PhpAnnotationBlock([
189            'Add element to array',
190            new PhpAnnotation(self::ANNOTATION_SEE, sprintf('%s::add()', $this->getModel()->getExtends(true))),
191            new PhpAnnotation(self::ANNOTATION_THROWS, \InvalidArgumentException::class),
192            new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $item', $this->getStructAttributeType(null, true, false))),
193            new PhpAnnotation(self::ANNOTATION_RETURN, sprintf('%s', $this->getModel()->getPackagedName(true))),
194        ]);
195    }
196
197    protected function getArrayMethodGenericAnnotationBlock(string $name, string $description, $param = null): PhpAnnotationBlock
198    {
199        $annotationBlock = new PhpAnnotationBlock([
200            $description,
201            new PhpAnnotation(self::ANNOTATION_SEE, sprintf('%s::%s()', $this->getModel()->getExtends(true), $name)),
202        ]);
203
204        if (!empty($param)) {
205            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, $param));
206        }
207        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getStructAttributeTypeGetAnnotation($this->getStructAttribute(), false, true)));
208
209        return $annotationBlock;
210    }
211
212    protected function getStructMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
213    {
214        switch ($method->getName()) {
215            case self::METHOD_GET_ATTRIBUTE_NAME:
216                $annotationBlock = $this->getArrayMethodGetAttributeNameAnnotationBlock();
217
218                break;
219
220            case self::METHOD_CURRENT:
221                $annotationBlock = $this->getArrayMethodCurrentAnnotationBlock();
222
223                break;
224
225            case self::METHOD_FIRST:
226                $annotationBlock = $this->getArrayMethodFirstAnnotationBlock();
227
228                break;
229
230            case self::METHOD_ITEM:
231                $annotationBlock = $this->getArrayMethodItemAnnotationBlock();
232
233                break;
234
235            case self::METHOD_LAST:
236                $annotationBlock = $this->getArrayMethodLastAnnotationBlock();
237
238                break;
239
240            case self::METHOD_OFFSET_GET:
241                $annotationBlock = $this->getArrayMethodOffsetGetAnnotationBlock();
242
243                break;
244
245            case self::METHOD_ADD:
246                $annotationBlock = $this->getArrayMethodAddAnnotationBlock();
247
248                break;
249
250            default:
251                $annotationBlock = parent::getStructMethodAnnotationBlock($method);
252
253                break;
254        }
255
256        return $annotationBlock;
257    }
258
259    protected function getArrayMethodBody(string $method, $var = ''): string
260    {
261        return sprintf('return parent::%s(%s);', $method, $var);
262    }
263}