Skip to content

Commit 15a2530

Browse files
committed
patch null inheritance in compositions (fixes #50)
1 parent f5978d9 commit 15a2530

File tree

5 files changed

+83
-10
lines changed

5 files changed

+83
-10
lines changed

src/PropertyProcessor/ComposedValue/AbstractComposedValueProcessor.php

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHPModelGenerator\Model\Validator\RequiredPropertyValidator;
1717
use PHPModelGenerator\PropertyProcessor\Decorator\Property\ObjectInstantiationDecorator;
1818
use PHPModelGenerator\PropertyProcessor\Decorator\SchemaNamespaceTransferDecorator;
19+
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHint\ClearTypeHintDecorator;
1920
use PHPModelGenerator\PropertyProcessor\Decorator\TypeHint\CompositionTypeHintDecorator;
2021
use PHPModelGenerator\PropertyProcessor\Property\AbstractValueProcessor;
2122
use PHPModelGenerator\PropertyProcessor\PropertyMetaDataCollection;
@@ -120,6 +121,10 @@ protected function getCompositionProperties(PropertyInterface $property, JsonSch
120121
$compositionProperties = [];
121122
$json = $propertySchema->getJson()['propertySchema']->getJson();
122123

124+
// clear the base type of the property to keep only the types of the composition.
125+
// This avoids e.g. "array|int[]" for a property which is known to contain always an integer array
126+
$property->addTypeHintDecorator(new ClearTypeHintDecorator());
127+
123128
foreach ($json[$propertySchema->getJson()['type']] as $compositionElement) {
124129
$compositionSchema = $propertySchema->getJson()['propertySchema']->withJson($compositionElement);
125130

@@ -165,19 +170,24 @@ private function transferPropertyType(PropertyInterface $property, array $compos
165170
{
166171
$compositionPropertyTypes = array_values(
167172
array_unique(
168-
array_filter(
169-
array_map(
170-
function (CompositionPropertyDecorator $property): string {
171-
return $property->getType() ? $property->getType()->getName() : '';
172-
},
173-
$compositionProperties
174-
)
173+
array_map(
174+
function (CompositionPropertyDecorator $property): string {
175+
return $property->getType() ? $property->getType()->getName() : '';
176+
},
177+
$compositionProperties
175178
)
176179
)
177180
);
178181

179-
if (count($compositionPropertyTypes) === 1 && !($this instanceof NotProcessor)) {
180-
$property->setType(new PropertyType($compositionPropertyTypes[0]));
182+
$nonEmptyCompositionPropertyTypes = array_values(array_filter($compositionPropertyTypes));
183+
184+
if (count($nonEmptyCompositionPropertyTypes) === 1 && !($this instanceof NotProcessor)) {
185+
$property->setType(
186+
new PropertyType(
187+
$nonEmptyCompositionPropertyTypes[0],
188+
count($compositionPropertyTypes) > 1 ? true : null
189+
)
190+
);
181191
}
182192
}
183193

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
declare(strict_types = 1);
4+
5+
namespace PHPModelGenerator\PropertyProcessor\Decorator\TypeHint;
6+
7+
/**
8+
* Class ClearTypeHintDecorator
9+
*
10+
* @package PHPModelGenerator\PropertyProcessor\Decorator\Property
11+
*/
12+
class ClearTypeHintDecorator implements TypeHintDecoratorInterface
13+
{
14+
/**
15+
* @inheritdoc
16+
*/
17+
public function decorate(string $input, bool $outputType = false): string
18+
{
19+
return '';
20+
}
21+
}

src/PropertyProcessor/Property/MultiTypeProcessor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public function process(string $propertyName, JsonSchema $propertySchema): Prope
9090
$property->addTypeHintDecorator(
9191
new TypeHintDecorator(
9292
array_map(
93-
function (PropertyInterface $subProperty): string {#
93+
function (PropertyInterface $subProperty): string {
9494
return $subProperty->getTypeHint();
9595
},
9696
$subProperties

tests/ComposedValue/ComposedOneOfTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,4 +639,28 @@ public function validationInSetterDataProvider(): array
639639
],
640640
];
641641
}
642+
643+
public function testTypesForComposedPropertyWithNullBranch(): void
644+
{
645+
$className = $this->generateClassFromFile(
646+
'OneOfNullBranch.json',
647+
(new GeneratorConfiguration())->setImmutable(false)
648+
);
649+
650+
$object = new $className([]);
651+
652+
$this->assertSame('int[]|null', $this->getPropertyTypeAnnotation($object, 'property'));
653+
654+
$this->assertSame('int[]|null', $this->getMethodReturnTypeAnnotation($object, 'getProperty'));
655+
$returnType = $this->getReturnType($object, 'getProperty');
656+
$this->assertSame('array', $returnType->getName());
657+
// as implicit null is enabled the default value may be overwritten by a null value
658+
$this->assertTrue($returnType->allowsNull());
659+
660+
$this->assertSame('int[]|null', $this->getMethodParameterTypeAnnotation($object, 'setProperty'));
661+
$parameterType = $this->getParameterType($object, 'setProperty');
662+
$this->assertSame('array', $parameterType->getName());
663+
// as implicit null is enabled the default value may be overwritten by a null value
664+
$this->assertTrue($parameterType->allowsNull());
665+
}
642666
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"type": "object",
3+
"properties": {
4+
"property": {
5+
"oneOf": [
6+
{
7+
"type": "array",
8+
"items": {
9+
"type": "integer"
10+
}
11+
},
12+
{
13+
"type": "null"
14+
}
15+
]
16+
}
17+
}
18+
}

0 commit comments

Comments
 (0)