From 3c6dd656180013f7e0d8b95236e81ea8435d73a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Fr=C3=A9mont?= Date: Tue, 28 Nov 2023 09:28:11 +0100 Subject: [PATCH] Init serialize processor --- .../EventListener/SerializeListenerTest.php | 214 ++++++++++++++++++ .../State/SerializeProcessorTest.php | 159 +++++++++++++ .../Serializer/State/SerializeProcessor.php | 59 +++++ .../EventListener/SerializeListenerSpec.php | 207 ----------------- 4 files changed, 432 insertions(+), 207 deletions(-) create mode 100644 src/Component/Tests/Symfony/EventListener/SerializeListenerTest.php create mode 100644 src/Component/Tests/Symfony/Serializer/State/SerializeProcessorTest.php create mode 100644 src/Component/src/Symfony/Serializer/State/SerializeProcessor.php delete mode 100644 src/Component/tests/spec/Symfony/EventListener/SerializeListenerSpec.php diff --git a/src/Component/Tests/Symfony/EventListener/SerializeListenerTest.php b/src/Component/Tests/Symfony/EventListener/SerializeListenerTest.php new file mode 100644 index 000000000..ee82e9aaa --- /dev/null +++ b/src/Component/Tests/Symfony/EventListener/SerializeListenerTest.php @@ -0,0 +1,214 @@ +operationInitiator = $this->prophesize(HttpOperationInitiatorInterface::class); + $this->serializer = $this->prophesize(SerializerInterface::class); + + $this->serializeListener = new SerializeListener( + $this->operationInitiator->reveal(), + $this->serializer->reveal(), + ); + } + + /** @test */ + public function it_serializes_data_to_the_requested_format(): void + { + $kernel = $this->prophesize(HttpKernelInterface::class); + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $event = new ViewEvent( + $kernel->reveal(), + $request->reveal(), + HttpKernelInterface::MAIN_REQUEST, + $data->reveal(), + ); + + $this->operationInitiator->initializeOperation($request)->willReturn($operation); + + $request->getRequestFormat()->willReturn('json'); + + $operation->canSerialize()->willReturn(null)->shouldBeCalled(); + $operation->getNormalizationContext()->willReturn([]); + + $this->serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldBeCalled(); + + $this->serializeListener->onKernelView($event); + + Assert::eq($event->getControllerResult(), 'serialized_data'); + } + + /** @test */ + public function it_serializes_data_to_the_requested_format_with_normalization_context(): void + { + $kernel = $this->prophesize(HttpKernelInterface::class); + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $event = new ViewEvent( + $kernel->reveal(), + $request->reveal(), + HttpKernelInterface::MAIN_REQUEST, + $data->reveal(), + ); + + $this->operationInitiator->initializeOperation($request)->willReturn($operation); + + $request->getRequestFormat()->willReturn('json'); + + $operation->canSerialize()->willReturn(null)->shouldBeCalled(); + $operation->getNormalizationContext()->willReturn(['groups' => ['dummy:read']]); + + $this->serializer->serialize($data, 'json', ['groups' => ['dummy:read']])->willReturn('serialized_data')->shouldBeCalled(); + + $this->serializeListener->onKernelView($event); + + Assert::eq($event->getControllerResult(), 'serialized_data'); + } + + /** @test */ + public function it_does_nothing_when_operation_is_null(): void + { + $kernel = $this->prophesize(HttpKernelInterface::class); + $request = $this->prophesize(Request::class); + $data = $this->prophesize(\stdClass::class); + + $event = new ViewEvent( + $kernel->reveal(), + $request->reveal(), + HttpKernelInterface::MAIN_REQUEST, + $data->reveal(), + ); + + $this->operationInitiator->initializeOperation($request)->willReturn(null); + + $request->getRequestFormat()->willReturn('json'); + + $this->serializer->serialize($data, 'json')->willReturn('serialized_data')->shouldNotBeCalled(); + + $this->serializeListener->onKernelView($event); + + Assert::eq($event->getControllerResult(), $data->reveal()); + } + + /** @test */ + public function it_does_nothing_when_format_is_html(): void + { + $kernel = $this->prophesize(HttpKernelInterface::class); + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $event = new ViewEvent( + $kernel->reveal(), + $request->reveal(), + HttpKernelInterface::MAIN_REQUEST, + $data->reveal(), + ); + + $this->operationInitiator->initializeOperation($request)->willReturn($operation); + + $request->getRequestFormat()->willReturn('html'); + + $this->serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldNotBeCalled(); + + $this->serializeListener->onKernelView($event); + + Assert::eq($event->getControllerResult(), $data->reveal()); + } + + /** @test */ + public function it_throws_an_exception_when_serializer_is_not_available(): void + { + $kernel = $this->prophesize(HttpKernelInterface::class); + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $serializeListener = new SerializeListener($this->operationInitiator->reveal(), null); + + $event = new ViewEvent( + $kernel->reveal(), + $request->reveal(), + HttpKernelInterface::MAIN_REQUEST, + $data->reveal(), + ); + + $this->operationInitiator->initializeOperation($request)->willReturn($operation); + + $request->getRequestFormat()->willReturn('json', []); + + $this->serializer->serialize($data, 'json')->willReturn('serialized_data')->shouldNotBeCalled(); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('You can not use the "json" format if the Serializer is not available. Try running "composer require symfony/serializer".'); + + $serializeListener->onKernelView($event); + } + + /** @test */ + public function it_does_nothing_if_operation_cannot_be_serialized(): void + { + $kernel = $this->prophesize(HttpKernelInterface::class); + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $event = new ViewEvent( + $kernel->reveal(), + $request->reveal(), + HttpKernelInterface::MAIN_REQUEST, + $data->reveal(), + ); + + $this->operationInitiator->initializeOperation($request)->willReturn($operation); + + $request->getRequestFormat()->willReturn('json'); + + $operation->canSerialize()->willReturn(false)->shouldBeCalled(); + + $this->serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldNotBeCalled(); + + $this->serializeListener->onKernelView($event); + + Assert::eq($event->getControllerResult(), $data->reveal()); + } +} diff --git a/src/Component/Tests/Symfony/Serializer/State/SerializeProcessorTest.php b/src/Component/Tests/Symfony/Serializer/State/SerializeProcessorTest.php new file mode 100644 index 000000000..5c95f2523 --- /dev/null +++ b/src/Component/Tests/Symfony/Serializer/State/SerializeProcessorTest.php @@ -0,0 +1,159 @@ +decorated = $this->prophesize(ProcessorInterface::class); + $this->serializer = $this->prophesize(SerializerInterface::class); + + $this->serializeProcessor = new SerializeProcessor( + $this->decorated->reveal(), + $this->serializer->reveal(), + ); + } + + /** @test */ + public function it_serializes_data_to_the_requested_format(): void + { + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $context = new Context(new RequestOption($request->reveal())); + + $this->decorated->process($data, $operation, $context)->willReturn($data); + + $request->getRequestFormat()->willReturn('json'); + + $operation->canSerialize()->willReturn(null)->shouldBeCalled(); + $operation->getNormalizationContext()->willReturn([]); + + $this->serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldBeCalled(); + + $result = $this->serializeProcessor->process($data, $operation->reveal(), $context); + + Assert::eq($result, 'serialized_data'); + } + + /** @test */ + public function it_serializes_data_to_the_requested_format_with_normalization_context(): void + { + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $context = new Context(new RequestOption($request->reveal())); + + $this->decorated->process($data, $operation, $context)->willReturn($data); + + $request->getRequestFormat()->willReturn('json'); + + $operation->canSerialize()->willReturn(null)->shouldBeCalled(); + $operation->getNormalizationContext()->willReturn(['groups' => ['dummy:read']]); + + $this->serializer->serialize($data, 'json', ['groups' => ['dummy:read']])->willReturn('serialized_data')->shouldBeCalled(); + + $result = $this->serializeProcessor->process($data, $operation->reveal(), $context); + + Assert::eq($result, 'serialized_data'); + } + + /** @test */ + public function it_does_nothing_when_format_is_html(): void + { + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $context = new Context(new RequestOption($request->reveal())); + + $this->decorated->process($data, $operation, $context)->willReturn($data); + + $request->getRequestFormat()->willReturn('html'); + + $this->serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldNotBeCalled(); + + $result = $this->serializeProcessor->process($data, $operation->reveal(), $context); + + Assert::eq($result, $data->reveal()); + } + + /** @test */ + public function it_throws_an_exception_when_serializer_is_not_available(): void + { + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $serializeProcessor = new SerializeProcessor($this->decorated->reveal(), null); + + $context = new Context(new RequestOption($request->reveal())); + + $this->decorated->process($data, $operation, $context)->willReturn($data); + + $request->getRequestFormat()->willReturn('json', []); + + $this->serializer->serialize($data, 'json')->willReturn('serialized_data')->shouldNotBeCalled(); + + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('You can not use the "json" format if the Serializer is not available. Try running "composer require symfony/serializer".'); + + $serializeProcessor->process($data, $operation->reveal(), $context); + } + + /** @test */ + public function it_does_nothing_if_operation_cannot_be_serialized(): void + { + $request = $this->prophesize(Request::class); + $operation = $this->prophesize(HttpOperation::class); + $data = $this->prophesize(\stdClass::class); + + $context = new Context(new RequestOption($request->reveal())); + + $this->decorated->process($data, $operation, $context)->willReturn($data); + + $request->getRequestFormat()->willReturn('json'); + + $operation->canSerialize()->willReturn(false)->shouldBeCalled(); + + $this->serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldNotBeCalled(); + + $result = $this->serializeProcessor->process($data, $operation->reveal(), $context); + + Assert::eq($result, $data->reveal()); + } +} diff --git a/src/Component/src/Symfony/Serializer/State/SerializeProcessor.php b/src/Component/src/Symfony/Serializer/State/SerializeProcessor.php new file mode 100644 index 000000000..3b91295b4 --- /dev/null +++ b/src/Component/src/Symfony/Serializer/State/SerializeProcessor.php @@ -0,0 +1,59 @@ +decorated->process($data, $operation, $context); + + $request = $context->get(RequestOption::class)?->request(); + + if (null === $request) { + return $data; + } + + /** @var string $format */ + $format = $request->getRequestFormat(); + + if ( + 'html' === $format || + !($operation->canSerialize() ?? true) + ) { + return $data; + } + + if (null === $this->serializer) { + throw new \LogicException(sprintf('You can not use the "%s" format if the Serializer is not available. Try running "composer require symfony/serializer".', $format)); + } + + return $this->serializer->serialize($data, $format, $operation->getNormalizationContext() ?? []); + } +} diff --git a/src/Component/tests/spec/Symfony/EventListener/SerializeListenerSpec.php b/src/Component/tests/spec/Symfony/EventListener/SerializeListenerSpec.php deleted file mode 100644 index 475ecedf3..000000000 --- a/src/Component/tests/spec/Symfony/EventListener/SerializeListenerSpec.php +++ /dev/null @@ -1,207 +0,0 @@ -beConstructedWith($operationInitiator, $serializer); - } - - function it_is_initializable(): void - { - $this->shouldHaveType(SerializeListener::class); - } - - function it_serializes_data_to_the_requested_format( - HttpKernelInterface $kernel, - Request $request, - \stdClass $data, - HttpOperationInitiatorInterface $operationInitiator, - HttpOperation $operation, - SerializerInterface $serializer, - ): void { - $event = new ViewEvent( - $kernel->getWrappedObject(), - $request->getWrappedObject(), - HttpKernelInterface::MAIN_REQUEST, - $data->getWrappedObject(), - ); - - $operationInitiator->initializeOperation($request)->willReturn($operation); - - $request->getRequestFormat()->willReturn('json'); - - $operation->canSerialize()->willReturn(null)->shouldBeCalled(); - $operation->getNormalizationContext()->willReturn([]); - - $serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldBeCalled(); - - $this->onKernelView($event); - - Assert::eq($event->getControllerResult(), 'serialized_data'); - } - - function it_serializes_data_to_the_requested_format_with_normalization_context( - HttpKernelInterface $kernel, - Request $request, - \stdClass $data, - HttpOperationInitiatorInterface $operationInitiator, - HttpOperation $operation, - SerializerInterface $serializer, - ): void { - $event = new ViewEvent( - $kernel->getWrappedObject(), - $request->getWrappedObject(), - HttpKernelInterface::MAIN_REQUEST, - $data->getWrappedObject(), - ); - - $operationInitiator->initializeOperation($request)->willReturn($operation); - - $request->getRequestFormat()->willReturn('json'); - - $operation->canSerialize()->willReturn(null)->shouldBeCalled(); - $operation->getNormalizationContext()->willReturn(['groups' => ['dummy:read']]); - - $serializer->serialize($data, 'json', ['groups' => ['dummy:read']])->willReturn('serialized_data')->shouldBeCalled(); - - $this->onKernelView($event); - - Assert::eq($event->getControllerResult(), 'serialized_data'); - } - - function it_does_nothing_when_operation_is_null( - HttpKernelInterface $kernel, - Request $request, - \stdClass $data, - HttpOperationInitiatorInterface $operationInitiator, - SerializerInterface $serializer, - ): void { - $event = new ViewEvent( - $kernel->getWrappedObject(), - $request->getWrappedObject(), - HttpKernelInterface::MAIN_REQUEST, - $data->getWrappedObject(), - ); - - $operationInitiator->initializeOperation($request)->willReturn(null); - - $request->getRequestFormat()->willReturn('json'); - - $serializer->serialize($data, 'json')->willReturn('serialized_data')->shouldNotBeCalled(); - - $this->onKernelView($event); - - Assert::eq($event->getControllerResult(), $data->getWrappedObject()); - } - - function it_does_nothing_when_format_is_html( - HttpKernelInterface $kernel, - Request $request, - \stdClass $data, - HttpOperationInitiatorInterface $operationInitiator, - HttpOperation $operation, - SerializerInterface $serializer, - ): void { - $event = new ViewEvent( - $kernel->getWrappedObject(), - $request->getWrappedObject(), - HttpKernelInterface::MAIN_REQUEST, - $data->getWrappedObject(), - ); - - $operationInitiator->initializeOperation($request)->willReturn($operation); - - $request->getRequestFormat()->willReturn('html'); - - $serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldNotBeCalled(); - - $this->onKernelView($event); - - Assert::eq($event->getControllerResult(), $data->getWrappedObject()); - } - - function it_throws_an_exception_when_serializer_is_not_available( - HttpKernelInterface $kernel, - Request $request, - \stdClass $data, - HttpOperationInitiatorInterface $operationInitiator, - HttpOperation $operation, - SerializerInterface $serializer, - ): void { - $this->beConstructedWith($operationInitiator, null); - - $event = new ViewEvent( - $kernel->getWrappedObject(), - $request->getWrappedObject(), - HttpKernelInterface::MAIN_REQUEST, - $data->getWrappedObject(), - ); - - $operationInitiator->initializeOperation($request)->willReturn($operation); - - $request->getRequestFormat()->willReturn('json', []); - - $serializer->serialize($data, 'json')->willReturn('serialized_data')->shouldNotBeCalled(); - - $this->shouldThrow(new \LogicException('You can not use the "json" format if the Serializer is not available. Try running "composer require symfony/serializer".')) - ->during( - 'onKernelView', - [$event], - ) - ; - } - - function it_does_nothing_if_operation_cannot_be_serialized( - HttpKernelInterface $kernel, - Request $request, - \stdClass $data, - HttpOperationInitiatorInterface $operationInitiator, - HttpOperation $operation, - SerializerInterface $serializer, - ): void { - $event = new ViewEvent( - $kernel->getWrappedObject(), - $request->getWrappedObject(), - HttpKernelInterface::MAIN_REQUEST, - $data->getWrappedObject(), - ); - - $operationInitiator->initializeOperation($request)->willReturn($operation); - - $request->getRequestFormat()->willReturn('json'); - - $operation->canSerialize()->willReturn(false)->shouldBeCalled(); - - $serializer->serialize($data, 'json', [])->willReturn('serialized_data')->shouldNotBeCalled(); - - $this->onKernelView($event); - - Assert::eq($event->getControllerResult(), $data->getWrappedObject()); - } -}