Passed
Push — master ( d8ac0a...430361 )
by Mikaël
15:43 queued 14s
created

StructArray::addClassElement()   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 0
Metric Value
cc 1
eloc 1
c 0
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
declare(strict_types=1);
4
5
namespace WsdlToPhp\PackageGenerator\File;
6
7
use WsdlToPhp\PackageGenerator\File\Element\PhpFunctionParameter;
8
use WsdlToPhp\PackageGenerator\File\Validation\Rules;
9
use WsdlToPhp\PackageGenerator\Model\AbstractModel;
10
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel;
11
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel;
12
use WsdlToPhp\PhpGenerator\Element\AssignedValueElementInterface;
13
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation;
14
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock;
15
use WsdlToPhp\PhpGenerator\Element\PhpMethod;
16
17
final 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 16
    public function addStructMethodsSetAndGet(): self
28
    {
29 16
        parent::addStructMethodsSetAndGet();
30
        $this
31 16
            ->addArrayMethodCurrent()
32 16
            ->addArrayMethodItem()
33 16
            ->addArrayMethodFirst()
34 16
            ->addArrayMethodLast()
35 16
            ->addArrayMethodOffsetGet()
36 16
            ->addArrayMethodAdd()
37 16
            ->addArrayMethodGetAttributeName()
38
        ;
39
40 16
        return $this;
41
    }
42
43 22
    protected function addClassElement(): AbstractModelFile
44
    {
45 22
        return AbstractModelFile::addClassElement();
46 4
    }
47
48
    public function setModel(AbstractModel $model): self
49 18
    {
50
        if ($model instanceof StructModel && !$model->isArray()) {
51
            throw new \InvalidArgumentException('The model is not a valid array struct (name must contain Array and the model must contain only one property', __LINE__);
52
        }
53
54
        return parent::setModel($model);
0 ignored issues
show
Bug Best Practice introduced by
The expression return parent::setModel($model) returns the type WsdlToPhp\PackageGenerator\File\Struct which includes types incompatible with the type-hinted return WsdlToPhp\PackageGenerator\File\StructArray.
Loading history...
55 16
    }
56
57 16
    /**
58
     * Disable this feature within StructArray class.
59
     */
60 16
    protected function addStructMethodAddTo(StructAttributeModel $attribute): Struct
61
    {
62 16
        return $this;
63
    }
64
65 16
    protected function addArrayMethodCurrent(): self
66
    {
67 16
        return $this->addArrayMethodGenericMethod(self::METHOD_CURRENT, $this->getArrayMethodBody(self::METHOD_CURRENT), [], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
68 16
    }
69 16
70
    protected function addArrayMethodItem(): self
71
    {
72 16
        return $this->addArrayMethodGenericMethod(self::METHOD_ITEM, $this->getArrayMethodBody(self::METHOD_ITEM, '$index'), [
73
            'index',
74 16
        ], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
75
    }
76
77 16
    protected function addArrayMethodFirst(): self
78
    {
79 16
        return $this->addArrayMethodGenericMethod(self::METHOD_FIRST, $this->getArrayMethodBody(self::METHOD_FIRST), [], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
80
    }
81
82 16
    protected function addArrayMethodLast(): self
83
    {
84 16
        return $this->addArrayMethodGenericMethod(self::METHOD_LAST, $this->getArrayMethodBody(self::METHOD_LAST), [], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
85 16
    }
86 16
87
    protected function addArrayMethodOffsetGet(): self
88
    {
89 16
        return $this->addArrayMethodGenericMethod(self::METHOD_OFFSET_GET, $this->getArrayMethodBody(self::METHOD_OFFSET_GET, '$offset'), [
90
            'offset',
91 16
        ], '?'.$this->getStructAttributeTypeAsPhpType($this->getStructAttribute(), false));
92 16
    }
93
94 16
    protected function addArrayMethodGetAttributeName(): self
95
    {
96 16
        /** @var StructModel $model */
97 16
        $model = $this->getModel();
98 16
99 16
        return $this->addArrayMethodGenericMethod(
100
            self::METHOD_GET_ATTRIBUTE_NAME,
101 16
            sprintf(
102 16
                'return \'%s\';',
103
                $model
104
                    ->getAttributes()
105
                    ->offsetGet(0)
106 16
                    ->getName()
107
            ),
108 16
            [],
109 14
            self::TYPE_STRING
110 14
        );
111 14
    }
112 14
113 14
    protected function addArrayMethodAdd(): self
114 14
    {
115
        if ($this->getModelFromStructAttribute() instanceof StructModel) {
116 14
            $method = new PhpMethod(self::METHOD_ADD, [
117
                new PhpFunctionParameter(
118 14
                    'item',
119 14
                    AssignedValueElementInterface::NO_VALUE,
120 14
                    null,
121 14
                    $this->getStructAttribute()
122 6
                ),
123
            ], self::TYPE_SELF);
124 12
125
            if ($this->getGenerator()->getOptionValidation()) {
126
                $rules = new Rules($this, $method, $this->getStructAttribute(), $this->methods);
0 ignored issues
show
Bug introduced by
It seems like $this->getStructAttribute() can also be of type null; however, parameter $attribute of WsdlToPhp\PackageGenerat...on\Rules::__construct() does only seem to accept WsdlToPhp\PackageGenerator\Model\StructAttribute, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

126
                $rules = new Rules($this, $method, /** @scrutinizer ignore-type */ $this->getStructAttribute(), $this->methods);
Loading history...
127
                $rules->applyRules('item', true);
128 14
            }
129 14
130
            $method->addChild('return parent::add($item);');
131
            $this->methods->add($method);
132 16
        }
133
134
        return $this;
135 16
    }
136
137 16
    protected function addArrayMethodGenericMethod(string $name, string $body, array $methodParameters = [], ?string $returnType = null): self
138 16
    {
139 16
        $method = new PhpMethod($name, $methodParameters, $returnType);
140
        $method->addChild($body);
141 16
        $this->methods->add($method);
142
143
        return $this;
144 16
    }
145
146 16
    protected function getArrayMethodGetAttributeNameAnnotationBlock(): PhpAnnotationBlock
147 16
    {
148 16
        /** @var StructModel $model */
149 16
        $model = $this->getModel();
150
151
        return new PhpAnnotationBlock([
152
            'Returns the attribute name',
153 16
            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 16
        ]);
156
    }
157
158 16
    protected function getArrayMethodCurrentAnnotationBlock(): PhpAnnotationBlock
159
    {
160 16
        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_CURRENT, 'Returns the current element');
161
    }
162
163 16
    protected function getArrayMethodFirstAnnotationBlock(): PhpAnnotationBlock
164
    {
165 16
        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_FIRST, 'Returns the first element');
166
    }
167
168 16
    protected function getArrayMethodLastAnnotationBlock(): PhpAnnotationBlock
169
    {
170 16
        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_LAST, 'Returns the last element');
171
    }
172
173 16
    protected function getArrayMethodItemAnnotationBlock(): PhpAnnotationBlock
174
    {
175 16
        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_ITEM, 'Returns the indexed element', 'int $index');
176
    }
