Skip to content

Commit 6823232

Browse files
committed
fix(json-schema): share invariable sub-schemas
1 parent 51f64ed commit 6823232

File tree

6 files changed

+47
-58
lines changed

6 files changed

+47
-58
lines changed

src/Hydra/JsonSchema/SchemaFactory.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,8 @@ final class SchemaFactory implements SchemaFactoryInterface, SchemaFactoryAwareI
6767
'additionalProperties' => true,
6868
],
6969
],
70-
] + self::BASE_PROPS,
71-
],
70+
],
71+
] + self::BASE_PROPS,
7272
];
7373

7474
private const ITEM_BASE_SCHEMA_OUTPUT = [

src/Hydra/Tests/JsonSchema/SchemaFactoryTest.php

+35-46
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
use ApiPlatform\JsonSchema\DefinitionNameFactory;
2020
use ApiPlatform\JsonSchema\Schema;
2121
use ApiPlatform\JsonSchema\SchemaFactory as BaseSchemaFactory;
22+
use ApiPlatform\Metadata\ApiProperty;
2223
use ApiPlatform\Metadata\ApiResource;
2324
use ApiPlatform\Metadata\Get;
2425
use ApiPlatform\Metadata\GetCollection;
@@ -28,6 +29,7 @@
2829
use ApiPlatform\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface;
2930
use ApiPlatform\Metadata\Resource\ResourceMetadataCollection;
3031
use PHPUnit\Framework\TestCase;
32+
use Prophecy\Argument;
3133
use Prophecy\PhpUnit\ProphecyTrait;
3234

3335
class SchemaFactoryTest extends TestCase
@@ -48,10 +50,12 @@ protected function setUp(): void
4850
);
4951

5052
$propertyNameCollectionFactory = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
51-
$propertyNameCollectionFactory->create(Dummy::class, ['enable_getter_setter_extraction' => true, 'schema_type' => Schema::TYPE_OUTPUT])->willReturn(new PropertyNameCollection());
53+
$propertyNameCollectionFactory->create(Dummy::class, ['enable_getter_setter_extraction' => true, 'schema_type' => Schema::TYPE_OUTPUT])->willReturn(new PropertyNameCollection(['id', 'name']));
5254
$propertyMetadataFactory = $this->prophesize(PropertyMetadataFactoryInterface::class);
55+
$propertyMetadataFactory->create(Dummy::class, 'id', Argument::type('array'))->willReturn(new ApiProperty(identifier: true));
56+
$propertyMetadataFactory->create(Dummy::class, 'name', Argument::type('array'))->willReturn(new ApiProperty());
5357

54-
$definitionNameFactory = new DefinitionNameFactory(['jsonapi' => true, 'jsonhal' => true, 'jsonld' => true]);
58+
$definitionNameFactory = new DefinitionNameFactory();
5559

5660
$baseSchemaFactory = new BaseSchemaFactory(
5761
resourceMetadataFactory: $resourceMetadataFactoryCollection->reveal(),
@@ -60,7 +64,12 @@ protected function setUp(): void
6064
definitionNameFactory: $definitionNameFactory,
6165
);
6266

63-
$this->schemaFactory = new SchemaFactory($baseSchemaFactory);
67+
$this->schemaFactory = new SchemaFactory(
68+
$baseSchemaFactory,
69+
[],
70+
$definitionNameFactory,
71+
$resourceMetadataFactoryCollection->reveal(),
72+
);
6473
}
6574

6675
public function testBuildSchema(): void
@@ -86,12 +95,13 @@ public function testHasRootDefinitionKeyBuildSchema(): void
8695
$rootDefinitionKey = $resultSchema->getRootDefinitionKey();
8796

