diff --git a/src/Hydra/Serializer/DocumentationNormalizer.php b/src/Hydra/Serializer/DocumentationNormalizer.php index a9ef38556f9..6e0fdb5a548 100644 --- a/src/Hydra/Serializer/DocumentationNormalizer.php +++ b/src/Hydra/Serializer/DocumentationNormalizer.php @@ -201,9 +201,13 @@ private function getHydraProperties(string $resourceClass, ResourceMetadata $res /** @var string[] $classes */ $classes = array_keys($classes); $properties = []; + $options = []; + if ($validationGroups = $this->getValidationGroups($resourceMetadata)) { + $options['validation_groups'] = $validationGroups; + } foreach ($classes as $class) { foreach ($this->propertyNameCollectionFactory->create($class, $this->getPropertyNameCollectionFactoryContext($resourceMetadata)) as $propertyName) { - $propertyMetadata = $this->propertyMetadataFactory->create($class, $propertyName); + $propertyMetadata = $this->propertyMetadataFactory->create($class, $propertyName, $options); if (true === $propertyMetadata->isIdentifier() && false === $propertyMetadata->isWritable()) { continue; } @@ -219,6 +223,17 @@ private function getHydraProperties(string $resourceClass, ResourceMetadata $res return $properties; } + private function getValidationGroups(ResourceMetadata $resourceMetadata): array + { + foreach ($resourceMetadata->getCollectionOperations() as $operationName => $operation) { + if ('POST' === $operation['method']) { + return \is_array($validationGroups = $resourceMetadata->getTypedOperationAttribute(OperationType::COLLECTION, $operationName, 'validation_groups', [])) ? $validationGroups : []; + } + } + + return []; + } + /** * Gets Hydra operations. */ diff --git a/tests/Hydra/Serializer/DocumentationNormalizerTest.php b/tests/Hydra/Serializer/DocumentationNormalizerTest.php index e75d39186e8..4cac87f9c2d 100644 --- a/tests/Hydra/Serializer/DocumentationNormalizerTest.php +++ b/tests/Hydra/Serializer/DocumentationNormalizerTest.php @@ -66,17 +66,18 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth $propertyNameCollectionFactoryProphecy = $this->prophesize(PropertyNameCollectionFactoryInterface::class); $propertyNameCollectionFactoryProphecy->create('dummy', [])->shouldBeCalled()->willReturn(new PropertyNameCollection(['name', 'description', 'nameConverted', 'relatedDummy'])); - $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST']], []); + $dummyMetadata = new ResourceMetadata('dummy', 'dummy', '#dummy', ['get' => ['method' => 'GET', 'hydra_context' => ['hydra:foo' => 'bar', 'hydra:title' => 'foobar']], 'put' => ['method' => 'PUT']], ['get' => ['method' => 'GET'], 'post' => ['method' => 'POST', 'validation_groups' => ['create']]], []); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); $resourceMetadataFactoryProphecy->create('relatedDummy')->shouldBeCalled()->willReturn(new ResourceMetadata('relatedDummy')); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('dummy', 'name')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create('dummy', 'description')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'description', true, true, true, true, false, false, null, null, ['jsonld_context' => ['@type' => '@id']])); - $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name converted', true, true, true, true, false, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('dummy', 'name', ['validation_groups' => ['create']])->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name', true, true, true, true, true, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('dummy', 'name', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name', true, true, true, true, false, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('dummy', 'description', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'description', true, true, true, true, false, false, null, null, ['jsonld_context' => ['@type' => '@id']])); + $propertyMetadataFactoryProphecy->create('dummy', 'nameConverted', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'name converted', true, true, true, true, false, false, null, null, [])); $subresourceMetadata = new SubresourceMetadata('relatedDummy', false); - $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); + $propertyMetadataFactoryProphecy->create('dummy', 'relatedDummy', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'dummy', true, null, new Type(Type::BUILTIN_TYPE_OBJECT, false, 'relatedDummy')), 'This is a name.', true, true, true, true, false, false, null, null, [], $subresourceMetadata)); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true); @@ -165,7 +166,7 @@ private function doTestNormalize(OperationMethodResolverInterface $operationMeth 'range' => 'xmls:string', ], 'hydra:title' => 'name', - 'hydra:required' => false, + 'hydra:required' => true, 'hydra:readable' => true, 'hydra:writeable' => true, 'hydra:description' => 'name', @@ -397,10 +398,10 @@ public function testNormalizeInputOutputClass() $resourceMetadataFactoryProphecy->create('dummy')->shouldBeCalled()->willReturn($dummyMetadata); $propertyMetadataFactoryProphecy = $this->prophesize(PropertyMetadataFactoryInterface::class); - $propertyMetadataFactoryProphecy->create('inputClass', 'a')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'a', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create('inputClass', 'b')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'b', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create('outputClass', 'c')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'c', true, true, true, true, false, false, null, null, [])); - $propertyMetadataFactoryProphecy->create('outputClass', 'd')->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'd', true, true, true, true, false, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('inputClass', 'a', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'a', true, true, true, true, false, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('inputClass', 'b', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'b', true, true, true, true, false, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('outputClass', 'c', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'c', true, true, true, true, false, false, null, null, [])); + $propertyMetadataFactoryProphecy->create('outputClass', 'd', Argument::any())->shouldBeCalled()->willReturn(new PropertyMetadata(new Type(Type::BUILTIN_TYPE_STRING), 'd', true, true, true, true, false, false, null, null, [])); $resourceClassResolverProphecy = $this->prophesize(ResourceClassResolverInterface::class); $resourceClassResolverProphecy->isResourceClass(Argument::type('string'))->willReturn(true);