Skip to content

Commit

Permalink
fix: use validation groups for property metadata in JSON Schema factory
Browse files Browse the repository at this point in the history
  • Loading branch information
alanpoulain committed Oct 31, 2020
1 parent 8e58a98 commit a9fd1b8
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
30 changes: 21 additions & 9 deletions src/JsonSchema/SchemaFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public function buildSchema(string $className, string $format = 'json', string $
if (null === $metadata = $this->getMetadata($className, $type, $operationType, $operationName, $serializerContext)) {
return $schema;
}
[$resourceMetadata, $serializerContext, $inputOrOutputClass] = $metadata;
[$resourceMetadata, $serializerContext, $validationGroups, $inputOrOutputClass] = $metadata;

if (null === $resourceMetadata && (null !== $operationType || null !== $operationName)) {
throw new \LogicException('The $operationType and $operationName arguments must be null for non-resource class.');
Expand Down Expand Up @@ -131,7 +131,7 @@ public function buildSchema(string $className, string $format = 'json', string $
$definition['externalDocs'] = ['url' => $iri];
}

$options = $this->getFactoryOptions($serializerContext, $operationType, $operationName);
$options = $this->getFactoryOptions($serializerContext, $validationGroups, $operationType, $operationName);
foreach ($this->propertyNameCollectionFactory->create($inputOrOutputClass, $options) as $propertyName) {
$propertyMetadata = $this->propertyMetadataFactory->create($inputOrOutputClass, $propertyName, $options);
if (!$propertyMetadata->isReadable() && !$propertyMetadata->isWritable()) {
Expand Down Expand Up @@ -200,18 +200,13 @@ private function buildPropertySchema(Schema $schema, string $definitionName, str
}

$propertySchema = new \ArrayObject($propertySchema + $valueSchema);
if (DocumentationNormalizer::OPENAPI_VERSION === $version) {
$schema->getDefinitions()[$definitionName]['properties'][$normalizedPropertyName] = $propertySchema;

return;
}

$schema->getDefinitions()[$definitionName]['properties'][$normalizedPropertyName] = $propertySchema;
}

private function buildDefinitionName(string $className, string $format = 'json', string $type = Schema::TYPE_OUTPUT, ?string $operationType = null, ?string $operationName = null, ?array $serializerContext = null): string
{
[$resourceMetadata, $serializerContext, $inputOrOutputClass] = $this->getMetadata($className, $type, $operationType, $operationName, $serializerContext);
[$resourceMetadata, $serializerContext,, $inputOrOutputClass] = $this->getMetadata($className, $type, $operationType, $operationName, $serializerContext);

$prefix = $resourceMetadata ? $resourceMetadata->getShortName() : (new \ReflectionClass($className))->getShortName();
if (null !== $inputOrOutputClass && $className !== $inputOrOutputClass) {
Expand Down Expand Up @@ -239,6 +234,7 @@ private function getMetadata(string $className, string $type = Schema::TYPE_OUTP
return [
null,
$serializerContext ?? [],
[],
$className,
];
}
Expand All @@ -259,6 +255,7 @@ private function getMetadata(string $className, string $type = Schema::TYPE_OUTP
return [
$resourceMetadata,
$serializerContext ?? $this->getSerializerContext($resourceMetadata, $type, $operationType, $operationName),
$this->getValidationGroups($resourceMetadata, $operationType, $operationName),
$inputOrOutput['class'],
];
}
Expand All @@ -274,10 +271,21 @@ private function getSerializerContext(ResourceMetadata $resourceMetadata, string
return $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, $attribute, [], true);
}

private function getValidationGroups(ResourceMetadata $resourceMetadata, ?string $operationType, ?string $operationName): array
{
$attribute = 'validation_groups';

if (null === $operationType || null === $operationName) {
return \is_array($validationGroups = $resourceMetadata->getAttribute($attribute, [])) ? $validationGroups : [];
}

return \is_array($validationGroups = $resourceMetadata->getTypedOperationAttribute($operationType, $operationName, $attribute, [], true)) ? $validationGroups : [];
}

/**
* Gets the options for the property name collection / property metadata factories.
*/
private function getFactoryOptions(array $serializerContext, ?string $operationType, ?string $operationName): array
private function getFactoryOptions(array $serializerContext, array $validationGroups, ?string $operationType, ?string $operationName): array
{
$options = [];

Expand All @@ -299,6 +307,10 @@ private function getFactoryOptions(array $serializerContext, ?string $operationT
}
}

if ($validationGroups) {
$options['validation_groups'] = $validationGroups;
}

return $options;
}
}
8 changes: 5 additions & 3 deletions tests/JsonSchema/SchemaFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public function testBuildSchemaForOperationWithOverriddenSerializerGroups(): voi
'normalization_context' => [
'groups' => 'overridden_operation_dummy_put',
],
'validation_groups' => ['validation_groups_dummy_put'],
],
], [], [
'normalization_context' => [
Expand All @@ -106,21 +107,22 @@ public function testBuildSchemaForOperationWithOverriddenSerializerGroups(): voi
]));

$serializerGroup = 'overridden_operation_dummy_put';
$validationGroups = 'validation_groups_dummy_put';

$propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class);
$propertyNameCollectionFactoryProphecy->create(OverriddenOperationDummy::class, Argument::allOf(
Argument::type('array'),
Argument::withEntry('serializer_groups', [$serializerGroup])
Argument::allOf(Argument::withEntry('serializer_groups', [$serializerGroup]), Argument::withEntry('validation_groups', [$validationGroups]))
))->willReturn(new PropertyNameCollection(['alias', 'description']));

$propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class);
$propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'alias', Argument::allOf(
Argument::type('array'),
Argument::withEntry('serializer_groups', [$serializerGroup])
Argument::allOf(Argument::withEntry('serializer_groups', [$serializerGroup]), Argument::withEntry('validation_groups', [$validationGroups]))
))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true));
$propertyMetadataFactoryProphecy->create(OverriddenOperationDummy::class, 'description', Argument::allOf(
Argument::type('array'),
Argument::withEntry('serializer_groups', [$serializerGroup])
Argument::allOf(Argument::withEntry('serializer_groups', [$serializerGroup]), Argument::withEntry('validation_groups', [$validationGroups]))
))->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), null, true));

$resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class);
Expand Down

0 comments on commit a9fd1b8

Please sign in to comment.