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