177
178 14
    protected function getArrayMethodOffsetGetAnnotationBlock(): PhpAnnotationBlock
179
    {
180 14
        return $this->getArrayMethodGenericAnnotationBlock(self::METHOD_OFFSET_GET, 'Returns the element at the offset', 'int $offset');
181 14
    }
182 14
183 14
    protected function getArrayMethodAddAnnotationBlock(): PhpAnnotationBlock
184 14
    {
185 14
        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 16
            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 16
        ]);
192 16
    }
193 16
194
    protected function getArrayMethodGenericAnnotationBlock(string $name, string $description, $param = null): PhpAnnotationBlock
195
    {
196 16
        $annotationBlock = new PhpAnnotationBlock([
197 16
            $description,
198
            new PhpAnnotation(self::ANNOTATION_SEE, sprintf('%s::%s()', $this->getModel()->getExtends(true), $name)),
199 16
        ]);
200
201 16
        if (!empty($param)) {
202
            $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, $param));
203
        }
204 16
        $annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getStructAttributeTypeGetAnnotation($this->getStructAttribute(), false, true)));
205
206 16
        return $annotationBlock;
207 16
    }
208 16
209
    protected function getStructMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock
210 16
    {
211
        switch ($method->getName()) {
212 16
            case self::METHOD_GET_ATTRIBUTE_NAME:
213 16
                $annotationBlock = $this->getArrayMethodGetAttributeNameAnnotationBlock();
214
215 16
                break;
216
217 16
            case self::METHOD_CURRENT:
218 16
                $annotationBlock = $this->getArrayMethodCurrentAnnotationBlock();
219
220 16
                break;
221
222 16
            case self::METHOD_FIRST:
223 16
                $annotationBlock = $this->getArrayMethodFirstAnnotationBlock();
224
225 16
                break;
226
227 16
            case self::METHOD_ITEM:
228 16
                $annotationBlock = $this->getArrayMethodItemAnnotationBlock();
229
230 16
                break;
231
232 16
            case self::METHOD_LAST:
233 16
                $annotationBlock = $this->getArrayMethodLastAnnotationBlock();
234
235 16
                break;
236
237 16
            case self::METHOD_OFFSET_GET:
238 14
                $annotationBlock = $this->getArrayMethodOffsetGetAnnotationBlock();
239
240 14
                break;
241
242
            case self::METHOD_ADD:
243 16
                $annotationBlock = $this->getArrayMethodAddAnnotationBlock();
244
245 16
                break;
246
247
            default:
248 16
                $annotationBlock = parent::getStructMethodAnnotationBlock($method);
249
250
                break;
251 16
        }
252
253 16
        return $annotationBlock;
254
    }
255
256
    protected function getArrayMethodBody(string $method, $var = ''): string
257
    {
258
        return sprintf('return parent::%s(%s);', $method, $var);
259
    }
260
}
261