Skip to content

Commit

Permalink
Merge branch '6.4' into 7.1
Browse files Browse the repository at this point in the history
* 6.4:
  [BeanstalkMessenger] Round delay to an integer to avoid deprecation warning
  [PropertyInfo] Fix interface handling in `PhpStanTypeHelper`
  [HttpClient] Test POST to GET redirects
  [HttpKernel] Denormalize request data using the csv format when using "#[MapQueryString]" or "#[MapRequestPayload]" (except for content data)
  fix: preserve and nowrap in profiler code highlighting
  • Loading branch information
fabpot committed Dec 11, 2024
2 parents 451a858 + 661cb10 commit ec3423a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 4 deletions.
6 changes: 2 additions & 4 deletions Controller/ArgumentResolver/RequestPayloadValueResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@
class RequestPayloadValueResolver implements ValueResolverInterface, EventSubscriberInterface
{
/**
* @see \Symfony\Component\Serializer\Normalizer\AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT
* @see DenormalizerInterface::COLLECT_DENORMALIZATION_ERRORS
*/
private const CONTEXT_DENORMALIZE = [
'disable_type_enforcement' => true,
'collect_denormalization_errors' => true,
];

Expand Down Expand Up @@ -189,7 +187,7 @@ private function mapQueryString(Request $request, ArgumentMetadata $argument, Ma
return null;
}

return $this->serializer->denormalize($data, $argument->getType(), null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ['filter_bool' => true]);
return $this->serializer->denormalize($data, $argument->getType(), 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ['filter_bool' => true]);
}

private function mapRequestPayload(Request $request, ArgumentMetadata $argument, MapRequestPayload $attribute): object|array|null
Expand All @@ -209,7 +207,7 @@ private function mapRequestPayload(Request $request, ArgumentMetadata $argument,
}

if ($data = $request->request->all()) {
return $this->serializer->denormalize($data, $type, null, $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ('form' === $format ? ['filter_bool' => true] : []));
return $this->serializer->denormalize($data, $type, 'csv', $attribute->serializationContext + self::CONTEXT_DENORMALIZE + ('form' === $format ? ['filter_bool' => true] : []));
}

if ('' === $data = $request->getContent()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\NearMissValueResolverException;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Encoder\XmlEncoder;
use Symfony\Component\Serializer\Exception\NotNormalizableValueException;
Expand Down Expand Up @@ -395,6 +396,38 @@ public function testQueryStringValidationPassed()
$this->assertEquals([$payload], $event->getArguments());
}

public function testQueryStringParameterTypeMismatch()
{
$query = ['price' => 'not a float'];

$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
$serializer = new Serializer([$normalizer], ['json' => new JsonEncoder()]);

$validator = $this->createMock(ValidatorInterface::class);
$validator->expects($this->never())->method('validate');

$resolver = new RequestPayloadValueResolver($serializer, $validator);

$argument = new ArgumentMetadata('invalid', RequestPayload::class, false, false, null, false, [
MapQueryString::class => new MapQueryString(),
]);

$request = Request::create('/', 'GET', $query);

$kernel = $this->createMock(HttpKernelInterface::class);
$arguments = $resolver->resolve($request, $argument);
$event = new ControllerArgumentsEvent($kernel, function () {}, $arguments, $request, HttpKernelInterface::MAIN_REQUEST);

try {
$resolver->onKernelControllerArguments($event);
$this->fail(sprintf('Expected "%s" to be thrown.', HttpException::class));
} catch (HttpException $e) {
$validationFailedException = $e->getPrevious();
$this->assertInstanceOf(ValidationFailedException::class, $validationFailedException);
$this->assertSame('This value should be of type float.', $validationFailedException->getViolations()[0]->getMessage());
}
}

public function testRequestInputValidationPassed()
{
$input = ['price' => '50'];
Expand Down Expand Up @@ -457,6 +490,38 @@ public function testRequestArrayDenormalization()
$this->assertEquals([$payload], $event->getArguments());
}

public function testRequestInputTypeMismatch()
{
$input = ['price' => 'not a float'];

$normalizer = new ObjectNormalizer(null, null, null, new ReflectionExtractor());
$serializer = new Serializer([$normalizer], ['json' => new JsonEncoder()]);

$validator = $this->createMock(ValidatorInterface::class);
$validator->expects($this->never())->method('validate');

$resolver = new RequestPayloadValueResolver($serializer, $validator);

$argument = new ArgumentMetadata('invalid', RequestPayload::class, false, false, null, false, [
MapRequestPayload::class => new MapRequestPayload(),
]);

$request = Request::create('/', 'POST', $input);

$kernel = $this->createMock(HttpKernelInterface::class);
$arguments = $resolver->resolve($request, $argument);
$event = new ControllerArgumentsEvent($kernel, function () {}, $arguments, $request, HttpKernelInterface::MAIN_REQUEST);

try {
$resolver->onKernelControllerArguments($event);
$this->fail(sprintf('Expected "%s" to be thrown.', HttpException::class));
} catch (HttpException $e) {
$validationFailedException = $e->getPrevious();
$this->assertInstanceOf(ValidationFailedException::class, $validationFailedException);
$this->assertSame('This value should be of type float.', $validationFailedException->getViolations()[0]->getMessage());
}
}

public function testItThrowsOnMissingAttributeType()
{
$serializer = new Serializer();
Expand Down

0 comments on commit ec3423a

Please sign in to comment.