Skip to content

Commit 334fa25

Browse files
authored
fix: ensure OpenAPI-specific implementation for nullable types does not influence the other ones (#4725)
1 parent 39b4e43 commit 334fa25

File tree

2 files changed

+54
-17
lines changed

2 files changed

+54
-17
lines changed

src/JsonSchema/TypeFactory.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,16 @@ private function addNullabilityToTypeDefinition(array $jsonSchema, Type $type, ?
169169
}
170170

171171
if (\array_key_exists('$ref', $jsonSchema)) {
172-
return [
173-
'nullable' => true,
174-
'anyOf' => [$jsonSchema],
175-
];
172+
$typeDefinition = ['anyOf' => [$jsonSchema]];
173+
174+
if ($schema && Schema::VERSION_JSON_SCHEMA === $schema->getVersion()) {
175+
$typeDefinition['anyOf'][] = ['type' => 'null'];
176+
} else {
177+
// OpenAPI < 3.1
178+
$typeDefinition['nullable'] = true;
179+
}
180+
181+
return $typeDefinition;
176182
}
177183

178184
if ($schema && Schema::VERSION_JSON_SCHEMA === $schema->getVersion()) {

tests/JsonSchema/TypeFactoryTest.php

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -387,29 +387,60 @@ public function testGetClassType(): void
387387
$this->assertSame(['$ref' => 'ref'], $typeFactory->getType(new Type(Type::BUILTIN_TYPE_OBJECT, false, Dummy::class), 'jsonld', true, ['foo' => 'bar'], new Schema()));
388388
}
389389

390-
public function testGetClassTypeWithNullability(): void
390+
/** @dataProvider classTypeWithNullabilityDataProvider */
391+
public function testGetClassTypeWithNullability(array $expected, SchemaFactoryInterface $schemaFactory, Schema $schema): void
392+
{
393+
$typeFactory = new TypeFactory();
394+
$typeFactory->setSchemaFactory($schemaFactory);
395+
396+
self::assertSame(
397+
$expected,
398+
$typeFactory->getType(new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class), 'jsonld', true, ['foo' => 'bar'], $schema)
399+
);
400+
}
401+
402+
public function classTypeWithNullabilityDataProvider(): iterable
403+
{
404+
$schemaFactory = $this->createSchemaFactoryMock($schema = new Schema());
405+
406+
yield 'JSON-Schema version' => [
407+
[
408+
'anyOf' => [
409+
['$ref' => 'the-ref-name'],
410+
['type' => 'null'],
411+
],
412+
],
413+
$schemaFactory,
414+
$schema,
415+
];
416+
417+
$schemaFactory = $this->createSchemaFactoryMock($schema = new Schema(Schema::VERSION_OPENAPI));
418+
419+
yield 'OpenAPI < 3.1 version' => [
420+
[
421+
'anyOf' => [
422+
['$ref' => 'the-ref-name'],
423+
],
424+
'nullable' => true,
425+
],
426+
$schemaFactory,
427+
$schema,
428+
];
429+
}
430+
431+
private function createSchemaFactoryMock(Schema $schema): SchemaFactoryInterface
391432
{
392433
$schemaFactory = $this->createMock(SchemaFactoryInterface::class);
393434

394435
$schemaFactory
395436
->method('buildSchema')
396-
->willReturnCallback(static function (): Schema {
397-
$schema = new Schema();
398-
437+
->willReturnCallback(static function () use ($schema): Schema {
399438
$schema['$ref'] = 'the-ref-name';
400439
$schema['description'] = 'more stuff here';
401440

402441
return $schema;
403442
});
404443

405-
$typeFactory = new TypeFactory();
406-
$typeFactory->setSchemaFactory($schemaFactory);
407-
408-
self::assertSame([
409-
'nullable' => true,
410-
'anyOf' => [
411-
['$ref' => 'the-ref-name'],
412-
],
413-
], $typeFactory->getType(new Type(Type::BUILTIN_TYPE_OBJECT, true, Dummy::class), 'jsonld', true, ['foo' => 'bar'], new Schema()));
444+
return $schemaFactory;
414445
}
415446
}

0 commit comments

Comments
 (0)