From ec716af7a56d454c93f9e37d22202e9675bdfa80 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 1 Nov 2023 17:24:44 +0100 Subject: [PATCH 1/3] fix(serializer): json violation list normalizer fixes #5912 --- features/main/validation.feature | 30 +++++++++++++ .../Resources/config/symfony/validator.xml | 8 ++++ .../ConstraintViolationListNormalizer.php | 44 +++++++++++++++++++ .../TestBundle/Entity/Issue5912/Dummy.php | 32 ++++++++++++++ 4 files changed, 114 insertions(+) create mode 100644 src/Symfony/Validator/Serializer/ConstraintViolationListNormalizer.php create mode 100644 tests/Fixtures/TestBundle/Entity/Issue5912/Dummy.php diff --git a/features/main/validation.feature b/features/main/validation.feature index e0e29dfe181..4381add967a 100644 --- a/features/main/validation.feature +++ b/features/main/validation.feature @@ -157,3 +157,33 @@ Feature: Using validations groups ] } """ + + Scenario: Get violations constraints + When I add "Accept" header equal to "application/json" + And I add "Content-Type" header equal to "application/json" + And I send a "POST" request to "/issue5912s" with body: + """ + { + "title": "" + } + """ + Then the response status code should be 422 + And the response should be in JSON + And the JSON should be equal to: + """ + { + "status": 422, + "violations": [ + { + "propertyPath": "title", + "message": "This value should not be blank.", + "code": "c1051bb4-d103-4f74-8988-acbcafc7fdc3" + } + ], + "detail": "title: This value should not be blank.", + "type": "/validation_errors/c1051bb4-d103-4f74-8988-acbcafc7fdc3", + "title": "An error occurred" + } + """ + And the header "Content-Type" should be equal to "application/problem+json; charset=utf-8" + diff --git a/src/Symfony/Bundle/Resources/config/symfony/validator.xml b/src/Symfony/Bundle/Resources/config/symfony/validator.xml index 0f8eb782224..cf5c9f92a9c 100644 --- a/src/Symfony/Bundle/Resources/config/symfony/validator.xml +++ b/src/Symfony/Bundle/Resources/config/symfony/validator.xml @@ -31,6 +31,14 @@ + + + %api_platform.validator.serialize_payload_fields% + + + + + diff --git a/src/Symfony/Validator/Serializer/ConstraintViolationListNormalizer.php b/src/Symfony/Validator/Serializer/ConstraintViolationListNormalizer.php new file mode 100644 index 00000000000..46fb21cf55c --- /dev/null +++ b/src/Symfony/Validator/Serializer/ConstraintViolationListNormalizer.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Symfony\Validator\Serializer; + +use ApiPlatform\Serializer\AbstractConstraintViolationListNormalizer; +use Symfony\Component\Serializer\NameConverter\NameConverterInterface; + +/** + * Converts {@see \Symfony\Component\Validator\ConstraintViolationListInterface} the API Problem spec (RFC 7807). + * + * @author Kévin Dunglas + */ +final class ConstraintViolationListNormalizer extends AbstractConstraintViolationListNormalizer +{ + public const FORMAT = 'json'; + + private array $defaultContext = []; + + public function __construct(array $serializePayloadFields = null, NameConverterInterface $nameConverter = null, array $defaultContext = []) + { + parent::__construct($serializePayloadFields, $nameConverter); + + $this->defaultContext = array_merge($this->defaultContext, $defaultContext); + } + + /** + * {@inheritdoc} + */ + public function normalize(mixed $object, string $format = null, array $context = []): array + { + return $this->getViolations($object); + } +} diff --git a/tests/Fixtures/TestBundle/Entity/Issue5912/Dummy.php b/tests/Fixtures/TestBundle/Entity/Issue5912/Dummy.php new file mode 100644 index 00000000000..46c50d630aa --- /dev/null +++ b/tests/Fixtures/TestBundle/Entity/Issue5912/Dummy.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace ApiPlatform\Tests\Fixtures\TestBundle\Entity\Issue5912; + +use ApiPlatform\Metadata\ApiResource; +use ApiPlatform\Metadata\NotExposed; +use ApiPlatform\Metadata\Post; +use Symfony\Component\Validator\Constraints\NotBlank; + +#[ApiResource( + shortName: 'Issue5912', + operations: [ + new NotExposed(), + new Post(), + ] +)] +class Dummy +{ + #[NotBlank] + public string $title; +} From 2551658c2de886dadffc0c1345cae39b3c3a5237 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 1 Nov 2023 17:48:35 +0100 Subject: [PATCH 2/3] fixes #5916 --- .../Validator/Exception/ValidationException.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Validator/Exception/ValidationException.php b/src/Symfony/Validator/Exception/ValidationException.php index 9d46283ebb7..ef80badd00d 100644 --- a/src/Symfony/Validator/Exception/ValidationException.php +++ b/src/Symfony/Validator/Exception/ValidationException.php @@ -19,6 +19,7 @@ use ApiPlatform\Metadata\Exception\ProblemExceptionInterface; use ApiPlatform\Metadata\Util\CompositeIdentifierParser; use ApiPlatform\Validator\Exception\ValidationException as BaseValidationException; +use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; use Symfony\Component\Serializer\Annotation\Groups; use Symfony\Component\Serializer\Annotation\SerializedName; use Symfony\Component\Validator\ConstraintViolationListInterface; @@ -50,7 +51,7 @@ ], graphQlOperations: [] )] -final class ValidationException extends BaseValidationException implements ConstraintViolationListAwareExceptionInterface, \Stringable, ProblemExceptionInterface +final class ValidationException extends BaseValidationException implements ConstraintViolationListAwareExceptionInterface, \Stringable, ProblemExceptionInterface, HttpExceptionInterface { private int $status = 422; @@ -154,4 +155,14 @@ public function __toString(): string return $message; } + + public function getStatusCode(): int + { + return $this->status; + } + + public function getHeaders(): array + { + return []; + } } From af37e7d6ca4e4466da154356b840c6945dbe5238 Mon Sep 17 00:00:00 2001 From: soyuka Date: Wed, 1 Nov 2023 17:56:41 +0100 Subject: [PATCH 3/3] fixes #5916 --- features/main/validation.feature | 1 + 1 file changed, 1 insertion(+) diff --git a/features/main/validation.feature b/features/main/validation.feature index 4381add967a..170c4c51a27 100644 --- a/features/main/validation.feature +++ b/features/main/validation.feature @@ -158,6 +158,7 @@ Feature: Using validations groups } """ + @!mongodb Scenario: Get violations constraints When I add "Accept" header equal to "application/json" And I add "Content-Type" header equal to "application/json"