8897
$this->assertTrue(isset($definitions[$rootDefinitionKey]));
89-
$this->assertTrue(isset($definitions[$rootDefinitionKey]['properties']));
90-
$properties = $resultSchema['definitions'][$rootDefinitionKey]['properties'];
98+
$this->assertTrue(isset($definitions[$rootDefinitionKey]['allOf'][1]['properties']));
99+
$this->assertEquals($definitions[$rootDefinitionKey]['allOf'][0], ['$ref' => '#/definitions/HydraItemBaseSchema']);
100+
101+
$properties = $definitions['HydraItemBaseSchema']['properties'];
91102
$this->assertArrayHasKey('@context', $properties);
92103
$this->assertEquals(
93104
[
94-
'readOnly' => true,
95105
'oneOf' => [
96106
['type' => 'string'],
97107
[
@@ -119,55 +129,34 @@ public function testHasRootDefinitionKeyBuildSchema(): void
119129
public function testSchemaTypeBuildSchema(): void
120130
{
121131
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection());
122-
$definitionName = 'Dummy.jsonld';
123-
124132
$this->assertNull($resultSchema->getRootDefinitionKey());
125-
$this->assertTrue(isset($resultSchema['properties']));
126-
$this->assertTrue(isset($resultSchema['properties']['hydra:member']));
127-
$this->assertArrayHasKey('hydra:totalItems', $resultSchema['properties']);
128-
$this->assertArrayHasKey('hydra:view', $resultSchema['properties']);
129-
$this->assertArrayHasKey('hydra:search', $resultSchema['properties']);
130-
$properties = $resultSchema['definitions'][$definitionName]['properties'];
133+
$hydraCollectionSchema = $resultSchema['definitions']['HydraCollectionBaseSchema'];
134+
$properties = $hydraCollectionSchema['properties'];
135+
$this->assertTrue(isset($properties['hydra:member']));
136+
$this->assertArrayHasKey('hydra:totalItems', $properties);
137+
$this->assertArrayHasKey('hydra:view', $properties);
138+
$this->assertArrayHasKey('hydra:search', $properties);
131139
$this->assertArrayNotHasKey('@context', $properties);
132-
$this->assertArrayHasKey('@type', $properties);
133-
$this->assertArrayHasKey('@id', $properties);
134140

135-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, null, null, null, true);
141+
$this->assertTrue(isset($properties['hydra:view']));
142+
$this->assertArrayHasKey('properties', $properties['hydra:view']);
143+
$this->assertArrayHasKey('hydra:first', $properties['hydra:view']['properties']);
144+
$this->assertArrayHasKey('hydra:last', $properties['hydra:view']['properties']);
145+
$this->assertArrayHasKey('hydra:previous', $properties['hydra:view']['properties']);
146+
$this->assertArrayHasKey('hydra:next', $properties['hydra:view']['properties']);
136147

137-
$this->assertNull($resultSchema->getRootDefinitionKey());
138-
$this->assertTrue(isset($resultSchema['properties']));
139-
$this->assertTrue(isset($resultSchema['properties']['hydra:member']));
140-
$this->assertArrayHasKey('hydra:totalItems', $resultSchema['properties']);
141-
$this->assertArrayHasKey('hydra:view', $resultSchema['properties']);
142-
$this->assertArrayHasKey('hydra:search', $resultSchema['properties']);
143-
$properties = $resultSchema['definitions'][$definitionName]['properties'];
144-
$this->assertArrayNotHasKey('@context', $properties);
145-
$this->assertArrayHasKey('@type', $properties);
146-
$this->assertArrayHasKey('@id', $properties);
147-
}
148-
149-
public function testHasHydraViewNavigationBuildSchema(): void
150-
{
151-
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection());
152-
153-
$this->assertNull($resultSchema->getRootDefinitionKey());
154-
$this->assertTrue(isset($resultSchema['properties']));
155-
$this->assertTrue(isset($resultSchema['properties']['hydra:view']));
156-
$this->assertArrayHasKey('properties', $resultSchema['properties']['hydra:view']);
157-
$this->assertArrayHasKey('hydra:first', $resultSchema['properties']['hydra:view']['properties']);
158-
$this->assertArrayHasKey('hydra:last', $resultSchema['properties']['hydra:view']['properties']);
159-
$this->assertArrayHasKey('hydra:previous', $resultSchema['properties']['hydra:view']['properties']);
160-
$this->assertArrayHasKey('hydra:next', $resultSchema['properties']['hydra:view']['properties']);
148+
$forcedCollection = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, null, null, null, true);
149+
$this->assertEquals($resultSchema['allOf'][0]['$ref'], $forcedCollection['allOf'][0]['$ref']);
161150
}
162151

163152
public function testSchemaTypeBuildSchemaWithoutPrefix(): void
164153
{
165154
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, new GetCollection(), null, [ContextBuilder::HYDRA_CONTEXT_HAS_PREFIX => false]);
166155
$this->assertNull($resultSchema->getRootDefinitionKey());
167-
$this->assertTrue(isset($resultSchema['properties']));
168-
$this->assertTrue(isset($resultSchema['properties']['member']));
169-
$this->assertArrayHasKey('totalItems', $resultSchema['properties']);
170-
$this->assertArrayHasKey('view', $resultSchema['properties']);
171-
$this->assertArrayHasKey('search', $resultSchema['properties']);
156+
$hydraCollectionSchema = $resultSchema['definitions']['HydraCollectionBaseSchema'];
157+
$properties = $hydraCollectionSchema['properties'];
158+
$this->assertArrayHasKey('totalItems', $properties);
159+
$this->assertArrayHasKey('view', $properties);
160+
$this->assertArrayHasKey('search', $properties);
172161
}
173162
}

