1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
declare(strict_types=1); |
4
|
|
|
|
5
|
|
|
namespace WsdlToPhp\PackageGenerator\File; |
6
|
|
|
|
7
|
|
|
use InvalidArgumentException; |
8
|
|
|
use WsdlToPhp\PackageGenerator\Container\Model\StructAttribute as StructAttributeContainer; |
9
|
|
|
use WsdlToPhp\PackageGenerator\Container\PhpElement\Constant as ConstantContainer; |
10
|
|
|
use WsdlToPhp\PackageGenerator\Container\PhpElement\Property as PropertyContainer; |
11
|
|
|
use WsdlToPhp\PackageGenerator\File\Element\PhpFunctionParameter; |
12
|
|
|
use WsdlToPhp\PackageGenerator\File\Validation\Rules; |
13
|
|
|
use WsdlToPhp\PackageGenerator\Model\AbstractModel; |
14
|
|
|
use WsdlToPhp\PackageGenerator\Model\Struct as StructModel; |
15
|
|
|
use WsdlToPhp\PackageGenerator\Model\StructAttribute as StructAttributeModel; |
16
|
|
|
use WsdlToPhp\PhpGenerator\Element\PhpAnnotation; |
17
|
|
|
use WsdlToPhp\PhpGenerator\Element\PhpAnnotationBlock; |
18
|
|
|
use WsdlToPhp\PhpGenerator\Element\PhpConstant; |
19
|
|
|
use WsdlToPhp\PhpGenerator\Element\PhpMethod; |
20
|
|
|
use WsdlToPhp\PhpGenerator\Element\PhpProperty; |
21
|
|
|
|
22
|
|
|
class Struct extends AbstractModelFile |
23
|
|
|
{ |
24
|
136 |
|
public function setModel(AbstractModel $model): self |
25
|
|
|
{ |
26
|
136 |
|
if (!$model instanceof StructModel) { |
27
|
2 |
|
throw new InvalidArgumentException('Model must be an instance of a Struct', __LINE__); |
28
|
|
|
} |
29
|
|
|
|
30
|
134 |
|
return parent::setModel($model); |
|
|
|
|
31
|
|
|
} |
32
|
|
|
|
33
|
132 |
|
public function getModel(): ?StructModel |
34
|
|
|
{ |
35
|
132 |
|
return parent::getModel(); |
|
|
|
|
36
|
|
|
} |
37
|
|
|
|
38
|
106 |
|
protected function defineUseStatements(): self |
39
|
|
|
{ |
40
|
106 |
|
if ($this->getGenerator()->getOptionValidation()) { |
41
|
104 |
|
$this->getFile()->addUse(InvalidArgumentException::class, null, false); |
42
|
|
|
} |
43
|
|
|
|
44
|
106 |
|
return parent::defineUseStatements(); |
|
|
|
|
45
|
|
|
} |
46
|
|
|
|
47
|
|
|
protected function fillClassConstants(ConstantContainer $constants): void |
48
|
|
|
{ |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
protected function getConstantAnnotationBlock(PhpConstant $constant): ?PhpAnnotationBlock |
52
|
|
|
{ |
53
|
|
|
return null; |
54
|
|
|
} |
55
|
|
|
|
56
|
122 |
|
protected function getModelAttributes(): StructAttributeContainer |
57
|
|
|
{ |
58
|
122 |
|
return $this->getModel()->getProperAttributes(true); |
59
|
|
|
} |
60
|
|
|
|
61
|
122 |
|
protected function fillClassProperties(PropertyContainer $properties): void |
62
|
|
|
{ |
63
|
|
|
/** @var StructAttributeModel $attribute */ |
64
|
122 |
|
foreach ($this->getModelAttributes() as $attribute) { |
65
|
|
|
switch (true) { |
66
|
102 |
|
case $attribute->isXml(): |
67
|
4 |
|
$type = null; |
68
|
|
|
|
69
|
4 |
|
break; |
70
|
|
|
|
71
|
|
|
default: |
72
|
102 |
|
$type = (($attribute->isRequired() && !$attribute->isNullable()) ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute); |
73
|
|
|
|
74
|
102 |
|
break; |
75
|
|
|
} |
76
|
|
|
|
77
|
102 |
|
$properties->add( |
78
|
102 |
|
new PhpProperty( |
79
|
102 |
|
$attribute->getCleanName(), |
80
|
102 |
|
$attribute->isRequired() ? PhpProperty::NO_VALUE : null, |
81
|
102 |
|
$this->getGenerator()->getOptionValidation() ? PhpProperty::ACCESS_PROTECTED : PhpProperty::ACCESS_PUBLIC, |
82
|
|
|
$type |
83
|
|
|
) |
84
|
|
|
); |
85
|
|
|
} |
86
|
|
|
} |
87
|
|
|
|
88
|
102 |
|
protected function getPropertyAnnotationBlock(PhpProperty $property): ?PhpAnnotationBlock |
89
|
|
|
{ |
90
|
102 |
|
$annotationBlock = new PhpAnnotationBlock(); |
91
|
102 |
|
$annotationBlock->addChild(sprintf('The %s', $property->getName())); |
92
|
102 |
|
$attribute = $this->getModel()->getAttribute($property->getName()); |
93
|
102 |
|
if (!$attribute instanceof StructAttributeModel) { |
94
|
2 |
|
$attribute = $this->getModel()->getAttributeByCleanName($property->getName()); |
95
|
|
|
} |
96
|
102 |
|
if ($attribute instanceof StructAttributeModel) { |
97
|
102 |
|
$this->defineModelAnnotationsFromWsdl($annotationBlock, $attribute); |
98
|
102 |
|
$annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_VAR, $this->getStructAttributeTypeGetAnnotation($attribute))); |
99
|
|
|
} |
100
|
|
|
|
101
|
102 |
|
return $annotationBlock; |
102
|
|
|
} |
103
|
|
|
|
104
|
106 |
|
protected function fillClassMethods(): void |
105
|
|
|
{ |
106
|
|
|
$this |
107
|
106 |
|
->addStructMethodConstruct() |
108
|
106 |
|
->addStructMethodsSetAndGet() |
109
|
|
|
; |
110
|
|
|
} |
111
|
|
|
|
112
|
106 |
|
protected function addStructMethodConstruct(): self |
113
|
|
|
{ |
114
|
106 |
|
if (0 < count($parameters = $this->getStructMethodParametersValues())) { |
115
|
102 |
|
$method = new PhpMethod(self::METHOD_CONSTRUCT, $parameters); |
116
|
102 |
|
$this->addStructMethodConstructBody($method); |
117
|
102 |
|
$this->methods->add($method); |
118
|
|
|
} |
119
|
|
|
|
120
|
106 |
|
return $this; |
121
|
|
|
} |
122
|
|
|
|
123
|
102 |
|
protected function addStructMethodConstructBody(PhpMethod $method): self |
124
|
|
|
{ |
125
|
102 |
|
$count = $this->getModelAttributes()->count(); |
126
|
102 |
|
foreach ($this->getModelAttributes() as $index => $attribute) { |
127
|
102 |
|
if (0 === $index) { |
128
|
102 |
|
$method->addChild('$this'); |
129
|
|
|
} |
130
|
102 |
|
$this->addStructMethodConstructBodyForAttribute($method, $attribute, $count - 1 === $index); |
131
|
|
|
} |
132
|
|
|
|
133
|
102 |
|
return $this; |
134
|
|
|
} |
135
|
|
|
|
136
|
102 |
|
protected function addStructMethodConstructBodyForAttribute(PhpMethod $method, StructAttributeModel $attribute, bool $isLast): self |
137
|
|
|
{ |
138
|
102 |
|
$uniqueString = $attribute->getUniqueString($attribute->getCleanName(), 'method'); |
139
|
102 |
|
$method->addChild($method->getIndentedString(sprintf('->%s($%s)%s', $attribute->getSetterName(), lcfirst($uniqueString), $isLast ? ';' : ''), 1)); |
140
|
|
|
|
141
|
102 |
|
return $this; |
142
|
|
|
} |
143
|
|
|
|
144
|
106 |
|
protected function getStructMethodParametersValues(): array |
145
|
|
|
{ |
146
|
106 |
|
$parametersValues = []; |
147
|
106 |
|
foreach ($this->getModelAttributes() as $attribute) { |
148
|
102 |
|
$parametersValues[] = $this->getStructMethodParameter($attribute); |
149
|
|
|
} |
150
|
|
|
|
151
|
106 |
|
return $parametersValues; |
152
|
|
|
} |
153
|
|
|
|
154
|
102 |
|
protected function getStructMethodParameter(StructAttributeModel $attribute): PhpFunctionParameter |
155
|
|
|
{ |
156
|
|
|
switch (true) { |
157
|
102 |
|
case $attribute->isXml(): |
158
|
102 |
|
case $attribute->isList(): |
159
|
10 |
|
$type = null; |
160
|
|
|
|
161
|
10 |
|
break; |
162
|
|
|
|
163
|
|
|
default: |
164
|
102 |
|
$type = (($attribute->isRequired() && !$attribute->isNullable()) ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute); |
165
|
|
|
|
166
|
102 |
|
break; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
try { |
170
|
102 |
|
return new PhpFunctionParameter( |
171
|
102 |
|
lcfirst($attribute->getUniqueString($attribute->getCleanName(), 'method')), |
172
|
102 |
|
$attribute->isRequired() ? PhpFunctionParameter::NO_VALUE : $attribute->getDefaultValue(), |
173
|
|
|
$type, |
174
|
|
|
$attribute |
175
|
|
|
); |
176
|
|
|
} catch (InvalidArgumentException $exception) { |
177
|
|
|
throw new InvalidArgumentException(sprintf('Unable to create function parameter for struct "%s" with type "%s" for attribute "%s"', $this->getModel()->getName(), var_export($this->getStructAttributeTypeAsPhpType($attribute), true), $attribute->getName()), __LINE__, $exception); |
178
|
|
|
} |
179
|
|
|
} |
180
|
|
|
|
181
|
106 |
|
protected function addStructMethodsSetAndGet(): self |
182
|
|
|
{ |
183
|
106 |
|
foreach ($this->getModelAttributes() as $attribute) { |
184
|
|
|
$this |
185
|
102 |
|
->addStructMethodGet($attribute) |
186
|
102 |
|
->addStructMethodSet($attribute) |
187
|
102 |
|
->addStructMethodAddTo($attribute) |
188
|
|
|
; |
189
|
|
|
} |
190
|
|
|
|
191
|
106 |
|
return $this; |
192
|
|
|
} |
193
|
|
|
|
194
|
92 |
|
protected function addStructMethodAddTo(StructAttributeModel $attribute): self |
195
|
|
|
{ |
196
|
92 |
|
if ($attribute->isArray()) { |
197
|
38 |
|
$method = new PhpMethod(sprintf('addTo%s', ucfirst($attribute->getCleanName())), [ |
198
|
38 |
|
new PhpFunctionParameter( |
199
|
|
|
'item', |
200
|
|
|
PhpFunctionParameter::NO_VALUE, |
201
|
38 |
|
$this->getStructAttributeTypeAsPhpType($attribute, false), |
202
|
|
|
$attribute |
203
|
|
|
), |
204
|
|
|
], self::TYPE_SELF); |
205
|
38 |
|
$this->addStructMethodAddToBody($method, $attribute); |
206
|
38 |
|
$this->methods->add($method); |
207
|
|
|
} |
208
|
|
|
|
209
|
92 |
|
return $this; |
210
|
|
|
} |
211
|
|
|
|
212
|
38 |
|
protected function addStructMethodAddToBody(PhpMethod $method, StructAttributeModel $attribute): self |
213
|
|
|
{ |
214
|
38 |
|
if ($this->getGenerator()->getOptionValidation()) { |
215
|
38 |
|
$this->applyRules($method, $attribute, 'item', true); |
216
|
|
|
} |
217
|
|
|
|
218
|
38 |
|
if ($attribute->nameIsClean()) { |
219
|
38 |
|
$assignment = sprintf('$this->%s[] = $item;', $attribute->getCleanName()); |
220
|
|
|
} else { |
221
|
|
|
$assignment = sprintf('$this->%s[] = $this->{\'%s\'}[] = $item;', $attribute->getCleanName(), addslashes($attribute->getName())); |
222
|
|
|
} |
223
|
|
|
|
224
|
|
|
$method |
225
|
38 |
|
->addChild($assignment) |
226
|
38 |
|
->addChild('') |
227
|
38 |
|
->addChild('return $this;') |
228
|
|
|
; |
229
|
|
|
|
230
|
38 |
|
return $this; |
231
|
|
|
} |
232
|
|
|
|
233
|
102 |
|
protected function addStructMethodSet(StructAttributeModel $attribute): self |
234
|
|
|
{ |
235
|
102 |
|
$method = new PhpMethod($attribute->getSetterName(), [ |
236
|
102 |
|
$this->getStructMethodParameter($attribute), |
237
|
|
|
], self::TYPE_SELF); |
238
|
102 |
|
$this->addStructMethodSetBody($method, $attribute); |
239
|
102 |
|
$this->methods->add($method); |
240
|
|
|
|
241
|
102 |
|
return $this; |
242
|
|
|
} |
243
|
|
|
|
244
|
102 |
|
protected function addStructMethodSetBody(PhpMethod $method, StructAttributeModel $attribute): self |
245
|
|
|
{ |
246
|
102 |
|
$parameters = $method->getParameters(); |
247
|
102 |
|
$parameter = array_shift($parameters); |
248
|
102 |
|
$parameterName = is_string($parameter) ? $parameter : $parameter->getName(); |
249
|
102 |
|
if ($this->getGenerator()->getOptionValidation()) { |
250
|
100 |
|
$this->applyRules($method, $attribute, $parameterName); |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
return $this |
254
|
102 |
|
->addStructMethodSetBodyAssignment($method, $attribute, $parameterName) |
255
|
102 |
|
->addStructMethodSetBodyReturn($method) |
256
|
|
|
; |
257
|
|
|
} |
258
|
|
|
|
259
|
102 |
|
protected function addStructMethodSetBodyAssignment(PhpMethod $method, StructAttributeModel $attribute, string $parameterName): self |
260
|
|
|
{ |
261
|
102 |
|
if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) { |
262
|
|
|
$method |
263
|
18 |
|
->addChild(sprintf('if (is_null($%1$s) || (is_array($%1$s) && empty($%1$s))) {', $parameterName)) |
264
|
18 |
|
->addChild($method->getIndentedString(sprintf('unset($this->%1$s%2$s);', $attribute->getCleanName(), $attribute->nameIsClean() ? '' : sprintf(', $this->{\'%s\'}', addslashes($attribute->getName()))), 1)) |
265
|
18 |
|
->addChild('} else {') |
266
|
18 |
|
->addChild($method->getIndentedString($this->getStructMethodSetBodyAssignment($attribute, $parameterName), 1)) |
267
|
18 |
|
->addChild('}') |
268
|
|
|
; |
269
|
|
|
} else { |
270
|
98 |
|
$method->addChild($this->getStructMethodSetBodyAssignment($attribute, $parameterName)); |
271
|
|
|
} |
272
|
|
|
|
273
|
102 |
|
return $this; |
274
|
|
|
} |
275
|
|
|
|
276
|
102 |
|
protected function addStructMethodSetBodyReturn(PhpMethod $method): self |
277
|
|
|
{ |
278
|
|
|
$method |
279
|
102 |
|
->addChild('') |
280
|
102 |
|
->addChild('return $this;') |
281
|
|
|
; |
282
|
|
|
|
283
|
102 |
|
return $this; |
284
|
|
|
} |
285
|
|
|
|
286
|
102 |
|
protected function getStructMethodSetBodyAssignment(StructAttributeModel $attribute, string $parameterName): string |
287
|
|
|
{ |
288
|
102 |
|
$prefix = '$'; |
289
|
102 |
|
if ($attribute->isList()) { |
290
|
6 |
|
$prefix = ''; |
291
|
6 |
|
$parameterName = sprintf('is_array($%1$s) ? implode(\' \', $%1$s) : $%1$s', $parameterName); |
292
|
102 |
|
} elseif ($attribute->isXml()) { |
293
|
4 |
|
$prefix = ''; |
294
|
4 |
|
$parameterName = sprintf('($%1$s instanceof \DOMDocument) ? $%1$s->saveXML($%1$s->hasChildNodes() ? $%1$s->childNodes->item(0) : null) : $%1$s', $parameterName); |
295
|
|
|
} |
296
|
|
|
|
297
|
102 |
|
if ($attribute->nameIsClean()) { |
298
|
102 |
|
$assignment = sprintf('$this->%s = %s%s;', $attribute->getName(), $prefix, $parameterName); |
299
|
|
|
} else { |
300
|
2 |
|
$assignment = sprintf('$this->%s = $this->{\'%s\'} = %s%s;', $attribute->getCleanName(), addslashes($attribute->getName()), $prefix, $parameterName); |
301
|
|
|
} |
302
|
|
|
|
303
|
102 |
|
return $assignment; |
304
|
|
|
} |
305
|
|
|
|
306
|
102 |
|
protected function addStructMethodGetBody(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self |
307
|
|
|
{ |
308
|
102 |
|
return $this->addStructMethodGetBodyReturn($method, $attribute, $thisAccess); |
309
|
|
|
} |
310
|
|
|
|
311
|
102 |
|
protected function addStructMethodGetBodyReturn(PhpMethod $method, StructAttributeModel $attribute, string $thisAccess): self |
312
|
|
|
{ |
313
|
102 |
|
$return = sprintf('return $this->%s;', $thisAccess); |
314
|
102 |
|
if ($attribute->isXml()) { |
315
|
|
|
$method |
316
|
4 |
|
->addChild('$domDocument = null;') |
317
|
4 |
|
->addChild(sprintf('if (!empty($this->%1$s) && $asDomDocument) {', $thisAccess)) |
318
|
4 |
|
->addChild($method->getIndentedString('$domDocument = new \DOMDocument(\'1.0\', \'UTF-8\');', 1)) |
319
|
4 |
|
->addChild($method->getIndentedString(sprintf('$domDocument->loadXML($this->%s);', $thisAccess), 1)) |
320
|
4 |
|
->addChild('}') |
321
|
|
|
; |
322
|
4 |
|
if ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) { |
323
|
|
|
$return = sprintf('return $asDomDocument ? $domDocument : (isset($this->%1$s) ? $this->%1$s : null);', $thisAccess); |
324
|
|
|
} else { |
325
|
4 |
|
$return = sprintf('return $asDomDocument ? $domDocument : $this->%1$s;', $thisAccess); |
326
|
|
|
} |
327
|
102 |
|
} elseif ($attribute->getRemovableFromRequest() || $attribute->isAChoice()) { |
328
|
18 |
|
$return = sprintf('return isset($this->%1$s) ? $this->%1$s : null;', $thisAccess); |
329
|
|
|
} |
330
|
102 |
|
$method->addChild($return); |
331
|
|
|
|
332
|
102 |
|
return $this; |
333
|
|
|
} |
334
|
|
|
|
335
|
102 |
|
protected function addStructMethodGet(StructAttributeModel $attribute): self |
336
|
|
|
{ |
337
|
|
|
switch (true) { |
338
|
|
|
// it can either be a string, a DOMDocument or null... |
339
|
102 |
|
case $attribute->isXml(): |
340
|
4 |
|
$returnType = ''; |
341
|
|
|
|
342
|
4 |
|
break; |
343
|
|
|
|
344
|
|
|
default: |
345
|
102 |
|
$returnType = (!$attribute->getRemovableFromRequest() && $attribute->isRequired() ? '' : '?').$this->getStructAttributeTypeAsPhpType($attribute); |
346
|
|
|
|
347
|
102 |
|
break; |
348
|
|
|
} |
349
|
|
|
|
350
|
102 |
|
$method = new PhpMethod( |
351
|
102 |
|
$attribute->getGetterName(), |
352
|
102 |
|
$this->getStructMethodGetParameters($attribute), |
353
|
|
|
$returnType |
354
|
|
|
); |
355
|
102 |
|
if ($attribute->nameIsClean()) { |
356
|
102 |
|
$thisAccess = sprintf('%s', $attribute->getName()); |
357
|
|
|
} else { |
358
|
2 |
|
$thisAccess = sprintf('{\'%s\'}', addslashes($attribute->getName())); |
359
|
|
|
} |
360
|
102 |
|
$this->addStructMethodGetBody($method, $attribute, $thisAccess); |
361
|
102 |
|
$this->methods->add($method); |
362
|
|
|
|
363
|
102 |
|
return $this; |
364
|
|
|
} |
365
|
|
|
|
366
|
102 |
|
protected function getStructMethodGetParameters(StructAttributeModel $attribute): array |
367
|
|
|
{ |
368
|
102 |
|
$parameters = []; |
369
|
102 |
|
if ($attribute->isXml()) { |
370
|
4 |
|
$parameters[] = new PhpFunctionParameter('asDomDocument', false, self::TYPE_BOOL, $attribute); |
371
|
|
|
} |
372
|
|
|
|
373
|
102 |
|
return $parameters; |
374
|
|
|
} |
375
|
|
|
|
376
|
102 |
|
protected function getMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock |
377
|
|
|
{ |
378
|
102 |
|
return $this->getStructMethodAnnotationBlock($method); |
379
|
|
|
} |
380
|
|
|
|
381
|
102 |
|
protected function getStructMethodAnnotationBlock(PhpMethod $method): ?PhpAnnotationBlock |
382
|
|
|
{ |
383
|
102 |
|
$annotationBlock = null; |
384
|
|
|
|
385
|
102 |
|
switch ($method->getName()) { |
386
|
102 |
|
case self::METHOD_CONSTRUCT: |
387
|
102 |
|
$annotationBlock = $this->getStructMethodConstructAnnotationBlock(); |
388
|
|
|
|
389
|
102 |
|
break; |
390
|
|
|
|
391
|
102 |
|
case 0 === mb_strpos($method->getName(), 'get'): |
392
|
102 |
|
case 0 === mb_strpos($method->getName(), 'set'): |
393
|
102 |
|
$annotationBlock = $this->getStructMethodsSetAndGetAnnotationBlock($method); |
394
|
|
|
|
395
|
102 |
|
break; |
396
|
|
|
|
397
|
66 |
|
case 0 === mb_strpos($method->getName(), 'addTo'): |
398
|
38 |
|
$annotationBlock = $this->getStructMethodsAddToAnnotationBlock($method); |
399
|
|
|
|
400
|
38 |
|
break; |
401
|
|
|
|
402
|
66 |
|
case false !== mb_strpos($method->getName(), 'ForUnionConstraintsFrom'): |
403
|
4 |
|
$annotationBlock = $this->getStructMethodsValidateUnionAnnotationBlock($method); |
404
|
|
|
|
405
|
4 |
|
break; |
406
|
|
|
|
407
|
62 |
|
case false !== mb_strpos($method->getName(), 'ForArrayConstraintsFrom'): |
408
|
58 |
|
$annotationBlock = $this->getStructMethodsValidateArrayAnnotationBlock($method); |
409
|
|
|
|
410
|
58 |
|
break; |
411
|
|
|
|
412
|
12 |
|
case false !== mb_strpos($method->getName(), 'ForChoiceConstraintsFrom'): |
413
|
8 |
|
$annotationBlock = $this->getStructMethodsValidateChoiceAnnotationBlock($method); |
414
|
|
|
|
415
|
8 |
|
break; |
416
|
|
|
|
417
|
4 |
|
case false !== mb_strpos($method->getName(), 'MaxLengthConstraintFrom'): |
418
|
4 |
|
$annotationBlock = $this->getStructMethodsValidateLengthAnnotationBlock($method, 'max'); |
419
|
|
|
|
420
|
4 |
|
break; |
421
|
|
|
|
422
|
4 |
|
case false !== mb_strpos($method->getName(), 'MinLengthConstraintFrom'): |
423
|
4 |
|
$annotationBlock = $this->getStructMethodsValidateLengthAnnotationBlock($method, 'min'); |
424
|
|
|
|
425
|
4 |
|
break; |
426
|
|
|
|
427
|
|
|
case false !== mb_strpos($method->getName(), 'LengthConstraintFrom'): |
428
|
|
|
$annotationBlock = $this->getStructMethodsValidateLengthAnnotationBlock($method); |
429
|
|
|
|
430
|
|
|
break; |
431
|
|
|
} |
432
|
|
|
|
433
|
102 |
|
return $annotationBlock; |
434
|
|
|
} |
435
|
|
|
|
436
|
102 |
|
protected function getStructMethodConstructAnnotationBlock(): PhpAnnotationBlock |
437
|
|
|
{ |
438
|
102 |
|
$annotationBlock = new PhpAnnotationBlock([ |
439
|
102 |
|
sprintf('Constructor method for %s', $this->getModel()->getName()), |
440
|
|
|
]); |
441
|
102 |
|
$this->addStructPropertiesToAnnotationBlock($annotationBlock); |
442
|
|
|
|
443
|
102 |
|
return $annotationBlock; |
444
|
|
|
} |
445
|
|
|
|
446
|
102 |
|
protected function getStructMethodsSetAndGetAnnotationBlock(PhpMethod $method): PhpAnnotationBlock |
447
|
|
|
{ |
448
|
102 |
|
$parameters = $method->getParameters(); |
449
|
102 |
|
$setOrGet = mb_strtolower(mb_substr($method->getName(), 0, 3)); |
450
|
102 |
|
$parameter = array_shift($parameters); |
451
|
|
|
// Only set parameter must be based on a potential PhpFunctionParameter |
452
|
102 |
|
if ($parameter instanceof PhpFunctionParameter && 'set' === $setOrGet) { |
453
|
102 |
|
$parameterName = ucfirst($parameter->getName()); |
454
|
|
|
} else { |
455
|
102 |
|
$parameterName = mb_substr($method->getName(), 3); |
456
|
|
|
} |
457
|
|
|
/** |
458
|
|
|
* Since properties can be duplicated with different case, we assume that _\d+ is replaceable by an empty string as methods are "duplicated" with this suffix. |
459
|
|
|
*/ |
460
|
102 |
|
$parameterName = preg_replace('/(_\d+)/', '', $parameterName); |
461
|
102 |
|
$attribute = $this->getModel()->getAttribute($parameterName); |
462
|
102 |
|
if (!$attribute instanceof StructAttributeModel) { |
463
|
42 |
|
$attribute = $this->getModel()->getAttributeByCleanName($parameterName); |
464
|
|
|
} |
465
|
102 |
|
if (!$attribute instanceof StructAttributeModel) { |
466
|
42 |
|
$parameterName = lcfirst($parameterName); |
467
|
42 |
|
$attribute = $this->getModel()->getAttribute($parameterName); |
468
|
42 |
|
if (!$attribute instanceof StructAttributeModel) { |
469
|
4 |
|
$attribute = $this->getModel()->getAttributeByCleanName($parameterName); |
470
|
|
|
} |
471
|
|
|
} |
472
|
102 |
|
$setValueAnnotation = '%s %s value'; |
473
|
102 |
|
$annotationBlock = new PhpAnnotationBlock(); |
474
|
102 |
|
if ($attribute instanceof StructAttributeModel) { |
475
|
102 |
|
$annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), $parameterName)); |
476
|
102 |
|
$this->addStructMethodsSetAndGetAnnotationBlockFromStructAttribute($setOrGet, $annotationBlock, $attribute); |
477
|
2 |
|
} elseif (!$attribute) { |
|
|
|
|
478
|
2 |
|
$annotationBlock->addChild(sprintf($setValueAnnotation, ucfirst($setOrGet), lcfirst($parameterName))); |
479
|
2 |
|
$this->addStructMethodsSetAndGetAnnotationBlockFromScalar($setOrGet, $annotationBlock, $parameterName); |
480
|
|
|
} |
481
|
|
|
|
482
|
102 |
|
return $annotationBlock; |
483
|
|
|
} |
484
|
|
|
|
485
|
102 |
|
protected function addStructMethodsSetAndGetAnnotationBlockFromStructAttribute(string $setOrGet, PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self |
486
|
|
|
{ |
487
|
102 |
|
switch ($setOrGet) { |
488
|
102 |
|
case 'set': |
489
|
102 |
|
if ($attribute->getRemovableFromRequest()) { |
490
|
10 |
|
$annotationBlock->addChild('This property is removable from request (nillable=true+minOccurs=0), therefore if the value assigned to this property is null, it is removed from this object'); |
491
|
|
|
} |
492
|
102 |
|
if ($attribute->isAChoice()) { |
493
|
8 |
|
$annotationBlock->addChild('This property belongs to a choice that allows only one property to exist. It is therefore removable from the request, consequently if the value assigned to this property is null, the property is removed from this object'); |
494
|
|
|
} |
495
|
102 |
|
if ($attribute->isXml()) { |
496
|
|
|
$annotationBlock |
497
|
4 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::hasChildNodes()')) |
498
|
4 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::saveXML()')) |
499
|
4 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMNode::item()')) |
500
|
|
|
; |
501
|
|
|
} |
502
|
102 |
|
if ($this->getGenerator()->getOptionValidation()) { |
503
|
100 |
|
if ($attribute->isAChoice()) { |
504
|
8 |
|
$annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class)); |
505
|
|
|
} |
506
|
100 |
|
if (($model = $this->getRestrictionFromStructAttribute($attribute)) instanceof StructModel) { |
507
|
|
|
$annotationBlock |
508
|
48 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID))) |
509
|
48 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES))) |
510
|
48 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class)) |
511
|
|
|
; |
512
|
98 |
|
} elseif ($attribute->isArray()) { |
513
|
52 |
|
$annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class)); |
514
|
|
|
} |
515
|
|
|
} |
516
|
102 |
|
$this->addStructMethodsSetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeSetAnnotation($attribute, false), lcfirst($attribute->getCleanName())); |
517
|
|
|
|
518
|
102 |
|
break; |
519
|
|
|
|
520
|
102 |
|
case 'get': |
521
|
102 |
|
if ($attribute->getRemovableFromRequest()) { |
522
|
10 |
|
$annotationBlock->addChild('An additional test has been added (isset) before returning the property value as this property may have been unset before, due to the fact that this property is removable from the request (nillable=true+minOccurs=0)'); |
523
|
|
|
} |
524
|
|
|
$this |
525
|
102 |
|
->addStructMethodsGetAnnotationBlockFromXmlAttribute($annotationBlock, $attribute) |
526
|
102 |
|
->addStructMethodsGetAnnotationBlock($annotationBlock, $this->getStructAttributeTypeGetAnnotation($attribute)) |
527
|
|
|
; |
528
|
|
|
|
529
|
102 |
|
break; |
530
|
|
|
} |
531
|
|
|
|
532
|
102 |
|
return $this; |
533
|
|
|
} |
534
|
|
|
|
535
|
2 |
|
protected function addStructMethodsSetAndGetAnnotationBlockFromScalar(string $setOrGet, PhpAnnotationBlock $annotationBlock, string $attributeName): self |
536
|
|
|
{ |
537
|
2 |
|
switch ($setOrGet) { |
538
|
2 |
|
case 'set': |
539
|
2 |
|
$this->addStructMethodsSetAnnotationBlock($annotationBlock, lcfirst($attributeName), lcfirst($attributeName)); |
540
|
|
|
|
541
|
2 |
|
break; |
542
|
|
|
|
543
|
2 |
|
case 'get': |
544
|
2 |
|
$this->addStructMethodsGetAnnotationBlock($annotationBlock, lcfirst($attributeName)); |
545
|
|
|
|
546
|
2 |
|
break; |
547
|
|
|
} |
548
|
|
|
|
549
|
2 |
|
return $this; |
550
|
|
|
} |
551
|
|
|
|
552
|
102 |
|
protected function addStructMethodsSetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $type, string $name): self |
553
|
|
|
{ |
554
|
|
|
$annotationBlock |
555
|
102 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $type, $name))) |
556
|
102 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true))) |
557
|
|
|
; |
558
|
|
|
|
559
|
102 |
|
return $this; |
560
|
|
|
} |
561
|
|
|
|
562
|
102 |
|
protected function addStructMethodsGetAnnotationBlock(PhpAnnotationBlock $annotationBlock, string $attributeType): self |
563
|
|
|
{ |
564
|
102 |
|
$annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $attributeType)); |
565
|
|
|
|
566
|
102 |
|
return $this; |
567
|
|
|
} |
568
|
|
|
|
569
|
102 |
|
protected function addStructMethodsGetAnnotationBlockFromXmlAttribute(PhpAnnotationBlock $annotationBlock, StructAttributeModel $attribute): self |
570
|
|
|
{ |
571
|
102 |
|
if ($attribute->isXml()) { |
572
|
|
|
$annotationBlock |
573
|
4 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, '\DOMDocument::loadXML()')) |
574
|
4 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, 'bool $asDomDocument true: returns \DOMDocument, false: returns XML string')) |
575
|
|
|
; |
576
|
|
|
} |
577
|
|
|
|
578
|
102 |
|
return $this; |
579
|
|
|
} |
580
|
|
|
|
581
|
102 |
|
protected function addStructPropertiesToAnnotationBlock(PhpAnnotationBlock $annotationBlock): self |
582
|
|
|
{ |
583
|
|
|
return $this |
584
|
102 |
|
->addStructPropertiesToAnnotationBlockUses($annotationBlock) |
585
|
102 |
|
->addStructPropertiesToAnnotationBlockParams($annotationBlock) |
586
|
|
|
; |
587
|
|
|
} |
588
|
|
|
|
589
|
102 |
|
protected function addStructPropertiesToAnnotationBlockUses(PhpAnnotationBlock $annotationBlock): self |
590
|
|
|
{ |
591
|
102 |
|
foreach ($this->getModelAttributes() as $attribute) { |
592
|
102 |
|
$annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $this->getModel()->getPackagedName(), $attribute->getSetterName()))); |
593
|
|
|
} |
594
|
|
|
|
595
|
102 |
|
return $this; |
596
|
|
|
} |
597
|
|
|
|
598
|
102 |
|
protected function addStructPropertiesToAnnotationBlockParams(PhpAnnotationBlock $annotationBlock): self |
599
|
|
|
{ |
600
|
102 |
|
foreach ($this->getModelAttributes() as $attribute) { |
601
|
102 |
|
$annotationBlock->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $%s', $this->getStructAttributeTypeSetAnnotation($attribute, false), lcfirst($attribute->getCleanName())))); |
602
|
|
|
} |
603
|
|
|
|
604
|
102 |
|
return $this; |
605
|
|
|
} |
606
|
|
|
|
607
|
38 |
|
protected function getStructMethodsAddToAnnotationBlock(PhpMethod $method): PhpAnnotationBlock |
608
|
|
|
{ |
609
|
38 |
|
$methodParameters = $method->getParameters(); |
610
|
|
|
/** @var PhpFunctionParameter $firstParameter */ |
611
|
38 |
|
$firstParameter = array_shift($methodParameters); |
612
|
38 |
|
$attribute = $this->getModel()->getAttribute($firstParameter->getModel()->getName()); |
613
|
38 |
|
$annotationBlock = new PhpAnnotationBlock(); |
614
|
38 |
|
if ($attribute instanceof StructAttributeModel) { |
615
|
38 |
|
$model = $this->getRestrictionFromStructAttribute($attribute); |
616
|
38 |
|
$annotationBlock->addChild(sprintf('Add item to %s value', $attribute->getCleanName())); |
617
|
38 |
|
if ($model instanceof StructModel) { |
618
|
|
|
$annotationBlock |
619
|
2 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_VALUE_IS_VALID))) |
620
|
2 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_USES, sprintf('%s::%s()', $model->getPackagedName(true), StructEnum::METHOD_GET_VALID_VALUES))) |
621
|
|
|
; |
622
|
|
|
} |
623
|
|
|
$annotationBlock |
624
|
38 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_THROWS, InvalidArgumentException::class)) |
625
|
38 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_PARAM, sprintf('%s $item', $this->getStructAttributeTypeSetAnnotation($attribute, false, true)))) |
626
|
38 |
|
->addChild(new PhpAnnotation(self::ANNOTATION_RETURN, $this->getModel()->getPackagedName(true))) |
627
|
|
|
; |
628
|
|
|
} |
629
|
|
|
|
630
|
38 |
|
return $annotationBlock; |
631
|
|
|
} |
632
|
|
|
|
633
|
58 |
|
protected function getStructMethodsValidateArrayAnnotationBlock(PhpMethod $method): PhpAnnotationBlock |
634
|
|
|
{ |
635
|
58 |
|
$methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), 'ForArrayConstraintsFrom') + mb_strlen('ForArrayConstraintsFrom'))); |
636
|
|
|
|
637
|
58 |
|
return new PhpAnnotationBlock([ |
638
|
58 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the values passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
639
|
58 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
640
|
58 |
|
new PhpAnnotation(self::ANNOTATION_PARAM, 'array $values'), |
641
|
58 |
|
new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'), |
642
|
|
|
]); |
643
|
|
|
} |
644
|
|
|
|
645
|
4 |
|
protected function getStructMethodsValidateUnionAnnotationBlock(PhpMethod $method): PhpAnnotationBlock |
646
|
|
|
{ |
647
|
4 |
|
$methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), 'ForUnionConstraintsFrom') + mb_strlen('ForUnionConstraintsFrom'))); |
648
|
|
|
|
649
|
4 |
|
return new PhpAnnotationBlock([ |
650
|
4 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the value passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
651
|
4 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
652
|
4 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This is a set of validation rules based on the union types associated to the property being set by the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
653
|
4 |
|
new PhpAnnotation(self::ANNOTATION_PARAM, 'mixed $value'), |
654
|
4 |
|
new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'), |
655
|
|
|
]); |
656
|
|
|
} |
657
|
|
|
|
658
|
8 |
|
protected function getStructMethodsValidateChoiceAnnotationBlock(PhpMethod $method): PhpAnnotationBlock |
659
|
|
|
{ |
660
|
8 |
|
$methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), 'ForChoiceConstraintsFrom') + mb_strlen('ForChoiceConstraintsFrom'))); |
661
|
|
|
|
662
|
8 |
|
return new PhpAnnotationBlock([ |
663
|
8 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the value passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
664
|
8 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
665
|
8 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, 'This has to validate that the property which is being set is the only one among the given choices', self::ANNOTATION_LONG_LENGTH), |
666
|
8 |
|
new PhpAnnotation(self::ANNOTATION_PARAM, 'mixed $value'), |
667
|
8 |
|
new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'), |
668
|
|
|
]); |
669
|
|
|
} |
670
|
|
|
|
671
|
4 |
|
protected function getStructMethodsValidateLengthAnnotationBlock(PhpMethod $method, string $type = ''): PhpAnnotationBlock |
672
|
|
|
{ |
673
|
4 |
|
$replace = sprintf('%sLengthConstraintFrom', ucfirst($type)); |
674
|
4 |
|
$methodName = lcfirst(mb_substr($method->getName(), mb_strpos($method->getName(), $replace) + mb_strlen($replace))); |
675
|
|
|
|
676
|
4 |
|
return new PhpAnnotationBlock([ |
677
|
4 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is responsible for validating the value passed to the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
678
|
4 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, sprintf('This method is willingly generated in order to preserve the one-line inline validation within the %s method', $methodName), self::ANNOTATION_LONG_LENGTH), |
679
|
4 |
|
new PhpAnnotation(PhpAnnotation::NO_NAME, 'This has to validate that the items contained by the array match the length constraint', self::ANNOTATION_LONG_LENGTH), |
680
|
4 |
|
new PhpAnnotation(self::ANNOTATION_PARAM, 'mixed $values'), |
681
|
4 |
|
new PhpAnnotation(self::ANNOTATION_RETURN, 'string A non-empty message if the values does not match the validation rules'), |
682
|
|
|
]); |
683
|
|
|
} |
684
|
|
|
|
685
|
100 |
|
protected function applyRules(PhpMethod $method, StructAttributeModel $attribute, string $parameterName, bool $itemType = false): void |
686
|
|
|
{ |
687
|
100 |
|
if ($this->getGenerator()->getOptionValidation()) { |
688
|
100 |
|
$rules = new Rules($this, $method, $attribute, $this->methods); |
689
|
100 |
|
$rules->applyRules($parameterName, $itemType); |
690
|
|
|
} |
691
|
|
|
} |
692
|
|
|
} |
693
|
|
|
|