Skip to content

Commit f07b2f6

Browse files
authored
fix: add base Hydra properties to collection items definition in JSON Schema (#3803)
1 parent 1b18bce commit f07b2f6

File tree

4 files changed

+54
-6
lines changed

4 files changed

+54
-6
lines changed

src/Hydra/JsonSchema/SchemaFactory.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ final class SchemaFactory implements SchemaFactoryInterface
3131
'type' => 'string',
3232
];
3333
private const BASE_PROPS = [
34-
'@context' => self::BASE_PROP,
3534
'@id' => self::BASE_PROP,
3635
'@type' => self::BASE_PROP,
3736
];
37+
private const BASE_ROOT_PROPS = [
38+
'@context' => self::BASE_PROP,
39+
] + self::BASE_PROPS;
3840

3941
private $schemaFactory;
4042

@@ -59,10 +61,13 @@ public function buildSchema(string $className, string $format = 'jsonld', string
5961

6062
$definitions = $schema->getDefinitions();
6163
if ($key = $schema->getRootDefinitionKey()) {
62-
$definitions[$key]['properties'] = self::BASE_PROPS + ($definitions[$key]['properties'] ?? []);
64+
$definitions[$key]['properties'] = self::BASE_ROOT_PROPS + ($definitions[$key]['properties'] ?? []);
6365

6466
return $schema;
6567
}
68+
if ($key = $schema->getItemsDefinitionKey()) {
69+
$definitions[$key]['properties'] = self::BASE_PROPS + ($definitions[$key]['properties'] ?? []);
70+
}
6671

6772
if (($schema['type'] ?? '') === 'array') {
6873
// hydra:collection

src/JsonSchema/Schema.php

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,20 @@ public function getRootDefinitionKey(): ?string
100100
return null;
101101
}
102102

103-
// strlen('#/definitions/') = 14
104-
// strlen('#/components/schemas/') = 21
105-
$prefix = self::VERSION_OPENAPI === $this->version ? 21 : 14;
103+
return $this->removeDefinitionKeyPrefix($this['$ref']);
104+
}
106105

107-
return substr($this['$ref'], $prefix);
106+
/**
107+
* Returns the name of the items definition, if defined.
108+
*/
109+
public function getItemsDefinitionKey(): ?string
110+
{
111+
$ref = $this['items']['$ref'] ?? null;
112+
if (null === $ref) {
113+
return null;
114+
}
115+
116+
return $this->removeDefinitionKeyPrefix($ref);
108117
}
109118

110119
/**
@@ -114,4 +123,13 @@ public function isDefined(): bool
114123
{
115124
return isset($this['$ref']) || isset($this['type']);
116125
}
126+
127+
private function removeDefinitionKeyPrefix(string $definitionKey): string
128+
{
129+
// strlen('#/definitions/') = 14
130+
// strlen('#/components/schemas/') = 21
131+
$prefix = self::VERSION_OPENAPI === $this->version ? 21 : 14;
132+
133+
return substr($definitionKey, $prefix);
134+
}
117135
}

tests/Hydra/JsonSchema/SchemaFactoryTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ public function testHasRootDefinitionKeyBuildSchema(): void
7777
$this->assertEquals(Dummy::class.':jsonld', $rootDefinitionKey);
7878
$this->assertArrayHasKey($rootDefinitionKey, $definitions);
7979
$this->assertArrayHasKey('properties', $definitions[$rootDefinitionKey]);
80+
$properties = $resultSchema['definitions'][$rootDefinitionKey]['properties'];
81+
$this->assertArrayHasKey('@context', $properties);
82+
$this->assertArrayHasKey('@type', $properties);
83+
$this->assertArrayHasKey('@id', $properties);
8084
}
8185

8286
public function testSchemaTypeBuildSchema(): void
@@ -89,6 +93,10 @@ public function testSchemaTypeBuildSchema(): void
8993
$this->assertArrayHasKey('hydra:totalItems', $resultSchema['properties']);
9094
$this->assertArrayHasKey('hydra:view', $resultSchema['properties']);
9195
$this->assertArrayHasKey('hydra:search', $resultSchema['properties']);
96+
$properties = $resultSchema['definitions'][Dummy::class.':jsonld']['properties'];
97+
$this->assertArrayNotHasKey('@context', $properties);
98+
$this->assertArrayHasKey('@type', $properties);
99+
$this->assertArrayHasKey('@id', $properties);
92100

93101
$resultSchema = $this->schemaFactory->buildSchema(Dummy::class, 'jsonld', Schema::TYPE_OUTPUT, null, null, null, null, true);
94102

@@ -98,5 +106,9 @@ public function testSchemaTypeBuildSchema(): void
98106
$this->assertArrayHasKey('hydra:totalItems', $resultSchema['properties']);
99107
$this->assertArrayHasKey('hydra:view', $resultSchema['properties']);
100108
$this->assertArrayHasKey('hydra:search', $resultSchema['properties']);
109+
$properties = $resultSchema['definitions'][Dummy::class.':jsonld']['properties'];
110+
$this->assertArrayNotHasKey('@context', $properties);
111+
$this->assertArrayHasKey('@type', $properties);
112+
$this->assertArrayHasKey('@id', $properties);
101113
}
102114
}

tests/JsonSchema/SchemaTest.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,19 @@ public function testJsonSchemaVersion(string $version, string $ref): void
3131
$this->assertSame('Foo', $schema->getRootDefinitionKey());
3232
}
3333

34+
/**
35+
* @dataProvider versionProvider
36+
*/
37+
public function testCollectionJsonSchemaVersion(string $version, string $ref): void
38+
{
39+
$schema = new Schema($version);
40+
$schema['items']['$ref'] = $ref;
41+
42+
$this->assertInstanceOf(\ArrayObject::class, $schema);
43+
$this->assertSame($version, $schema->getVersion());
44+
$this->assertSame('Foo', $schema->getItemsDefinitionKey());
45+
}
46+
3447
public function versionProvider(): iterable
3548
{
3649
yield [Schema::VERSION_JSON_SCHEMA, '#/definitions/Foo'];

0 commit comments

Comments
 (0)