src/JsonSchema/SchemaFactory.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ public function buildSchema(string $className, string $format = 'json', string $
135135
foreach ($this->propertyNameCollectionFactory->create($inputOrOutputClass, $options) as $propertyName) {
136136
$propertyMetadata = $this->propertyMetadataFactory->create($inputOrOutputClass, $propertyName, $options);
137137

138-
if (!$propertyMetadata->isReadable() && !$propertyMetadata->isWritable()) {
138+
if (false === $propertyMetadata->isReadable() && false === $propertyMetadata->isWritable()) {
139139
continue;
140140
}
141141

src/Symfony/Tests/Validator/Metadata/Property/Restriction/PropertySchemaGreaterThanRestrictionTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,25 +79,25 @@ public function testCreate(): void
7979
{
8080
self::assertEquals([
8181
'exclusiveMinimum' => 10,
82-
'minimum' => 10
82+
'minimum' => 10,
8383
], $this->propertySchemaGreaterThanRestriction->create(new GreaterThan(['value' => 10]), (new ApiProperty())->withBuiltinTypes([new LegacyType(LegacyType::BUILTIN_TYPE_INT)])));
8484
}
8585

8686
public function testCreateWithNativeType(): void
8787
{
8888
self::assertEquals([
8989
'exclusiveMinimum' => 10,
90-
'minimum' => 10
90+
'minimum' => 10,
9191
], $this->propertySchemaGreaterThanRestriction->create(new GreaterThan(['value' => 10]), (new ApiProperty())->withNativeType(Type::int())));
9292

9393
self::assertEquals([
9494
'exclusiveMinimum' => 0,
95-
'minimum' => 0
95+
'minimum' => 0,
9696
], $this->propertySchemaGreaterThanRestriction->create(new Positive(), (new ApiProperty())->withNativeType(Type::int())));
9797

9898
self::assertEquals([
9999
'exclusiveMinimum' => 10.99,
100-
'minimum' => 10.99
100+
'minimum' => 10.99,
101101
], $this->propertySchemaGreaterThanRestriction->create(new GreaterThan(['value' => 10.99]), (new ApiProperty())->withNativeType(Type::float())));
102102
}
103103
}

src/Symfony/Tests/Validator/Metadata/Property/Restriction/PropertySchemaLessThanRestrictionTest.php

+4-4
Original file line numberDiff line numberDiff line change
@@ -79,25 +79,25 @@ public function testCreate(): void
7979
{
8080
self::assertEquals([
8181
'exclusiveMaximum' => 10,
82-
'maximum' => 10
82+
'maximum' => 10,
8383
], $this->propertySchemaLessThanRestriction->create(new LessThan(['value' => 10]), (new ApiProperty())->withBuiltinTypes([new LegacyType(LegacyType::BUILTIN_TYPE_INT)])));
8484
}
8585

8686
public function testCreateWithNativeType(): void
8787
{
8888
self::assertEquals([
8989
'exclusiveMaximum' => 10,
90-
'maximum' => 10
90+
'maximum' => 10,
9191
], $this->propertySchemaLessThanRestriction->create(new LessThan(['value' => 10]), (new ApiProperty())->withNativeType(Type::int())));
9292

9393
self::assertEquals([
9494
'exclusiveMaximum' => 0,
95-
'maximum' => 0
95+
'maximum' => 0,
9696
], $this->propertySchemaLessThanRestriction->create(new Negative(), (new ApiProperty())->withNativeType(Type::int())));
9797

9898
self::assertEquals([
9999
'exclusiveMaximum' => 10.99,
100-
'maximum' => 10.99
100+
'maximum' => 10.99,
101101
], $this->propertySchemaLessThanRestriction->create(new LessThan(['value' => 10.99]), (new ApiProperty())->withNativeType(Type::float())));
102102
}
103103
}

src/Symfony/Tests/Validator/Metadata/Property/ValidatorPropertyMetadataFactoryTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ public function testCreateWithPropertyCollectionRestriction(): void
712712
'phone' => ['pattern' => '^([+]*[(]{0,1}[0-9]{1,4}[)]{0,1}[-\s\./0-9]*)$'],
713713
'age' => [
714714
'exclusiveMinimum' => 0,
715-
'minimum' => 0
715+
'minimum' => 0,
716716
],
717717
'social' => [
718718
'type' => 'object',

0 commit comments

Comments
 (0)