From 42b0c4f108a5a933aabc8378fa9440bca1f865ae Mon Sep 17 00:00:00 2001 From: Nick Date: Fri, 24 Nov 2023 11:08:39 +0100 Subject: [PATCH] fix embedded root schema (#63) * fix embedded root schema * small fix --- .../{embedded => }/Collection.avsc | 1 + src/Merger/SchemaMerger.php | 11 +- .../Registry/SchemaRegistryTest.php | 2 +- tests/Unit/Merger/SchemaMergerTest.php | 106 +++++++++++++++++- 4 files changed, 114 insertions(+), 6 deletions(-) rename example/schemaTemplates/{embedded => }/Collection.avsc (90%) diff --git a/example/schemaTemplates/embedded/Collection.avsc b/example/schemaTemplates/Collection.avsc similarity index 90% rename from example/schemaTemplates/embedded/Collection.avsc rename to example/schemaTemplates/Collection.avsc index 9a47df6..7d3b854 100644 --- a/example/schemaTemplates/embedded/Collection.avsc +++ b/example/schemaTemplates/Collection.avsc @@ -1,6 +1,7 @@ { "type": "record", "namespace": "com.example", + "schema_level": "root", "name": "Collection", "fields": [ { "name": "name", "type": "string" }, diff --git a/src/Merger/SchemaMerger.php b/src/Merger/SchemaMerger.php index 113f681..9f23292 100644 --- a/src/Merger/SchemaMerger.php +++ b/src/Merger/SchemaMerger.php @@ -102,8 +102,17 @@ private function replaceSchemaIdWithDefinition( ): string { $idString = '"' . $schemaId . '"'; $pos = (int) strpos($rootDefinition, $idString); + $embeddedDefinitionWithoutLevel = $this->removeSchemaLevel($embeddedDefinition); - return substr_replace($rootDefinition, $embeddedDefinition, $pos, strlen($idString)); + return substr_replace($rootDefinition, $embeddedDefinitionWithoutLevel, $pos, strlen($idString)); + } + + private function removeSchemaLevel(string $embeddedDefinition): string + { + $arraySchema = json_decode($embeddedDefinition, true); + unset($arraySchema['schema_level']); + + return json_encode($arraySchema, JSON_THROW_ON_ERROR | JSON_PRESERVE_ZERO_FRACTION); } /** diff --git a/tests/Integration/Registry/SchemaRegistryTest.php b/tests/Integration/Registry/SchemaRegistryTest.php index 87a0e00..a8c5586 100644 --- a/tests/Integration/Registry/SchemaRegistryTest.php +++ b/tests/Integration/Registry/SchemaRegistryTest.php @@ -59,7 +59,7 @@ public function testGetRootSchemas() $rootSchemas = $registry->getRootSchemas(); - self::assertCount(2, $rootSchemas); + self::assertCount(3, $rootSchemas); foreach ($rootSchemas as $rootSchema) { self::assertInstanceOf(SchemaTemplateInterface::class, $rootSchema); diff --git a/tests/Unit/Merger/SchemaMergerTest.php b/tests/Unit/Merger/SchemaMergerTest.php index aede98d..a373e7d 100644 --- a/tests/Unit/Merger/SchemaMergerTest.php +++ b/tests/Unit/Merger/SchemaMergerTest.php @@ -86,14 +86,14 @@ public function testGetResolvedSchemaTemplate() { "name": "items", "type": {"type": "array", "items": "com.example.Page" }, "default": [] } ] }'; - $subschemaDefinition = '{ + $subschemaDefinition = json_encode(json_decode('{ "type": "record", "namespace": "com.example", "name": "Page", "fields": [ { "name": "number", "type": "int" } ] - }'; + }')); $expectedResult = str_replace('"com.example.Page"', $subschemaDefinition, $rootDefinition); @@ -124,6 +124,104 @@ public function testGetResolvedSchemaTemplate() $merger->getResolvedSchemaTemplate($rootSchemaTemplate); } + public function testGetResolvedSchemaTemplateWithEmbeddedRoot(): void + { + $rootDefinition = '{ + "type": "record", + "namespace": "com.example", + "schema_level": "root", + "name": "Library", + "fields": [ + { + "name": "name", + "type": "string" + }, + { + "name": "foundingYear", + "type": [ + "null", + "int" + ], + "default": null + }, + { + "name": "type", + "type": [ + "null", + { + "name": "type", + "type": "enum", + "symbols": [ + "PUBLIC", + "PRIVATE" + ] + } + ], + "default": null + }, + { + "name": "collection", + "type": { + "type": "array", + "items": "com.example.Collection" + }, + "default": [] + }, + { + "name": "archive", + "type": { + "type": "array", + "items": "com.example.Collection" + }, + "default": [] + } + ] + }'; + $subschemaDefinition = json_encode(json_decode('{ + "type": "record", + "namespace": "com.example", + "schema_level": "root", + "name": "Collection", + "fields": [ + { "name": "name", "type": "string" } + ] + }')); + + $subschemaDefinitionArray = \Safe\json_decode($subschemaDefinition, true); + unset($subschemaDefinitionArray['schema_level']); + $subschemaDefinitionWithoutLevel = json_encode($subschemaDefinitionArray); + + $subschemaId = '"com.example.Collection"'; + $pos = strpos($rootDefinition, $subschemaId); + $expectedResult = substr_replace($rootDefinition, $subschemaDefinitionWithoutLevel, $pos, strlen($subschemaId)); + + $subschemaTemplate = $this->getMockForAbstractClass(SchemaTemplateInterface::class); + $subschemaTemplate + ->expects(self::once()) + ->method('getSchemaDefinition') + ->willReturn($subschemaDefinition); + $schemaRegistry = $this->getMockForAbstractClass(SchemaRegistryInterface::class); + $schemaRegistry + ->expects(self::once()) + ->method('getSchemaById') + ->with('com.example.Collection') + ->willReturn($subschemaTemplate); + $rootSchemaTemplate = $this->getMockForAbstractClass(SchemaTemplateInterface::class); + $rootSchemaTemplate + ->expects(self::once()) + ->method('getSchemaDefinition') + ->willReturn($rootDefinition); + $rootSchemaTemplate + ->expects(self::once()) + ->method('withSchemaDefinition') + ->with($expectedResult) + ->willReturn($rootSchemaTemplate); + + $merger = new SchemaMerger($schemaRegistry); + + $merger->getResolvedSchemaTemplate($rootSchemaTemplate); + } + public function testGetResolvedSchemaTemplateWithMultiEmbedd() { $rootDefinition = $this->reformatJsonString('{ @@ -304,14 +402,14 @@ public function testGetResolvedSchemaTemplateWithDifferentNamespaceForEmbeddedSc { "name": "items", "type": {"type": "array", "items": "com.example.other.Page" }, "default": [] } ] }'; - $subschemaDefinition = '{ + $subschemaDefinition = json_encode(json_decode('{ "type": "record", "namespace": "com.example.other", "name": "Page", "fields": [ { "name": "number", "type": "int" } ] - }'; + }')); $expectedResult = str_replace('"com.example.other.Page"', $subschemaDefinition, $rootDefinition);