From a6eededeaebadcea58daea72a5d5652dcba50ee8 Mon Sep 17 00:00:00 2001 From: soyuka Date: Tue, 19 Dec 2023 09:35:44 +0100 Subject: [PATCH] fix(jsonschema): keep format subschema generation fixes #5950 --- src/Hal/JsonSchema/SchemaFactory.php | 4 ++++ src/Hydra/JsonSchema/SchemaFactory.php | 4 ++++ src/JsonSchema/SchemaFactory.php | 11 +++++++++-- .../SchemaFactoryAwareInterface.php | 19 +++++++++++++++++++ .../Command/JsonSchemaGenerateCommandTest.php | 12 ++++++++++++ 5 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 src/JsonSchema/SchemaFactoryAwareInterface.php diff --git a/src/Hal/JsonSchema/SchemaFactory.php b/src/Hal/JsonSchema/SchemaFactory.php index 295b444c13c..fdb0f67b0aa 100644 --- a/src/Hal/JsonSchema/SchemaFactory.php +++ b/src/Hal/JsonSchema/SchemaFactory.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Hal\JsonSchema; use ApiPlatform\JsonSchema\Schema; +use ApiPlatform\JsonSchema\SchemaFactoryAwareInterface; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation; @@ -46,6 +47,9 @@ final class SchemaFactory implements SchemaFactoryInterface public function __construct(private readonly SchemaFactoryInterface $schemaFactory) { $this->addDistinctFormat('jsonhal'); + if ($this->schemaFactory instanceof SchemaFactoryAwareInterface) { + $this->schemaFactory->setSchemaFactory($this); + } } /** diff --git a/src/Hydra/JsonSchema/SchemaFactory.php b/src/Hydra/JsonSchema/SchemaFactory.php index 540834d92f5..cecb0391ee6 100644 --- a/src/Hydra/JsonSchema/SchemaFactory.php +++ b/src/Hydra/JsonSchema/SchemaFactory.php @@ -16,6 +16,7 @@ use ApiPlatform\JsonLd\ContextBuilder; use ApiPlatform\JsonSchema\Schema; use ApiPlatform\JsonSchema\SchemaFactory as BaseSchemaFactory; +use ApiPlatform\JsonSchema\SchemaFactoryAwareInterface; use ApiPlatform\JsonSchema\SchemaFactoryInterface; use ApiPlatform\Metadata\Operation; @@ -60,6 +61,9 @@ final class SchemaFactory implements SchemaFactoryInterface public function __construct(private readonly SchemaFactoryInterface $schemaFactory) { $this->addDistinctFormat('jsonld'); + if ($this->schemaFactory instanceof SchemaFactoryAwareInterface) { + $this->schemaFactory->setSchemaFactory($this); + } } /** diff --git a/src/JsonSchema/SchemaFactory.php b/src/JsonSchema/SchemaFactory.php index 6d366ab63f4..42af8dd413d 100644 --- a/src/JsonSchema/SchemaFactory.php +++ b/src/JsonSchema/SchemaFactory.php @@ -33,11 +33,12 @@ * * @author Kévin Dunglas */ -final class SchemaFactory implements SchemaFactoryInterface +final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareInterface { use ResourceClassInfoTrait; private array $distinctFormats = []; private ?TypeFactoryInterface $typeFactory = null; + private ?SchemaFactoryInterface $schemaFactory = null; // Edge case where the related resource is not readable (for example: NotExposed) but we have groups to read the whole related object public const FORCE_SUBSCHEMA = '_api_subschema_force_readable_link'; public const OPENAPI_DEFINITION_NAME = 'openapi_definition_name'; @@ -217,7 +218,8 @@ private function buildPropertySchema(Schema $schema, string $definitionName, str continue; } - $subSchema = $this->buildSchema($className, $format, $parentType, null, $subSchema, $serializerContext + [self::FORCE_SUBSCHEMA => true], false); + $subSchemaFactory = $this->schemaFactory ?: $this; + $subSchema = $subSchemaFactory->buildSchema($className, $format, $parentType, null, $subSchema, $serializerContext + [self::FORCE_SUBSCHEMA => true], false); if (!isset($subSchema['$ref'])) { continue; } @@ -399,4 +401,9 @@ private function getShortClassName(string $fullyQualifiedName): string return end($parts); } + + public function setSchemaFactory(SchemaFactoryInterface $schemaFactory): void + { + $this->schemaFactory = $schemaFactory; + } } diff --git a/src/JsonSchema/SchemaFactoryAwareInterface.php b/src/JsonSchema/SchemaFactoryAwareInterface.php new file mode 100644 index 00000000000..fd9338e4db1 --- /dev/null +++ b/src/JsonSchema/SchemaFactoryAwareInterface.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\JsonSchema; + +interface SchemaFactoryAwareInterface +{ + public function setSchemaFactory(SchemaFactoryInterface $schemaFactory): void; +} diff --git a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php index 27632d900cf..27475fe839e 100644 --- a/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php +++ b/tests/JsonSchema/Command/JsonSchemaGenerateCommandTest.php @@ -150,4 +150,16 @@ public function testWritableNonResourceRef(): void $this->assertEquals($json['definitions']['SaveProduct.jsonld']['properties']['codes']['items']['$ref'], '#/definitions/ProductCode.jsonld'); } + + /** + * Test related Schema keeps json-ld context. + */ + public function testSubSchemaJsonLd(): void + { + $this->tester->run(['command' => 'api:json-schema:generate', 'resource' => 'ApiPlatform\Tests\Fixtures\TestBundle\Entity\RelatedDummy', '--type' => 'output', '--format' => 'jsonld']); + $result = $this->tester->getDisplay(); + $json = json_decode($result, associative: true); + + $this->assertArrayHasKey('@id', $json['definitions']['ThirdLevel.jsonld-friends']['properties']); + } }