From 6c8b29f899ad8bfaeb928ad084627b30f4365f9b Mon Sep 17 00:00:00 2001 From: Alan Poulain Date: Sun, 10 Feb 2019 20:33:14 +0100 Subject: [PATCH] Request events Co-authored-by: ArnoudThibaut --- composer.json | 2 +- src/Bridge/FosUser/EventListener.php | 38 ++++- .../EventListener/SwaggerUiListener.php | 23 ++- .../EventSubscriber/EventDispatcher.php | 136 ++++++++++++++++ .../Symfony/Bundle/Resources/config/api.xml | 21 ++- .../Bundle/Resources/config/fos_user.xml | 2 +- .../Bundle/Resources/config/jsonapi.xml | 8 +- .../Bundle/Resources/config/security.xml | 2 +- .../Bundle/Resources/config/swagger-ui.xml | 2 +- .../Bundle/Resources/config/validator.xml | 4 +- .../ValidationExceptionListener.php | 60 +++++-- src/Event/DeserializeEvent.php | 21 +++ src/Event/Event.php | 51 ++++++ src/Event/EventInterface.php | 28 ++++ src/Event/FormatAddEvent.php | 21 +++ src/Event/PostDeserializeEvent.php | 21 +++ src/Event/PostReadEvent.php | 21 +++ src/Event/PostRespondEvent.php | 18 +++ src/Event/PostSerializeEvent.php | 18 +++ src/Event/PostValidateEvent.php | 18 +++ src/Event/PostWriteEvent.php | 18 +++ src/Event/PreDeserializeEvent.php | 21 +++ src/Event/PreReadEvent.php | 21 +++ src/Event/PreRespondEvent.php | 18 +++ src/Event/PreSerializeEvent.php | 18 +++ src/Event/PreValidateEvent.php | 18 +++ src/Event/PreWriteEvent.php | 18 +++ src/Event/QueryParameterValidateEvent.php | 21 +++ src/Event/ReadEvent.php | 21 +++ src/Event/RespondEvent.php | 18 +++ src/Event/SerializeEvent.php | 18 +++ src/Event/ValidateEvent.php | 18 +++ src/Event/ValidationExceptionEvent.php | 18 +++ src/Event/WriteEvent.php | 18 +++ src/EventListener/AddFormatListener.php | 26 +++- src/EventListener/DeserializeListener.php | 23 ++- src/EventListener/ReadListener.php | 27 +++- src/EventListener/RespondListener.php | 36 ++++- src/EventListener/SerializeListener.php | 52 ++++++- src/EventListener/WriteListener.php | 51 +++++- src/Events.php | 49 ++++++ src/Filter/QueryParameterValidateListener.php | 21 ++- .../EventListener/AddLinkHeaderListener.php | 25 ++- .../TransformFieldsetsParametersListener.php | 21 ++- .../TransformFilteringParametersListener.php | 22 ++- .../TransformPaginationParametersListener.php | 21 ++- .../TransformSortingParametersListener.php | 21 ++- .../EventListener/AddLinkHeaderListener.php | 25 ++- .../EventListener/DenyAccessListener.php | 25 ++- .../EventListener/ValidateListener.php | 34 +++- .../ApiPlatformExtensionTest.php | 1 + .../EventListener/SwaggerUiListenerTest.php | 24 ++- .../EventSubscriber/EventDispatcherTest.php | 146 ++++++++++++++++++ .../ValidationExceptionListenerTest.php | 36 ++++- tests/EventListener/AddFormatListenerTest.php | 99 +++++++----- .../EventListener/DeserializeListenerTest.php | 92 ++++++----- tests/EventListener/ReadListenerTest.php | 100 +++++++----- tests/EventListener/RespondListenerTest.php | 107 ++++++------- tests/EventListener/SerializeListenerTest.php | 112 ++++++++------ tests/EventListener/WriteListenerTest.php | 130 +++++++--------- .../QueryParameterValidateListenerTest.php | 53 +++++-- .../AddLinkHeaderListenerTest.php | 23 ++- ...ansformFieldsetsParametersListenerTest.php | 60 ++++--- ...ansformFilteringParametersListenerTest.php | 44 ++++-- ...nsformPaginationParametersListenerTest.php | 44 ++++-- ...TransformSortingParametersListenerTest.php | 44 ++++-- .../AddLinkHeaderListenerTest.php | 32 +++- .../EventListener/DenyAccessListenerTest.php | 79 ++++++---- .../EventListener/ValidateListenerTest.php | 36 +++-- 69 files changed, 2023 insertions(+), 497 deletions(-) create mode 100644 src/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcher.php create mode 100644 src/Event/DeserializeEvent.php create mode 100644 src/Event/Event.php create mode 100644 src/Event/EventInterface.php create mode 100644 src/Event/FormatAddEvent.php create mode 100644 src/Event/PostDeserializeEvent.php create mode 100644 src/Event/PostReadEvent.php create mode 100644 src/Event/PostRespondEvent.php create mode 100644 src/Event/PostSerializeEvent.php create mode 100644 src/Event/PostValidateEvent.php create mode 100644 src/Event/PostWriteEvent.php create mode 100644 src/Event/PreDeserializeEvent.php create mode 100644 src/Event/PreReadEvent.php create mode 100644 src/Event/PreRespondEvent.php create mode 100644 src/Event/PreSerializeEvent.php create mode 100644 src/Event/PreValidateEvent.php create mode 100644 src/Event/PreWriteEvent.php create mode 100644 src/Event/QueryParameterValidateEvent.php create mode 100644 src/Event/ReadEvent.php create mode 100644 src/Event/RespondEvent.php create mode 100644 src/Event/SerializeEvent.php create mode 100644 src/Event/ValidateEvent.php create mode 100644 src/Event/ValidationExceptionEvent.php create mode 100644 src/Event/WriteEvent.php create mode 100644 src/Events.php create mode 100644 tests/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcherTest.php diff --git a/composer.json b/composer.json index bb606055d4b..dc4ba5dbff2 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ "doctrine/inflector": "^1.0", "psr/cache": "^1.0", "psr/container": "^1.0", + "symfony/event-dispatcher": "^3.4 || ^4.0", "symfony/http-foundation": "^3.4 || ^4.0", "symfony/http-kernel": "^3.4 || ^4.0", "symfony/property-access": "^3.4 || ^4.0", @@ -61,7 +62,6 @@ "symfony/dependency-injection": "^3.4 || ^4.0", "symfony/doctrine-bridge": "^3.4 || ^4.0", "symfony/dom-crawler": "^3.4 || ^4.0", - "symfony/event-dispatcher": "^3.4 || ^4.0", "symfony/expression-language": "^3.4 || ^4.0", "symfony/finder": "^3.4 || ^4.0", "symfony/form": "^3.4 || ^4.0", diff --git a/src/Bridge/FosUser/EventListener.php b/src/Bridge/FosUser/EventListener.php index 75c88ea2bc4..3108056a634 100644 --- a/src/Bridge/FosUser/EventListener.php +++ b/src/Bridge/FosUser/EventListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Bridge\FosUser; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; use FOS\UserBundle\Model\UserInterface; use FOS\UserBundle\Model\UserManagerInterface; @@ -35,22 +36,53 @@ public function __construct(UserManagerInterface $userManager) /** * Persists, updates or delete data return by the controller if applicable. + * + * @deprecated since version 2.5, to bo removed in 3.0 */ public function onKernelView(GetResponseForControllerResultEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Persists, updates or delete data return by the controller if applicable. + */ + public function handleEvent(/* EventInterface */ $event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseForControllerResultEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseForControllerResultEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + if (!RequestAttributesExtractor::extractAttributes($request)) { return; } - $user = $event->getControllerResult(); + if ($event instanceof EventInterface) { + $user = $event->getData(); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $user = $event->getControllerResult(); + } else { + return; + } if (!$user instanceof UserInterface || $request->isMethodSafe(false)) { return; } if ('DELETE' === $request->getMethod()) { $this->userManager->deleteUser($user); - $event->setControllerResult(null); + if ($event instanceof EventInterface) { + $event->setData(null); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult(null); + } } else { $this->userManager->updateUser($user); } diff --git a/src/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php b/src/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php index 32c9320813b..d465f066327 100644 --- a/src/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php +++ b/src/Bridge/Symfony/Bundle/EventListener/SwaggerUiListener.php @@ -13,16 +13,37 @@ namespace ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener; +use ApiPlatform\Core\Event\EventInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; final class SwaggerUiListener { /** * Sets SwaggerUiAction as controller if the requested format is HTML. + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Sets SwaggerUiAction as controller if the requested format is HTML. + */ + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } if ( 'html' !== $request->getRequestFormat('') || (!$request->attributes->has('_api_resource_class') && !$request->attributes->has('_api_respond')) diff --git a/src/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcher.php b/src/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcher.php new file mode 100644 index 00000000000..f251c8f73f6 --- /dev/null +++ b/src/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcher.php @@ -0,0 +1,136 @@ + + * + * 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\Core\Bridge\Symfony\Bundle\EventSubscriber; + +use ApiPlatform\Core\Event\DeserializeEvent; +use ApiPlatform\Core\Event\Event as ApiPlatformEvent; +use ApiPlatform\Core\Event\FormatAddEvent; +use ApiPlatform\Core\Event\PostDeserializeEvent; +use ApiPlatform\Core\Event\PostReadEvent; +use ApiPlatform\Core\Event\PostRespondEvent; +use ApiPlatform\Core\Event\PostSerializeEvent; +use ApiPlatform\Core\Event\PostValidateEvent; +use ApiPlatform\Core\Event\PostWriteEvent; +use ApiPlatform\Core\Event\PreDeserializeEvent; +use ApiPlatform\Core\Event\PreReadEvent; +use ApiPlatform\Core\Event\PreRespondEvent; +use ApiPlatform\Core\Event\PreSerializeEvent; +use ApiPlatform\Core\Event\PreValidateEvent; +use ApiPlatform\Core\Event\PreWriteEvent; +use ApiPlatform\Core\Event\QueryParameterValidateEvent; +use ApiPlatform\Core\Event\ReadEvent; +use ApiPlatform\Core\Event\RespondEvent; +use ApiPlatform\Core\Event\SerializeEvent; +use ApiPlatform\Core\Event\ValidateEvent; +use ApiPlatform\Core\Event\ValidationExceptionEvent; +use ApiPlatform\Core\Event\WriteEvent; +use ApiPlatform\Core\Events; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * @internal + * + * @author Alan Poulain + */ +final class EventDispatcher implements EventSubscriberInterface +{ + private const INTERNAL_EVENTS_CONFIGURATION = [ + KernelEvents::REQUEST => [ + QueryParameterValidateEvent::class => Events::QUERY_PARAMETER_VALIDATE, + FormatAddEvent::class => Events::FORMAT_ADD, + + PreReadEvent::class => Events::PRE_READ, + ReadEvent::class => Events::READ, + PostReadEvent::class => Events::POST_READ, + + PreDeserializeEvent::class => Events::PRE_DESERIALIZE, + DeserializeEvent::class => Events::DESERIALIZE, + PostDeserializeEvent::class => Events::POST_DESERIALIZE, + ], + KernelEvents::VIEW => [ + PreValidateEvent::class => Events::PRE_VALIDATE, + ValidateEvent::class => Events::VALIDATE, + PostValidateEvent::class => Events::POST_VALIDATE, + + PreWriteEvent::class => Events::PRE_WRITE, + WriteEvent::class => Events::WRITE, + PostWriteEvent::class => Events::POST_WRITE, + + PreSerializeEvent::class => Events::PRE_SERIALIZE, + SerializeEvent::class => Events::SERIALIZE, + PostSerializeEvent::class => Events::POST_SERIALIZE, + + PreRespondEvent::class => Events::PRE_RESPOND, + RespondEvent::class => Events::RESPOND, + PostRespondEvent::class => Events::POST_RESPOND, // @todo kernel.response + ], + KernelEvents::EXCEPTION => [ + ValidationExceptionEvent::class => Events::VALIDATE_EXCEPTION, + ], + ]; + + private $dispatcher; + + public function __construct(EventDispatcherInterface $dispatcher) + { + $this->dispatcher = $dispatcher; + } + + public static function getSubscribedEvents(): array + { + return [ + KernelEvents::REQUEST => 'dispatch', + KernelEvents::VIEW => 'dispatch', + ]; + } + + public function dispatch(Event $event, string $eventName): void + { + $internalEventData = null; + $internalEventContext = []; + + // case order is important because of Symfony events inheritance + switch (true) { + case $event instanceof GetResponseForControllerResultEvent: + $internalEventData = $event->getControllerResult(); + $internalEventContext = ['request' => $event->getRequest()]; + break; + case $event instanceof GetResponseForExceptionEvent: + $internalEventContext = ['request' => $event->getRequest(), 'exception' => $event->getException()]; + break; + case $event instanceof GetResponseEvent: + $internalEventContext = ['request' => $event->getRequest()]; + break; + } + + foreach (self::INTERNAL_EVENTS_CONFIGURATION[$eventName] as $internalEventClass => $internalEventName) { + /** @var ApiPlatformEvent $internalEvent */ + $internalEvent = new $internalEventClass($internalEventData, $internalEventContext); + + $this->dispatcher->dispatch($internalEventName, $internalEvent); + + $internalEventData = $internalEvent->getData(); + // @todo set controller result? + if ($event instanceof GetResponseEvent && $response = $internalEvent->getContext()['response']) { + $event->setResponse($response); + } + } + } +} diff --git a/src/Bridge/Symfony/Bundle/Resources/config/api.xml b/src/Bridge/Symfony/Bundle/Resources/config/api.xml index b9a7824fe15..feb7d3c55b5 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/api.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/api.xml @@ -138,14 +138,21 @@ + + + + + + + + - - + @@ -155,7 +162,7 @@ - + @@ -163,7 +170,7 @@ - + @@ -171,19 +178,19 @@ - + - + - + diff --git a/src/Bridge/Symfony/Bundle/Resources/config/fos_user.xml b/src/Bridge/Symfony/Bundle/Resources/config/fos_user.xml index 30c0141e64a..9b2ca5216f0 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/fos_user.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/fos_user.xml @@ -8,7 +8,7 @@ - + diff --git a/src/Bridge/Symfony/Bundle/Resources/config/jsonapi.xml b/src/Bridge/Symfony/Bundle/Resources/config/jsonapi.xml index 5d71ec29369..0ea2b8b9f95 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/jsonapi.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/jsonapi.xml @@ -63,22 +63,22 @@ - + %api_platform.collection.order_parameter_name% - + - + - + diff --git a/src/Bridge/Symfony/Bundle/Resources/config/security.xml b/src/Bridge/Symfony/Bundle/Resources/config/security.xml index e04314ff5fc..91bde4e262a 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/security.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/security.xml @@ -21,7 +21,7 @@ - + diff --git a/src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml b/src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml index 753184f1fa2..be8abf92878 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/swagger-ui.xml @@ -7,7 +7,7 @@ - + diff --git a/src/Bridge/Symfony/Bundle/Resources/config/validator.xml b/src/Bridge/Symfony/Bundle/Resources/config/validator.xml index d34dcd8cfe6..1f3a3320167 100644 --- a/src/Bridge/Symfony/Bundle/Resources/config/validator.xml +++ b/src/Bridge/Symfony/Bundle/Resources/config/validator.xml @@ -20,14 +20,14 @@ - + - + diff --git a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php index 0a1f1dfcedf..4acd68cca1e 100644 --- a/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php +++ b/src/Bridge/Symfony/Validator/EventListener/ValidationExceptionListener.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Bridge\Symfony\Validator\EventListener; use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Util\ErrorFormatGuesser; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; @@ -37,24 +38,59 @@ public function __construct(SerializerInterface $serializer, array $errorFormats /** * Returns a list of violations normalized in the Hydra format. + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelException(GetResponseForExceptionEvent $event) { - $exception = $event->getException(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Returns a list of violations normalized in the Hydra format. + */ + public function handleEvent(/* EventInterface */ $event) + { + if ($event instanceof EventInterface) { + $exception = $event->getContext()['exception']; + } elseif ($event instanceof GetResponseForExceptionEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseForExceptionEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $exception = $event->getException(); + } else { + return; + } + if (!$exception instanceof ValidationException) { return; } - $format = ErrorFormatGuesser::guessErrorFormat($event->getRequest(), $this->errorFormats); - - $event->setResponse(new Response( - $this->serializer->serialize($exception->getConstraintViolationList(), $format['key']), - Response::HTTP_BAD_REQUEST, - [ - 'Content-Type' => sprintf('%s; charset=utf-8', $format['value'][0]), - 'X-Content-Type-Options' => 'nosniff', - 'X-Frame-Options' => 'deny', - ] - )); + if ($event instanceof GetResponseForExceptionEvent) { + $request = $event->getRequest(); + } elseif ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } else { + return; + } + + $format = ErrorFormatGuesser::guessErrorFormat($request, $this->errorFormats); + + $response = new Response( + $this->serializer->serialize($exception->getConstraintViolationList(), $format['key']), + Response::HTTP_BAD_REQUEST, + [ + 'Content-Type' => sprintf('%s; charset=utf-8', $format['value'][0]), + 'X-Content-Type-Options' => 'nosniff', + 'X-Frame-Options' => 'deny', + ] + ); + + if ($event instanceof EventInterface) { + $event->setData($response); + } elseif ($event instanceof GetResponseForExceptionEvent) { + $event->setResponse($response); + } } } diff --git a/src/Event/DeserializeEvent.php b/src/Event/DeserializeEvent.php new file mode 100644 index 00000000000..f255c337c80 --- /dev/null +++ b/src/Event/DeserializeEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class DeserializeEvent extends Event +{ +} diff --git a/src/Event/Event.php b/src/Event/Event.php new file mode 100644 index 00000000000..2f562983523 --- /dev/null +++ b/src/Event/Event.php @@ -0,0 +1,51 @@ + + * + * 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\Core\Event; + +use Symfony\Component\EventDispatcher\Event as BaseEvent; + +/** + * @author Alan Poulain + */ +abstract class Event extends BaseEvent implements EventInterface +{ + private $data; + private $context; + + public function __construct($data, array $context = []) + { + $this->data = $data; + $this->context = $context; + } + + public function getData() + { + return $this->data; + } + + public function setData($data): void + { + $this->data = $data; + } + + public function getContext(): array + { + return $this->context; + } + + public function setContext(array $context): void + { + $this->context = $context; + } +} diff --git a/src/Event/EventInterface.php b/src/Event/EventInterface.php new file mode 100644 index 00000000000..e61e2979e65 --- /dev/null +++ b/src/Event/EventInterface.php @@ -0,0 +1,28 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +interface EventInterface +{ + public function getData(); + + public function setData($data): void; + + public function getContext(): array; + + public function setContext(array $context): void; +} diff --git a/src/Event/FormatAddEvent.php b/src/Event/FormatAddEvent.php new file mode 100644 index 00000000000..9cc669f19cd --- /dev/null +++ b/src/Event/FormatAddEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class FormatAddEvent extends Event +{ +} diff --git a/src/Event/PostDeserializeEvent.php b/src/Event/PostDeserializeEvent.php new file mode 100644 index 00000000000..8ed5eab7c16 --- /dev/null +++ b/src/Event/PostDeserializeEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class PostDeserializeEvent extends Event +{ +} diff --git a/src/Event/PostReadEvent.php b/src/Event/PostReadEvent.php new file mode 100644 index 00000000000..0f57273f6ed --- /dev/null +++ b/src/Event/PostReadEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class PostReadEvent extends Event +{ +} diff --git a/src/Event/PostRespondEvent.php b/src/Event/PostRespondEvent.php new file mode 100644 index 00000000000..43ac40f51b2 --- /dev/null +++ b/src/Event/PostRespondEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PostRespondEvent extends Event +{ +} diff --git a/src/Event/PostSerializeEvent.php b/src/Event/PostSerializeEvent.php new file mode 100644 index 00000000000..3184fe084cf --- /dev/null +++ b/src/Event/PostSerializeEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PostSerializeEvent extends Event +{ +} diff --git a/src/Event/PostValidateEvent.php b/src/Event/PostValidateEvent.php new file mode 100644 index 00000000000..05d0a95da97 --- /dev/null +++ b/src/Event/PostValidateEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PostValidateEvent extends Event +{ +} diff --git a/src/Event/PostWriteEvent.php b/src/Event/PostWriteEvent.php new file mode 100644 index 00000000000..90231f85662 --- /dev/null +++ b/src/Event/PostWriteEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PostWriteEvent extends Event +{ +} diff --git a/src/Event/PreDeserializeEvent.php b/src/Event/PreDeserializeEvent.php new file mode 100644 index 00000000000..564aba328c0 --- /dev/null +++ b/src/Event/PreDeserializeEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class PreDeserializeEvent extends Event +{ +} diff --git a/src/Event/PreReadEvent.php b/src/Event/PreReadEvent.php new file mode 100644 index 00000000000..36ff15c0cbc --- /dev/null +++ b/src/Event/PreReadEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class PreReadEvent extends Event +{ +} diff --git a/src/Event/PreRespondEvent.php b/src/Event/PreRespondEvent.php new file mode 100644 index 00000000000..6cb18b94027 --- /dev/null +++ b/src/Event/PreRespondEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PreRespondEvent extends Event +{ +} diff --git a/src/Event/PreSerializeEvent.php b/src/Event/PreSerializeEvent.php new file mode 100644 index 00000000000..c57b18d3c7e --- /dev/null +++ b/src/Event/PreSerializeEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PreSerializeEvent extends Event +{ +} diff --git a/src/Event/PreValidateEvent.php b/src/Event/PreValidateEvent.php new file mode 100644 index 00000000000..0bc7cbc409e --- /dev/null +++ b/src/Event/PreValidateEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PreValidateEvent extends Event +{ +} diff --git a/src/Event/PreWriteEvent.php b/src/Event/PreWriteEvent.php new file mode 100644 index 00000000000..1a70f390ba8 --- /dev/null +++ b/src/Event/PreWriteEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class PreWriteEvent extends Event +{ +} diff --git a/src/Event/QueryParameterValidateEvent.php b/src/Event/QueryParameterValidateEvent.php new file mode 100644 index 00000000000..e96441df823 --- /dev/null +++ b/src/Event/QueryParameterValidateEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class QueryParameterValidateEvent extends Event +{ +} diff --git a/src/Event/ReadEvent.php b/src/Event/ReadEvent.php new file mode 100644 index 00000000000..ab59fb0b801 --- /dev/null +++ b/src/Event/ReadEvent.php @@ -0,0 +1,21 @@ + + * + * 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\Core\Event; + +/** + * @author Alan Poulain + */ +final class ReadEvent extends Event +{ +} diff --git a/src/Event/RespondEvent.php b/src/Event/RespondEvent.php new file mode 100644 index 00000000000..1f50652d16f --- /dev/null +++ b/src/Event/RespondEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class RespondEvent extends Event +{ +} diff --git a/src/Event/SerializeEvent.php b/src/Event/SerializeEvent.php new file mode 100644 index 00000000000..8bccf994bd0 --- /dev/null +++ b/src/Event/SerializeEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class SerializeEvent extends Event +{ +} diff --git a/src/Event/ValidateEvent.php b/src/Event/ValidateEvent.php new file mode 100644 index 00000000000..3251d9f35ed --- /dev/null +++ b/src/Event/ValidateEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class ValidateEvent extends Event +{ +} diff --git a/src/Event/ValidationExceptionEvent.php b/src/Event/ValidationExceptionEvent.php new file mode 100644 index 00000000000..b2f2d5209fe --- /dev/null +++ b/src/Event/ValidationExceptionEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class ValidationExceptionEvent extends Event +{ +} diff --git a/src/Event/WriteEvent.php b/src/Event/WriteEvent.php new file mode 100644 index 00000000000..e946709397e --- /dev/null +++ b/src/Event/WriteEvent.php @@ -0,0 +1,18 @@ + + * + * 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\Core\Event; + +final class WriteEvent extends Event +{ +} diff --git a/src/EventListener/AddFormatListener.php b/src/EventListener/AddFormatListener.php index 72e53713dda..ff1640f6256 100644 --- a/src/EventListener/AddFormatListener.php +++ b/src/EventListener/AddFormatListener.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Api\FormatMatcher; use ApiPlatform\Core\Api\FormatsProviderInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Util\RequestAttributesExtractor; use Negotiation\Negotiator; @@ -59,10 +60,33 @@ public function __construct(Negotiator $negotiator, /* FormatsProviderInterface * * @throws NotFoundHttpException * @throws NotAcceptableHttpException + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Sets the applicable format to the HttpFoundation Request. + * + * @throws NotFoundHttpException + * @throws NotAcceptableHttpException + */ + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } if (!$request->attributes->has('_api_resource_class') && !$request->attributes->has('_api_respond') && !$request->attributes->has('_graphql')) { return; } diff --git a/src/EventListener/DeserializeListener.php b/src/EventListener/DeserializeListener.php index 206174fe08d..c547af0afcf 100644 --- a/src/EventListener/DeserializeListener.php +++ b/src/EventListener/DeserializeListener.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Api\FormatMatcher; use ApiPlatform\Core\Api\FormatsProviderInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Exception\InvalidArgumentException; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; @@ -58,10 +59,30 @@ public function __construct(SerializerInterface $serializer, SerializerContextBu /** * Deserializes the data sent in the requested format. + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Deserializes the data sent in the requested format. + */ + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } $method = $request->getMethod(); if ( diff --git a/src/EventListener/ReadListener.php b/src/EventListener/ReadListener.php index 80fb62d439f..275478ceddb 100644 --- a/src/EventListener/ReadListener.php +++ b/src/EventListener/ReadListener.php @@ -17,13 +17,13 @@ use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\OperationDataProviderTrait; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Exception\InvalidIdentifierException; use ApiPlatform\Core\Exception\RuntimeException; use ApiPlatform\Core\Identifier\IdentifierConverterInterface; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; use ApiPlatform\Core\Util\RequestParser; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; @@ -51,10 +51,33 @@ public function __construct(CollectionDataProviderInterface $collectionDataProvi * Calls the data provider and sets the data attribute. * * @throws NotFoundHttpException + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Calls the data provider and sets the data attribute. + * + * @throws NotFoundHttpException + */ + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + if ( !($attributes = RequestAttributesExtractor::extractAttributes($request)) || !$attributes['receive'] diff --git a/src/EventListener/RespondListener.php b/src/EventListener/RespondListener.php index d78844c2b1f..6ba752c41a6 100644 --- a/src/EventListener/RespondListener.php +++ b/src/EventListener/RespondListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; use Symfony\Component\HttpFoundation\Response; @@ -39,11 +40,32 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa /** * Creates a Response to send to the client according to the requested format. + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelView(GetResponseForControllerResultEvent $event) { - $controllerResult = $event->getControllerResult(); - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Creates a Response to send to the client according to the requested format. + */ + public function handleEvent(/* EventInterface */ $event) + { + if ($event instanceof EventInterface) { + $controllerResult = $event->getData(); + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseForControllerResultEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseForControllerResultEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $controllerResult = $event->getControllerResult(); + $request = $event->getRequest(); + } else { + return; + } if ($controllerResult instanceof Response || !$request->attributes->getBoolean('_api_respond', true)) { return; @@ -75,10 +97,16 @@ public function onKernelView(GetResponseForControllerResultEvent $event) $status = $resourceMetadata->getOperationAttribute($attributes, 'status'); } - $event->setResponse(new Response( + $response = new Response( $controllerResult, $status ?? self::METHOD_TO_CODE[$request->getMethod()] ?? Response::HTTP_OK, $headers - )); + ); + + if ($event instanceof EventInterface) { + $event->setContext($event->getContext() + ['response' => $response]); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setResponse($response); + } } } diff --git a/src/EventListener/SerializeListener.php b/src/EventListener/SerializeListener.php index 50d6dd45fba..4883156e6cc 100644 --- a/src/EventListener/SerializeListener.php +++ b/src/EventListener/SerializeListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Exception\RuntimeException; use ApiPlatform\Core\Serializer\ResourceList; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; @@ -43,11 +44,32 @@ public function __construct(SerializerInterface $serializer, SerializerContextBu /** * Serializes the data to the requested format. + * + * @deprecated The method ApiPlatform\Core\EventListener\SerializeListener::onKernelView() is deprecated since 2.5 and will be removed in 3.0. */ public function onKernelView(GetResponseForControllerResultEvent $event) { - $controllerResult = $event->getControllerResult(); - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Serializes the data to the requested format. + */ + public function handleEvent(/* EventInterface */ $event) + { + if ($event instanceof EventInterface) { + $controllerResult = $event->getData(); + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseForControllerResultEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseForControllerResultEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $controllerResult = $event->getControllerResult(); + $request = $event->getRequest(); + } else { + return; + } if ($controllerResult instanceof Response || !$request->attributes->getBoolean('_api_respond', true)) { return; @@ -63,7 +85,11 @@ public function onKernelView(GetResponseForControllerResultEvent $event) $context = $this->serializerContextBuilder->createFromRequest($request, true, $attributes); if (isset($context['output']) && \array_key_exists('class', $context['output']) && null === $context['output']['class']) { - $event->setControllerResult(''); + if ($event instanceof EventInterface) { + $event->setData(''); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult(''); + } return; } @@ -79,7 +105,11 @@ public function onKernelView(GetResponseForControllerResultEvent $event) $request->attributes->set('_api_normalization_context', $context); - $event->setControllerResult($this->serializer->serialize($controllerResult, $request->getRequestFormat(), $context)); + if ($event instanceof EventInterface) { + $event->setData($this->serializer->serialize($controllerResult, $request->getRequestFormat(), $context)); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult($this->serializer->serialize($controllerResult, $request->getRequestFormat(), $context)); + } $request->attributes->set('_resources', $request->attributes->get('_resources', []) + (array) $resources); if (!\count($resourcesToPush)) { @@ -100,10 +130,14 @@ public function onKernelView(GetResponseForControllerResultEvent $event) * * @throws RuntimeException */ - private function serializeRawData(GetResponseForControllerResultEvent $event, Request $request, $controllerResult) + private function serializeRawData(/* EventInterface */ $event, Request $request, $controllerResult) { if (\is_object($controllerResult)) { - $event->setControllerResult($this->serializer->serialize($controllerResult, $request->getRequestFormat(), $request->attributes->get('_api_normalization_context', []))); + if ($event instanceof EventInterface) { + $event->setData($this->serializer->serialize($controllerResult, $request->getRequestFormat(), $request->attributes->get('_api_normalization_context', []))); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult($this->serializer->serialize($controllerResult, $request->getRequestFormat(), $request->attributes->get('_api_normalization_context', []))); + } return; } @@ -112,6 +146,10 @@ private function serializeRawData(GetResponseForControllerResultEvent $event, Re throw new RuntimeException(sprintf('The serializer instance must implements the "%s" interface.', EncoderInterface::class)); } - $event->setControllerResult($this->serializer->encode($controllerResult, $request->getRequestFormat())); + if ($event instanceof EventInterface) { + $event->setData($this->serializer->encode($controllerResult, $request->getRequestFormat())); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult($this->serializer->encode($controllerResult, $request->getRequestFormat())); + } } } diff --git a/src/EventListener/WriteListener.php b/src/EventListener/WriteListener.php index 4888053bd88..e3a2f5475d4 100644 --- a/src/EventListener/WriteListener.php +++ b/src/EventListener/WriteListener.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\DataPersister\DataPersisterInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; @@ -40,15 +41,43 @@ public function __construct(DataPersisterInterface $dataPersister, IriConverterI /** * Persists, updates or delete data return by the controller if applicable. + * + * @deprecated since version 2.5, to bo removed in 3.0 */ public function onKernelView(GetResponseForControllerResultEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Persists, updates or delete data return by the controller if applicable. + */ + public function handleEvent(/* EventInterface */ $event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseForControllerResultEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseForControllerResultEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + if ($request->isMethodSafe(false) || !$request->attributes->getBoolean('_api_persist', true) || !$attributes = RequestAttributesExtractor::extractAttributes($request)) { return; } - $controllerResult = $event->getControllerResult(); + if ($event instanceof EventInterface) { + $controllerResult = $event->getData(); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $controllerResult = $event->getControllerResult(); + } else { + return; + } + if (!$this->dataPersister->supports($controllerResult)) { return; } @@ -62,8 +91,13 @@ public function onKernelView(GetResponseForControllerResultEvent $event) if (null === $persistResult) { @trigger_error(sprintf('Returning void from %s::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3, an object should always be returned.', DataPersisterInterface::class), E_USER_DEPRECATED); } + $result = $persistResult ?? $controllerResult; - $event->setControllerResult($persistResult ?? $controllerResult); + if ($event instanceof EventInterface) { + $event->setData($result); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult($result); + } if (null === $this->iriConverter) { return; @@ -79,10 +113,17 @@ public function onKernelView(GetResponseForControllerResultEvent $event) if ($hasOutput) { $request->attributes->set('_api_write_item_iri', $this->iriConverter->getIriFromItem($controllerResult)); } - break; + + break; case 'DELETE': $this->dataPersister->remove($controllerResult); - $event->setControllerResult(null); + + if ($event instanceof EventInterface) { + $event->setData(null); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $event->setControllerResult(null); + } + break; } } diff --git a/src/Events.php b/src/Events.php new file mode 100644 index 00000000000..8bff0ade13e --- /dev/null +++ b/src/Events.php @@ -0,0 +1,49 @@ + + * + * 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\Core; + +/** + * @author Alan Poulain + */ +final class Events +{ + public const QUERY_PARAMETER_VALIDATE = 'api_platform.query_parameter_validate'; + public const FORMAT_ADD = 'api_platform.format_add'; + + public const PRE_READ = 'api_platform.pre_read'; + public const READ = 'api_platform.read'; + public const POST_READ = 'api_platform.post_read'; + + public const PRE_DESERIALIZE = 'api_platform.pre_deserialize'; + public const DESERIALIZE = 'api_platform.deserialize'; + public const POST_DESERIALIZE = 'api_platform.post_deserialize'; + + public const PRE_VALIDATE = 'api_platform.pre_validate'; + public const VALIDATE = 'api_platform.validate'; + public const POST_VALIDATE = 'api_platform.post_validate'; + + public const PRE_WRITE = 'api_platform.pre_write'; + public const WRITE = 'api_platform.write'; + public const POST_WRITE = 'api_platform.post_write'; + + public const PRE_SERIALIZE = 'api_platform.pre_serialize'; + public const SERIALIZE = 'api_platform.serialize'; + public const POST_SERIALIZE = 'api_platform.post_serialize'; + + public const PRE_RESPOND = 'api_platform.pre_respond'; + public const RESPOND = 'api_platform.respond'; + public const POST_RESPOND = 'api_platform.post_respond'; + + public const VALIDATE_EXCEPTION = 'api_platform.validate_exception'; +} diff --git a/src/Filter/QueryParameterValidateListener.php b/src/Filter/QueryParameterValidateListener.php index ffb919a69fd..7445eee8a2f 100644 --- a/src/Filter/QueryParameterValidateListener.php +++ b/src/Filter/QueryParameterValidateListener.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Filter; use ApiPlatform\Core\Api\FilterLocatorTrait; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Exception\FilterValidationException; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; @@ -38,9 +39,27 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa $this->setFilterLocator($filterLocator); } + /** + * @deprecated since version 2.5, to be removed in 3.0. + */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } if ( !$request->isMethodSafe(false) || !($attributes = RequestAttributesExtractor::extractAttributes($request)) diff --git a/src/Hydra/EventListener/AddLinkHeaderListener.php b/src/Hydra/EventListener/AddLinkHeaderListener.php index 81be5408e33..49e791a123a 100644 --- a/src/Hydra/EventListener/AddLinkHeaderListener.php +++ b/src/Hydra/EventListener/AddLinkHeaderListener.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Hydra\EventListener; use ApiPlatform\Core\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\JsonLd\ContextBuilder; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; @@ -35,13 +36,35 @@ public function __construct(UrlGeneratorInterface $urlGenerator) /** * Sends the Hydra header on each response. + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelResponse(FilterResponseEvent $event) + { + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Sends the Hydra header on each response. + */ + public function handleEvent(/* EventInterface */ $event) { $apiDocUrl = $this->urlGenerator->generate('api_doc', ['_format' => 'jsonld'], UrlGeneratorInterface::ABS_URL); $link = new Link(ContextBuilder::HYDRA_NS.'apiDocumentation', $apiDocUrl); - $attributes = $event->getRequest()->attributes; + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof FilterResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', FilterResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + + $attributes = $request->attributes; if (null === $linkProvider = $attributes->get('_links')) { $attributes->set('_links', new GenericLinkProvider([$link])); diff --git a/src/JsonApi/EventListener/TransformFieldsetsParametersListener.php b/src/JsonApi/EventListener/TransformFieldsetsParametersListener.php index 941c7d9bf73..79216beee7e 100644 --- a/src/JsonApi/EventListener/TransformFieldsetsParametersListener.php +++ b/src/JsonApi/EventListener/TransformFieldsetsParametersListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -31,9 +32,27 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa $this->resourceMetadataFactory = $resourceMetadataFactory; } + /** + * @deprecated since version 2.5, to be removed in 3.0. + */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } $includeParameter = $request->query->get('include'); if ( diff --git a/src/JsonApi/EventListener/TransformFilteringParametersListener.php b/src/JsonApi/EventListener/TransformFilteringParametersListener.php index 91ca94248b0..d484209fd74 100644 --- a/src/JsonApi/EventListener/TransformFilteringParametersListener.php +++ b/src/JsonApi/EventListener/TransformFilteringParametersListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** @@ -24,9 +25,28 @@ */ final class TransformFilteringParametersListener { + /** + * @deprecated since version 2.5, to be removed in 3.0. + */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + if ( 'jsonapi' !== $request->getRequestFormat() || null === ($filters = $request->query->get('filter')) || diff --git a/src/JsonApi/EventListener/TransformPaginationParametersListener.php b/src/JsonApi/EventListener/TransformPaginationParametersListener.php index 7bce05b9640..5a11cd7d76a 100644 --- a/src/JsonApi/EventListener/TransformPaginationParametersListener.php +++ b/src/JsonApi/EventListener/TransformPaginationParametersListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** @@ -24,9 +25,27 @@ */ final class TransformPaginationParametersListener { + /** + * @deprecated since version 2.5, to be removed in 3.0. + */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } if ( 'jsonapi' !== $request->getRequestFormat() || diff --git a/src/JsonApi/EventListener/TransformSortingParametersListener.php b/src/JsonApi/EventListener/TransformSortingParametersListener.php index 7bb5f154a7b..849062c6fc6 100644 --- a/src/JsonApi/EventListener/TransformSortingParametersListener.php +++ b/src/JsonApi/EventListener/TransformSortingParametersListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use Symfony\Component\HttpKernel\Event\GetResponseEvent; /** @@ -31,9 +32,27 @@ public function __construct(string $orderParameterName = 'order') $this->orderParameterName = $orderParameterName; } + /** + * @deprecated since version 2.5, to be removed in 3.0. + */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } if ( 'jsonapi' !== $request->getRequestFormat() || diff --git a/src/Mercure/EventListener/AddLinkHeaderListener.php b/src/Mercure/EventListener/AddLinkHeaderListener.php index 48f1f7d25e2..c715f8d4583 100644 --- a/src/Mercure/EventListener/AddLinkHeaderListener.php +++ b/src/Mercure/EventListener/AddLinkHeaderListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Mercure\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; @@ -36,12 +37,34 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa /** * Sends the Mercure header on each response. + * + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelResponse(FilterResponseEvent $event) + { + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Sends the Mercure header on each response. + */ + public function handleEvent(/* EventInterface */ $event) { $link = new Link('mercure', $this->hub); - $attributes = $event->getRequest()->attributes; + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof FilterResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', FilterResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + + $attributes = $request->attributes; if ( null === ($resourceClass = $attributes->get('_api_resource_class')) || false === $this->resourceMetadataFactory->create($resourceClass)->getAttribute('mercure', false) diff --git a/src/Security/EventListener/DenyAccessListener.php b/src/Security/EventListener/DenyAccessListener.php index f9ee41b8b3d..247a8fbdd10 100644 --- a/src/Security/EventListener/DenyAccessListener.php +++ b/src/Security/EventListener/DenyAccessListener.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Security\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Security\ExpressionLanguage; use ApiPlatform\Core\Security\ResourceAccessChecker; @@ -52,11 +53,31 @@ public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFa /** * Sets the applicable format to the HttpFoundation Request. * - * @throws AccessDeniedException + * @deprecated since version 2.5, to be removed in 3.0. */ public function onKernelRequest(GetResponseEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Sets the applicable format to the HttpFoundation Request. + * + * @throws AccessDeniedException + */ + public function handleEvent(/*EventInterface */$event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } if (!$attributes = RequestAttributesExtractor::extractAttributes($request)) { return; } diff --git a/src/Validator/EventListener/ValidateListener.php b/src/Validator/EventListener/ValidateListener.php index 5bf3afd3485..1f90c82b432 100644 --- a/src/Validator/EventListener/ValidateListener.php +++ b/src/Validator/EventListener/ValidateListener.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Validator\EventListener; use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Util\RequestAttributesExtractor; use ApiPlatform\Core\Validator\ValidatorInterface; @@ -39,10 +40,33 @@ public function __construct(ValidatorInterface $validator, ResourceMetadataFacto * Validates data returned by the controller if applicable. * * @throws ValidationException + * + * @deprecated since version 2.5, to bo removed in 3.0 */ public function onKernelView(GetResponseForControllerResultEvent $event) { - $request = $event->getRequest(); + @trigger_error(sprintf('The method %s() is deprecated since 2.5 and will be removed in 3.0.', __METHOD__), E_USER_DEPRECATED); + + $this->handleEvent($event); + } + + /** + * Validates data returned by the controller if applicable. + * + * @throws ValidationException + */ + public function handleEvent(/* EventInterface */ $event) + { + if ($event instanceof EventInterface) { + $request = $event->getContext()['request']; + } elseif ($event instanceof GetResponseForControllerResultEvent) { + @trigger_error(sprintf('Passing an instance of "%s" as argument of "%s" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "%s" instead.', GetResponseForControllerResultEvent::class, __METHOD__, EventInterface::class), E_USER_DEPRECATED); + + $request = $event->getRequest(); + } else { + return; + } + if ( $request->isMethodSafe(false) || $request->isMethod('DELETE') @@ -52,7 +76,13 @@ public function onKernelView(GetResponseForControllerResultEvent $event) return; } - $data = $event->getControllerResult(); + if ($event instanceof EventInterface) { + $data = $event->getData(); + } elseif ($event instanceof GetResponseForControllerResultEvent) { + $data = $event->getControllerResult(); + } else { + return; + } $resourceMetadata = $this->resourceMetadataFactory->create($attributes['resource_class']); $validationGroups = $resourceMetadata->getOperationAttribute($attributes, 'validation_groups', null, true); diff --git a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php index d53ea870d12..109dfab8034 100644 --- a/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php +++ b/tests/Bridge/Symfony/Bundle/DependencyInjection/ApiPlatformExtensionTest.php @@ -739,6 +739,7 @@ private function getPartialContainerBuilderProphecy() 'api_platform.identifiers_extractor', 'api_platform.identifiers_extractor.cached', 'api_platform.item_data_provider', + 'api_platform.dispatcher.internal_events', 'api_platform.listener.exception', 'api_platform.listener.exception.validation', 'api_platform.listener.request.add_format', diff --git a/tests/Bridge/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php b/tests/Bridge/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php index 0b68f7b45c9..d4eb7e83b2e 100644 --- a/tests/Bridge/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php +++ b/tests/Bridge/Symfony/Bundle/EventListener/SwaggerUiListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\Bridge\Symfony\Bundle\EventListener; use ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener; +use ApiPlatform\Core\Event\EventInterface; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\GetResponseEvent; @@ -26,13 +27,13 @@ class SwaggerUiListenerTest extends TestCase /** * @dataProvider getParameters */ - public function testOnKernelRequest(Request $request, string $controller = null) + public function testSetController(Request $request, string $controller = null) { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new SwaggerUiListener(); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($controller, $request->attributes->get('_controller')); } @@ -55,4 +56,19 @@ public function getParameters() [$jsonRequest, null], ]; } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\Bridge\Symfony\Bundle\EventListener\SwaggerUiListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request()); + + $listener = new SwaggerUiListener(); + $listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcherTest.php b/tests/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcherTest.php new file mode 100644 index 00000000000..35e13fbfe65 --- /dev/null +++ b/tests/Bridge/Symfony/Bundle/EventSubscriber/EventDispatcherTest.php @@ -0,0 +1,146 @@ + + * + * 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\Core\Tests\Bridge\Symfony\Bundle\EventSubscriber; + +use ApiPlatform\Core\Bridge\Symfony\Bundle\EventSubscriber\EventDispatcher; +use ApiPlatform\Core\Event\DeserializeEvent; +use ApiPlatform\Core\Event\FormatAddEvent; +use ApiPlatform\Core\Event\PostDeserializeEvent; +use ApiPlatform\Core\Event\PostReadEvent; +use ApiPlatform\Core\Event\PostRespondEvent; +use ApiPlatform\Core\Event\PostSerializeEvent; +use ApiPlatform\Core\Event\PostValidateEvent; +use ApiPlatform\Core\Event\PostWriteEvent; +use ApiPlatform\Core\Event\PreDeserializeEvent; +use ApiPlatform\Core\Event\PreReadEvent; +use ApiPlatform\Core\Event\PreRespondEvent; +use ApiPlatform\Core\Event\PreSerializeEvent; +use ApiPlatform\Core\Event\PreValidateEvent; +use ApiPlatform\Core\Event\PreWriteEvent; +use ApiPlatform\Core\Event\QueryParameterValidateEvent; +use ApiPlatform\Core\Event\ReadEvent; +use ApiPlatform\Core\Event\RespondEvent; +use ApiPlatform\Core\Event\SerializeEvent; +use ApiPlatform\Core\Event\ValidateEvent; +use ApiPlatform\Core\Event\ValidationExceptionEvent; +use ApiPlatform\Core\Event\WriteEvent; +use ApiPlatform\Core\Events; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; + +class EventDispatcherTest extends TestCase +{ + private const INTERNAL_EVENTS_CONFIGURATION = [ + KernelEvents::REQUEST => [ + QueryParameterValidateEvent::class => Events::QUERY_PARAMETER_VALIDATE, + FormatAddEvent::class => Events::FORMAT_ADD, + + PreReadEvent::class => Events::PRE_READ, + ReadEvent::class => Events::READ, + PostReadEvent::class => Events::POST_READ, + + PreDeserializeEvent::class => Events::PRE_DESERIALIZE, + DeserializeEvent::class => Events::DESERIALIZE, + PostDeserializeEvent::class => Events::POST_DESERIALIZE, + ], + KernelEvents::VIEW => [ + PreValidateEvent::class => Events::PRE_VALIDATE, + ValidateEvent::class => Events::VALIDATE, + PostValidateEvent::class => Events::POST_VALIDATE, + + PreWriteEvent::class => Events::PRE_WRITE, + WriteEvent::class => Events::WRITE, + PostWriteEvent::class => Events::POST_WRITE, + + PreSerializeEvent::class => Events::PRE_SERIALIZE, + SerializeEvent::class => Events::SERIALIZE, + PostSerializeEvent::class => Events::POST_SERIALIZE, + + PreRespondEvent::class => Events::PRE_RESPOND, + RespondEvent::class => Events::RESPOND, + PostRespondEvent::class => Events::POST_RESPOND, + ], + KernelEvents::EXCEPTION => [ + ValidationExceptionEvent::class => Events::VALIDATE_EXCEPTION, + ], + ]; + + public function testGetSubscribedEvents(): void + { + $this->assertEquals( + ['kernel.request' => 'dispatch', 'kernel.view' => 'dispatch'], + EventDispatcher::getSubscribedEvents() + ); + } + + public function testDispatchWithRequestKernelEvent(): void + { + $kernelProphecy = $this->prophesize(HttpKernelInterface::class); + $requestProphecy = $this->prophesize(Request::class); + + $symfonyEvent = new GetResponseEvent($kernelProphecy->reveal(), $requestProphecy->reveal(), HttpKernelInterface::MASTER_REQUEST); + + $symfonyEventDispatcher = $this->prophesize(EventDispatcherInterface::class); + + foreach (self::INTERNAL_EVENTS_CONFIGURATION[KernelEvents::REQUEST] as $internalEventClass => $internalEventName) { + $internalEvent = new $internalEventClass(null, ['request' => $symfonyEvent->getRequest()]); + $symfonyEventDispatcher->dispatch($internalEventName, $internalEvent)->shouldBeCalledOnce(); + } + + $eventDispatcher = new EventDispatcher($symfonyEventDispatcher->reveal()); + $eventDispatcher->dispatch($symfonyEvent, KernelEvents::REQUEST); + } + + public function testDispatchWithViewKernelEvent(): void + { + $kernelProphecy = $this->prophesize(HttpKernelInterface::class); + $requestProphecy = $this->prophesize(Request::class); + + $symfonyEvent = new GetResponseForControllerResultEvent($kernelProphecy->reveal(), $requestProphecy->reveal(), HttpKernelInterface::MASTER_REQUEST, ['data' => 'test']); + + $symfonyEventDispatcher = $this->prophesize(EventDispatcherInterface::class); + + foreach (self::INTERNAL_EVENTS_CONFIGURATION[KernelEvents::VIEW] as $internalEventClass => $internalEventName) { + $internalEvent = new $internalEventClass(['data' => 'test'], ['request' => $symfonyEvent->getRequest()]); + $symfonyEventDispatcher->dispatch($internalEventName, $internalEvent)->shouldBeCalledOnce(); + } + + $eventDispatcher = new EventDispatcher($symfonyEventDispatcher->reveal()); + $eventDispatcher->dispatch($symfonyEvent, KernelEvents::VIEW); + } + + public function testDispacthWithExceptionKernelEvent(): void + { + $kernelProphecy = $this->prophesize(HttpKernelInterface::class); + $requestProphecy = $this->prophesize(Request::class); + + $symfonyEvent = new GetResponseForExceptionEvent($kernelProphecy->reveal(), $requestProphecy->reveal(), HttpKernelInterface::MASTER_REQUEST, new \Exception()); + + $symfonyEventDispatcher = $this->prophesize(EventDispatcherInterface::class); + + foreach (self::INTERNAL_EVENTS_CONFIGURATION[KernelEvents::EXCEPTION] as $internalEventClass => $internalEventName) { + $internalEvent = new $internalEventClass(null, ['request' => $symfonyEvent->getRequest(), 'exception' => $symfonyEvent->getException()]); + $symfonyEventDispatcher->dispatch($internalEventName, $internalEvent)->shouldBeCalledOnce(); + } + + $eventDispatcher = new EventDispatcher($symfonyEventDispatcher->reveal()); + $eventDispatcher->dispatch($symfonyEvent, KernelEvents::EXCEPTION); + } +} diff --git a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php index 3e77a49eae0..1e8b058b144 100644 --- a/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php +++ b/tests/Bridge/Symfony/Validator/EventListener/ValidationExceptionListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener; use ApiPlatform\Core\Bridge\Symfony\Validator\Exception\ValidationException; +use ApiPlatform\Core\Event\ValidationExceptionEvent; use PHPUnit\Framework\TestCase; use Prophecy\Argument; use Symfony\Component\HttpFoundation\Request; @@ -30,14 +31,14 @@ class ValidationExceptionListenerTest extends TestCase { public function testNotValidationException() { - $eventProphecy = $this->prophesize(GetResponseForExceptionEvent::class); - $eventProphecy->getException()->willReturn(new \Exception())->shouldBeCalled(); - $eventProphecy->setResponse()->shouldNotBeCalled(); + $eventProphecy = $this->prophesize(ValidationExceptionEvent::class); + $eventProphecy->getContext()->willReturn(['exception' => new \Exception()])->shouldBeCalled(); + $eventProphecy->setData()->shouldNotBeCalled(); $serializerProphecy = $this->prophesize(SerializerInterface::class); $listener = new ValidationExceptionListener($serializerProphecy->reveal(), ['hydra' => ['application/ld+json']]); - $listener->onKernelException($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testValidationException() @@ -45,10 +46,9 @@ public function testValidationException() $exceptionJson = '{"foo": "bar"}'; $list = new ConstraintViolationList([]); - $eventProphecy = $this->prophesize(GetResponseForExceptionEvent::class); - $eventProphecy->getException()->willReturn(new ValidationException($list))->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); - $eventProphecy->setResponse(Argument::allOf( + $eventProphecy = $this->prophesize(ValidationExceptionEvent::class); + $eventProphecy->getContext()->willReturn(['request' => new Request(), 'exception' => new ValidationException($list)])->shouldBeCalledTimes(2); + $eventProphecy->setData(Argument::allOf( Argument::type(Response::class), Argument::which('getContent', $exceptionJson), Argument::which('getStatusCode', Response::HTTP_BAD_REQUEST), @@ -65,6 +65,26 @@ public function testValidationException() $serializerProphecy->serialize($list, 'hydra')->willReturn($exceptionJson)->shouldBeCalled(); $listener = new ValidationExceptionListener($serializerProphecy->reveal(), ['hydra' => ['application/ld+json']]); + $listener->handleEvent($eventProphecy->reveal()); + } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener::onKernelException() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent" as argument of "ApiPlatform\Core\Bridge\Symfony\Validator\EventListener\ValidationExceptionListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelException() + { + $serializerProphecy = $this->prophesize(SerializerInterface::class); + + $eventProphecy = $this->prophesize(GetResponseForExceptionEvent::class); + $eventProphecy->getException()->willReturn(new \Exception()); + + $listener = new ValidationExceptionListener( + $serializerProphecy->reveal(), + ['hydra' => ['application/ld+json']] + ); $listener->onKernelException($eventProphecy->reveal()); } } diff --git a/tests/EventListener/AddFormatListenerTest.php b/tests/EventListener/AddFormatListenerTest.php index 3c60f0556cf..3146c262318 100644 --- a/tests/EventListener/AddFormatListenerTest.php +++ b/tests/EventListener/AddFormatListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\EventListener; use ApiPlatform\Core\Api\FormatsProviderInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\EventListener\AddFormatListener; use Negotiation\Negotiator; use PHPUnit\Framework\TestCase; @@ -32,14 +33,14 @@ public function testNoResourceClass() { $request = new Request(); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertNull($request->getRequestFormat(null)); } @@ -49,15 +50,15 @@ public function testSupportedRequestFormat() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['xml' => ['text/xml']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('xml', $request->getRequestFormat()); $this->assertSame('text/xml', $request->getMimeType($request->getRequestFormat())); @@ -68,15 +69,15 @@ public function testRespondFlag() $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['xml' => ['text/xml']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('xml', $request->getRequestFormat()); $this->assertSame('text/xml', $request->getMimeType($request->getRequestFormat())); @@ -90,15 +91,15 @@ public function testUnsupportedRequestFormat() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('json', $request->getRequestFormat()); } @@ -108,15 +109,15 @@ public function testSupportedAcceptHeader() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->headers->set('Accept', 'text/html, application/xhtml+xml, application/xml, application/json;q=0.9, */*;q=0.8'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['binary' => ['application/octet-stream'], 'json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('json', $request->getRequestFormat()); } @@ -126,15 +127,15 @@ public function testSupportedAcceptHeaderSymfonyBuiltInFormat() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->headers->set('Accept', 'application/json'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['jsonld' => ['application/ld+json', 'application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('jsonld', $request->getRequestFormat()); } @@ -144,15 +145,15 @@ public function testAcceptAllHeader() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->headers->set('Accept', 'text/html, application/xhtml+xml, application/xml;q=0.9, */*;q=0.8'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['binary' => ['application/octet-stream'], 'json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('binary', $request->getRequestFormat()); $this->assertSame('application/octet-stream', $request->getMimeType($request->getRequestFormat())); @@ -166,15 +167,15 @@ public function testUnsupportedAcceptHeader() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->headers->set('Accept', 'text/html, application/xhtml+xml, application/xml;q=0.9'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['binary' => ['application/octet-stream'], 'json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testUnsupportedAcceptHeaderSymfonyBuiltInFormat() @@ -185,15 +186,15 @@ public function testUnsupportedAcceptHeaderSymfonyBuiltInFormat() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->headers->set('Accept', 'text/xml'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testInvalidAcceptHeader() @@ -204,15 +205,15 @@ public function testInvalidAcceptHeader() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->headers->set('Accept', 'invalid'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testAcceptHeaderTakePrecedenceOverRequestFormat() @@ -221,15 +222,15 @@ public function testAcceptHeaderTakePrecedenceOverRequestFormat() $request->headers->set('Accept', 'application/json'); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['xml' => ['application/xml'], 'json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('json', $request->getRequestFormat()); } @@ -241,15 +242,15 @@ public function testInvalidRouteFormat() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_format' => 'invalid']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(Argument::any())->willReturn(['json' => ['application/json']]); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testResourceClassSupportedRequestFormat() @@ -257,15 +258,15 @@ public function testResourceClassSupportedRequestFormat() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->setRequestFormat('csv'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); $formatsProviderProphecy->getFormatsFromAttributes(['resource_class' => 'Foo', 'collection_operation_name' => 'get', 'receive' => true, 'persist' => true])->willReturn(['csv' => ['text/csv']])->shouldBeCalled(); $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); $this->assertSame('csv', $request->getRequestFormat()); $this->assertSame('text/csv', $request->getMimeType($request->getRequestFormat())); @@ -287,4 +288,24 @@ public function testLegacyFormatsParameter() { new AddFormatListener(new Negotiator(), ['xml' => ['text/xml']]); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\EventListener\AddFormatListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\EventListener\AddFormatListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $request = new Request(); + + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn($request); + $event = $eventProphecy->reveal(); + + $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); + + $listener = new AddFormatListener(new Negotiator(), $formatsProviderProphecy->reveal()); + $listener->onKernelRequest($event); + } } diff --git a/tests/EventListener/DeserializeListenerTest.php b/tests/EventListener/DeserializeListenerTest.php index 20345460d3f..a89da0e534b 100644 --- a/tests/EventListener/DeserializeListenerTest.php +++ b/tests/EventListener/DeserializeListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\EventListener; use ApiPlatform\Core\Api\FormatsProviderInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\EventListener\DeserializeListener; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; use PHPUnit\Framework\TestCase; @@ -33,11 +34,10 @@ class DeserializeListenerTest extends TestCase public function testDoNotCallWhenRequestMethodIsSafe() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['data' => new \stdClass()]); $request->setMethod('GET'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -49,7 +49,7 @@ public function testDoNotCallWhenRequestMethodIsSafe() $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } /** @@ -57,12 +57,11 @@ public function testDoNotCallWhenRequestMethodIsSafe() */ public function testDoNotCallWhenSendingAndEmptyRequestContent($method) { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['data' => new \stdClass(), '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'put'], [], [], [], ''); $request->setMethod($method); $request->headers->set('Content-Type', 'application/json'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -74,7 +73,7 @@ public function testDoNotCallWhenSendingAndEmptyRequestContent($method) $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function allowedEmptyRequestMethodsProvider() @@ -84,11 +83,10 @@ public function allowedEmptyRequestMethodsProvider() public function testDoNotCallWhenRequestNotManaged() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['data' => new \stdClass()], [], [], [], '{}'); $request->setMethod('POST'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -100,16 +98,15 @@ public function testDoNotCallWhenRequestNotManaged() $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testDoNotCallWhenReceiveFlagIsFalse() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['data' => new \stdClass(), '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_receive' => false]); $request->setMethod('POST'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -121,16 +118,15 @@ public function testDoNotCallWhenReceiveFlagIsFalse() $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testDoNotCallWhenInputClassDisabled() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['data' => new \stdClass(), '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], 'content'); $request->setMethod('POST'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -142,7 +138,7 @@ public function testDoNotCallWhenInputClassDisabled() $formatsProviderProphecy->getFormatsFromAttributes(Argument::type('array'))->shouldNotBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } /** @@ -151,12 +147,12 @@ public function testDoNotCallWhenInputClassDisabled() public function testDeserialize(string $method, bool $populateObject) { $result = $populateObject ? new \stdClass() : null; - $eventProphecy = $this->prophesize(GetResponseEvent::class); $request = new Request([], [], ['data' => $result, '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod($method); $request->headers->set('Content-Type', 'application/json'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $context = $populateObject ? [AbstractNormalizer::OBJECT_TO_POPULATE => $populateObject] : []; @@ -172,7 +168,7 @@ public function testDeserialize(string $method, bool $populateObject) $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), false, Argument::type('array'))->willReturn(['input' => ['class' => 'Foo'], 'output' => ['class' => 'Foo'], 'resource_class' => 'Foo'])->shouldBeCalled(); $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } /** @@ -181,12 +177,12 @@ public function testDeserialize(string $method, bool $populateObject) public function testDeserializeResourceClassSupportedFormat(string $method, bool $populateObject) { $result = $populateObject ? new \stdClass() : null; - $eventProphecy = $this->prophesize(GetResponseEvent::class); $request = new Request([], [], ['data' => $result, '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod($method); $request->headers->set('Content-Type', 'application/json'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $context = $populateObject ? [AbstractNormalizer::OBJECT_TO_POPULATE => $populateObject] : []; @@ -203,7 +199,7 @@ public function testDeserializeResourceClassSupportedFormat(string $method, bool $listener = new DeserializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal()); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function methodProvider() @@ -213,13 +209,12 @@ public function methodProvider() public function testContentNegotiation() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod('POST'); $request->headers->set('Content-Type', 'text/xml'); $request->setFormat('xml', 'text/xml'); // Workaround to avoid weird behaviors - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $context = ['input' => ['class' => 'Foo'], 'output' => ['class' => 'Foo'], 'resource_class' => 'Foo']; @@ -237,7 +232,7 @@ public function testContentNegotiation() $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal() ); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testNotSupportedContentType() @@ -245,13 +240,12 @@ public function testNotSupportedContentType() $this->expectException(NotAcceptableHttpException::class); $this->expectExceptionMessage('The content-type "application/rdf+xml" is not supported. Supported MIME types are "application/ld+json", "text/xml".'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod('POST'); $request->headers->set('Content-Type', 'application/rdf+xml'); $request->setRequestFormat('xml'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -267,7 +261,7 @@ public function testNotSupportedContentType() $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal() ); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testNoContentType() @@ -275,12 +269,11 @@ public function testNoContentType() $this->expectException(NotAcceptableHttpException::class); $this->expectExceptionMessage('The "Content-Type" header must exist.'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post'], [], [], [], '{}'); $request->setMethod('POST'); $request->setRequestFormat('unknown'); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy->deserialize()->shouldNotBeCalled(); @@ -296,7 +289,7 @@ public function testNoContentType() $serializerContextBuilderProphecy->reveal(), $formatsProviderProphecy->reveal() ); - $listener->onKernelRequest($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testBadFormatsProviderParameterThrowsException() @@ -335,4 +328,27 @@ public function testLegacyFormatsParameter() self::FORMATS ); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\EventListener\DeserializeListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\EventListener\DeserializeListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $serializerProphecy = $this->prophesize(SerializerInterface::class); + $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $formatsProviderProphecy = $this->prophesize(FormatsProviderInterface::class); + + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request()); + + $listener = new DeserializeListener( + $serializerProphecy->reveal(), + $serializerContextBuilderProphecy->reveal(), + $formatsProviderProphecy->reveal() + ); + $listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/EventListener/ReadListenerTest.php b/tests/EventListener/ReadListenerTest.php index e259bf70010..faa2fa85958 100644 --- a/tests/EventListener/ReadListenerTest.php +++ b/tests/EventListener/ReadListenerTest.php @@ -16,6 +16,7 @@ use ApiPlatform\Core\DataProvider\CollectionDataProviderInterface; use ApiPlatform\Core\DataProvider\ItemDataProviderInterface; use ApiPlatform\Core\DataProvider\SubresourceDataProviderInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\EventListener\ReadListener; use ApiPlatform\Core\Exception\InvalidIdentifierException; use ApiPlatform\Core\Exception\RuntimeException; @@ -44,11 +45,11 @@ public function testNotAnApiPlatformRequest() $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn(new Request())->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => new Request()]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } /** @@ -65,11 +66,11 @@ public function testLegacyConstructor() $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn(new Request())->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => new Request()]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testDoNotCallWhenReceiveFlagIsFalse() @@ -88,11 +89,11 @@ public function testDoNotCallWhenReceiveFlagIsFalse() $request = new Request([], [], ['data' => new \stdClass(), '_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_receive' => false]); $request->setMethod('PUT'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testRetrieveCollectionPost() @@ -111,11 +112,11 @@ public function testRetrieveCollectionPost() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'post', '_api_format' => 'json', '_api_mime_type' => 'application/json'], [], [], [], '{}'); $request->setMethod('POST'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertTrue($request->attributes->has('data')); $this->assertNull($request->attributes->get('data')); @@ -137,11 +138,11 @@ public function testRetrieveCollectionGet() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json'], [], [], ['QUERY_STRING' => 'foo=bar']); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertSame([], $request->attributes->get('data')); } @@ -164,11 +165,11 @@ public function testRetrieveItem() $request = new Request([], [], ['id' => 1, '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertSame($data, $request->attributes->get('data')); } @@ -189,11 +190,11 @@ public function testRetrieveItemNoIdentifier() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $request->attributes->get('data'); } @@ -216,11 +217,11 @@ public function testRetrieveSubresource() $request = new Request([], [], ['id' => 1, '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true]], 'property' => 'bar']]); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertSame($data, $request->attributes->get('data')); } @@ -238,11 +239,11 @@ public function testRetrieveSubresourceNoDataProvider() $request = new Request([], [], ['id' => 1, '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true]], 'property' => 'bar']]); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $request->attributes->get('data'); } @@ -262,11 +263,11 @@ public function testRetrieveSubresourceNotFound() $request = new Request([], [], ['id' => 1, '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true]], 'property' => 'bar']]); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $this->prophesize(SubresourceDataProviderInterface::class)->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testRetrieveItemNotFound() @@ -285,11 +286,11 @@ public function testRetrieveItemNotFound() $request = new Request([], [], ['id' => 22, '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); $request->setMethod('GET'); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testRetrieveBadItemNormalizedIdentifiers() @@ -306,11 +307,11 @@ public function testRetrieveBadItemNormalizedIdentifiers() $request = new Request([], [], ['id' => 1, '_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json']); $request->setMethod(Request::METHOD_GET); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testRetrieveBadSubresourceNormalizedIdentifiers() @@ -326,17 +327,36 @@ public function testRetrieveBadSubresourceNormalizedIdentifiers() $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); $itemDataProvider->getItem()->shouldNotBeCalled(); - $data = [new \stdClass()]; $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); $subresourceDataProvider->getSubresource()->shouldNotBeCalled(); $request = new Request([], [], ['id' => 1, '_api_resource_class' => 'Foo', '_api_subresource_operation_name' => 'get', '_api_format' => 'json', '_api_mime_type' => 'application/json', '_api_subresource_context' => ['identifiers' => [['id', 'Bar', true]], 'property' => 'bar']]); $request->setMethod(Request::METHOD_GET); - $event = $this->prophesize(GetResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); + + $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); + $listener->handleEvent($eventProphecy->reveal()); + } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\EventListener\ReadListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\EventListener\ReadListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $collectionDataProvider = $this->prophesize(CollectionDataProviderInterface::class); + $itemDataProvider = $this->prophesize(ItemDataProviderInterface::class); + $subresourceDataProvider = $this->prophesize(SubresourceDataProviderInterface::class); + $identifierConverter = $this->prophesize(IdentifierConverterInterface::class); + + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request()); $listener = new ReadListener($collectionDataProvider->reveal(), $itemDataProvider->reveal(), $subresourceDataProvider->reveal(), null, $identifierConverter->reveal()); - $listener->onKernelRequest($event->reveal()); + $listener->onKernelRequest($eventProphecy->reveal()); } } diff --git a/tests/EventListener/RespondListenerTest.php b/tests/EventListener/RespondListenerTest.php index d2f5d6ca68d..c017635a8d2 100644 --- a/tests/EventListener/RespondListenerTest.php +++ b/tests/EventListener/RespondListenerTest.php @@ -13,6 +13,8 @@ namespace ApiPlatform\Core\Tests\EventListener; +use ApiPlatform\Core\Event\EventInterface; +use ApiPlatform\Core\Event\RespondEvent; use ApiPlatform\Core\EventListener\RespondListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; @@ -33,26 +35,26 @@ public function testDoNotHandleResponse() { $request = new Request(); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn(new Response()); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setResponse(Argument::any())->shouldNotBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn(new Response()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $eventProphecy->setData(Argument::any())->shouldNotBeCalled(); $listener = new RespondListener(); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testDoNotHandleWhenRespondFlagIsFalse() { $request = new Request([], [], ['_api_respond' => false]); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn('foo'); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setResponse(Argument::any())->shouldNotBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn('foo'); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $eventProphecy->setData(Argument::any())->shouldNotBeCalled(); $listener = new RespondListener(); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testCreate200Response() @@ -60,18 +62,12 @@ public function testCreate200Response() $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $event = new GetResponseForControllerResultEvent( - $kernelProphecy->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - 'foo' - ); + $event = new RespondEvent('foo', ['request' => $request]); $listener = new RespondListener(); - $listener->onKernelView($event); + $listener->handleEvent($event); - $response = $event->getResponse(); + $response = $event->getContext()['response']; $this->assertEquals('foo', $response->getContent()); $this->assertEquals(Response::HTTP_OK, $response->getStatusCode()); $this->assertEquals('text/xml; charset=utf-8', $response->headers->get('Content-Type')); @@ -82,23 +78,16 @@ public function testCreate200Response() public function testCreate201Response() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_respond' => true, '_api_write_item_iri' => '/dummy_entities/1']); $request->setMethod('POST'); $request->setRequestFormat('xml'); - $event = new GetResponseForControllerResultEvent( - $kernelProphecy->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - 'foo' - ); + $event = new RespondEvent('foo', ['request' => $request]); $listener = new RespondListener(); - $listener->onKernelView($event); + $listener->handleEvent($event); - $response = $event->getResponse(); + $response = $event->getContext()['response']; $this->assertEquals('foo', $response->getContent()); $this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode()); $this->assertEquals('text/xml; charset=utf-8', $response->headers->get('Content-Type')); @@ -111,23 +100,16 @@ public function testCreate201Response() public function testCreate204Response() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); $request->setMethod('DELETE'); - $event = new GetResponseForControllerResultEvent( - $kernelProphecy->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - 'foo' - ); + $event = new RespondEvent('foo', ['request' => $request]); $listener = new RespondListener(); - $listener->onKernelView($event); + $listener->handleEvent($event); - $response = $event->getResponse(); + $response = $event->getContext()['response']; $this->assertEquals('foo', $response->getContent()); $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); $this->assertEquals('text/xml; charset=utf-8', $response->headers->get('Content-Type')); @@ -138,23 +120,17 @@ public function testCreate204Response() public function testSetSunsetHeader() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]); - $event = new GetResponseForControllerResultEvent( - $kernelProphecy->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - 'bar' - ); + $event = new RespondEvent('bar', ['request' => $request]); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['sunset' => 'tomorrow']])); $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelView($event); + $listener->handleEvent($event); - $response = $event->getResponse(); + $response = $event->getContext()['response']; /** @var string $value */ $value = $response->headers->get('Sunset'); $this->assertEquals(new \DateTimeImmutable('tomorrow'), \DateTime::createFromFormat(DATE_RFC1123, $value)); @@ -162,22 +138,39 @@ public function testSetSunsetHeader() public function testSetCustomStatus() { - $kernelProphecy = $this->prophesize(HttpKernelInterface::class); - $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'get', '_api_respond' => true]); + $event = new RespondEvent('bar', ['request' => $request]); + + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_ACCEPTED]])); + + $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); + $listener->handleEvent($event); + + $this->assertSame(Response::HTTP_ACCEPTED, $event->getContext()['response']->getStatusCode()); + } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\EventListener\RespondListener::onKernelView() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" as argument of "ApiPlatform\Core\EventListener\RespondListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelView() + { + $request = new Request([], [], ['_api_respond' => true]); + $request->setRequestFormat('xml'); + + $kernelProphecy = $this->prophesize(HttpKernelInterface::class); $event = new GetResponseForControllerResultEvent( $kernelProphecy->reveal(), $request, HttpKernelInterface::MASTER_REQUEST, - 'bar' + 'foo' ); - $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); - $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, ['get' => ['status' => Response::HTTP_ACCEPTED]])); - $listener = new RespondListener($resourceMetadataFactoryProphecy->reveal()); + $listener = new RespondListener(); $listener->onKernelView($event); - - $this->assertSame(Response::HTTP_ACCEPTED, $event->getResponse()->getStatusCode()); } } diff --git a/tests/EventListener/SerializeListenerTest.php b/tests/EventListener/SerializeListenerTest.php index 48414dc9fbc..aa9c6c291c3 100644 --- a/tests/EventListener/SerializeListenerTest.php +++ b/tests/EventListener/SerializeListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\EventListener\SerializeListener; use ApiPlatform\Core\Serializer\ResourceList; use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface; @@ -37,15 +38,15 @@ public function testDoNotSerializeResponse() $request = new Request(); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn(new Response())->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn(new Response())->shouldBeCalled(); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::cetera())->shouldNotBeCalled(); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } public function testDoNotSerializeWhenRespondFlagIsFalse() @@ -57,20 +58,39 @@ public function testDoNotSerializeWhenRespondFlagIsFalse() $request = new Request([], [], ['_api_respond' => false]); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass()); - $eventProphecy->getRequest()->willReturn($request); - $eventProphecy->setControllerResult(Argument::any())->shouldNotBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn(new \stdClass()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $eventProphecy->setData(Argument::any())->shouldNotBeCalled(); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } - public function testSerializeCollectionOperation() + public function testSerializeCollectionOperationWithOutputClassDisabled() { - $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'collection_operation_name' => 'get']; + $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'collection_operation_name' => 'post', 'output' => ['class' => null]]; $serializerProphecy = $this->prophesize(SerializerInterface::class); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_output_class' => false]); + $request->setRequestFormat('xml'); + + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn(new \stdClass())->shouldBeCalled(); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); + $eventProphecy->setData('')->shouldBeCalled(); + + $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); + $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); + + $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); + } + + public function testSerializeItemOperation() + { + $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'item_operation_name' => 'get']; + $serializerProphecy = $this->prophesize(SerializerInterface::class); $serializerProphecy ->serialize( Argument::any(), @@ -81,51 +101,53 @@ public function testSerializeCollectionOperation() }), Argument::withEntry('request_uri', ''), Argument::withEntry('resource_class', 'Foo'), - Argument::withEntry('collection_operation_name', 'get') + Argument::withEntry('item_operation_name', 'get') ) ) ->willReturn('bar') ->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass())->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('bar')->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn(new \stdClass())->shouldBeCalled(); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); + $eventProphecy->setData('bar')->shouldBeCalled(); $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } - public function testSerializeCollectionOperationWithOutputClassDisabled() + public function testEncode() { - $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'collection_operation_name' => 'post', 'output' => ['class' => null]]; $serializerProphecy = $this->prophesize(SerializerInterface::class); + $serializerProphecy->willImplement(EncoderInterface::class); + $serializerProphecy->encode(Argument::any(), 'xml')->willReturn('bar')->shouldBeCalled(); + $serializerProphecy->serialize(Argument::cetera())->shouldNotBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', '_api_output_class' => false]); + $request = new Request([], [], ['_api_respond' => true]); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass())->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('')->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn([])->shouldBeCalled(); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); + $eventProphecy->setData('bar')->shouldBeCalled(); $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); - $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } - public function testSerializeItemOperation() + public function testSerializeCollectionOperation() { - $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'item_operation_name' => 'get']; + $expectedContext = ['request_uri' => '', 'resource_class' => 'Foo', 'collection_operation_name' => 'get']; $serializerProphecy = $this->prophesize(SerializerInterface::class); + $serializerProphecy ->serialize( Argument::any(), @@ -136,41 +158,43 @@ public function testSerializeItemOperation() }), Argument::withEntry('request_uri', ''), Argument::withEntry('resource_class', 'Foo'), - Argument::withEntry('item_operation_name', 'get') + Argument::withEntry('collection_operation_name', 'get') ) ) ->willReturn('bar') ->shouldBeCalled(); - $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_item_operation_name' => 'get']); + $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); $request->setRequestFormat('xml'); - $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn(new \stdClass())->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('bar')->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getData()->willReturn(new \stdClass())->shouldBeCalled(); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); + $eventProphecy->setData('bar')->shouldBeCalled(); $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); $serializerContextBuilderProphecy->createFromRequest(Argument::type(Request::class), true, Argument::type('array'))->willReturn($expectedContext)->shouldBeCalled(); $listener = new SerializeListener($serializerProphecy->reveal(), $serializerContextBuilderProphecy->reveal()); - $listener->onKernelView($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); } - public function testEncode() + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\EventListener\SerializeListener::onKernelView() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" as argument of "ApiPlatform\Core\EventListener\SerializeListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelView() { $serializerProphecy = $this->prophesize(SerializerInterface::class); - $serializerProphecy->willImplement(EncoderInterface::class); - $serializerProphecy->encode(Argument::any(), 'xml')->willReturn('bar')->shouldBeCalled(); - $serializerProphecy->serialize(Argument::cetera())->shouldNotBeCalled(); - $request = new Request([], [], ['_api_respond' => true]); + $request = new Request(); $request->setRequestFormat('xml'); $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); - $eventProphecy->getControllerResult()->willReturn([])->shouldBeCalled(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $eventProphecy->setControllerResult('bar')->shouldBeCalled(); + $eventProphecy->getControllerResult()->willReturn(new Response()); + $eventProphecy->getRequest()->willReturn($request); $serializerContextBuilderProphecy = $this->prophesize(SerializerContextBuilderInterface::class); diff --git a/tests/EventListener/WriteListenerTest.php b/tests/EventListener/WriteListenerTest.php index ddbda5aa4b5..014b92da9f9 100644 --- a/tests/EventListener/WriteListenerTest.php +++ b/tests/EventListener/WriteListenerTest.php @@ -15,6 +15,7 @@ use ApiPlatform\Core\Api\IriConverterInterface; use ApiPlatform\Core\DataPersister\DataPersisterInterface; +use ApiPlatform\Core\Event\WriteEvent; use ApiPlatform\Core\EventListener\WriteListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; @@ -30,7 +31,7 @@ */ class WriteListenerTest extends TestCase { - public function testOnKernelViewWithControllerResultAndPersist() + public function testHandleEventWithControllerResultAndPersist() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -44,19 +45,14 @@ public function testOnKernelViewWithControllerResultAndPersist() $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { $request->setMethod($httpMethod); $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); - $this->assertSame($dummy, $event->getControllerResult()); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); + $this->assertSame($dummy, $event->getData()); $this->assertEquals('/dummy/1', $request->attributes->get('_api_write_item_iri')); } } @@ -65,7 +61,7 @@ public function testOnKernelViewWithControllerResultAndPersist() * @group legacy * @expectedDeprecation Returning void from ApiPlatform\Core\DataPersister\DataPersisterInterface::persist() is deprecated since API Platform 2.3 and will not be supported in API Platform 3, an object should always be returned. */ - public function testOnKernelViewWithControllerResultAndPersistReturningVoid() + public function testHandleEventWithControllerResultAndPersistReturningVoid() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -76,26 +72,21 @@ public function testOnKernelViewWithControllerResultAndPersistReturningVoid() $request = new Request([], [], ['_api_resource_class' => Dummy::class]); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { $request->setMethod($httpMethod); $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - (new WriteListener($dataPersisterProphecy->reveal()))->onKernelView($event); - $this->assertSame($dummy, $event->getControllerResult()); + (new WriteListener($dataPersisterProphecy->reveal()))->handleEvent($event); + $this->assertSame($dummy, $event->getData()); } } /** * @see https://github.com/api-platform/core/issues/1799 */ - public function testOnKernelViewWithControllerResultAndPersistWithImmutableResource() + public function testhandleEventWithControllerResultAndPersistWithImmutableResource() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -118,24 +109,19 @@ public function testOnKernelViewWithControllerResultAndPersistWithImmutableResou $request = new Request([], [], ['_api_resource_class' => Dummy::class]); foreach (['PATCH', 'PUT', 'POST'] as $httpMethod) { - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); $request->setMethod($httpMethod); $request->attributes->set(sprintf('_api_%s_operation_name', 'POST' === $httpMethod ? 'collection' : 'item'), strtolower($httpMethod)); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); - $this->assertSame($dummy2, $event->getControllerResult()); + $this->assertSame($dummy2, $event->getData()); $this->assertEquals('/dummy/1', $request->attributes->get('_api_write_item_iri')); } } - public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() + public function testHandleEventDoNotCallIriConverterWhenOutputClassDisabled() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -154,17 +140,12 @@ public function testOnKernelViewDoNotCallIriConverterWhenOutputClassDisabled() $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'post']); $request->setMethod('POST'); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()))->handleEvent($event); } - public function testOnKernelViewWithControllerResultAndRemove() + public function testhandleEventWithControllerResultAndRemove() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -179,17 +160,12 @@ public function testOnKernelViewWithControllerResultAndRemove() $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'delete']); $request->setMethod('DELETE'); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); } - public function testOnKernelViewWithSafeMethod() + public function testHandleEventWithSafeMethod() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -205,17 +181,12 @@ public function testOnKernelViewWithSafeMethod() $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'head']); $request->setMethod('HEAD'); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); - (new WriteListener($dataPersisterProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal()))->handleEvent($event); } - public function testOnKernelViewWithPersistFlagOff() + public function testHandleEventWithPersistFlagOff() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -231,17 +202,12 @@ public function testOnKernelViewWithPersistFlagOff() $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_item_operation_name' => 'head', '_api_persist' => false]); $request->setMethod('HEAD'); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); } - public function testOnKernelViewWithNoResourceClass() + public function testHandleViewWithNoResourceClass() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -257,17 +223,12 @@ public function testOnKernelViewWithNoResourceClass() $request = new Request(); $request->setMethod('POST'); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); } - public function testOnKernelViewWithParentResourceClass() + public function testHandleViewWithParentResourceClass() { $dummy = new ConcreteDummy(); @@ -281,17 +242,12 @@ public function testOnKernelViewWithParentResourceClass() $request = new Request([], [], ['_api_resource_class' => ConcreteDummy::class, '_api_item_operation_name' => 'put', '_api_persist' => true]); $request->setMethod('PUT'); - $event = new GetResponseForControllerResultEvent( - $this->prophesize(HttpKernelInterface::class)->reveal(), - $request, - HttpKernelInterface::MASTER_REQUEST, - $dummy - ); + $event = new WriteEvent($dummy, ['request' => $request]); - (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->onKernelView($event); + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); } - public function testOnKernelViewWithNoDataPersisterSupport() + public function testHandleViewWithNoDataPersisterSupport() { $dummy = new Dummy(); $dummy->setName('Dummyrino'); @@ -307,6 +263,28 @@ public function testOnKernelViewWithNoDataPersisterSupport() $request = new Request([], [], ['_api_resource_class' => 'Dummy', '_api_collection_operation_name' => 'post']); $request->setMethod('POST'); + $event = new WriteEvent($dummy, ['request' => $request]); + + (new WriteListener($dataPersisterProphecy->reveal(), $iriConverterProphecy->reveal()))->handleEvent($event); + } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\EventListener\WriteListener::onKernelView() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" as argument of "ApiPlatform\Core\EventListener\WriteListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelView() + { + $dummy = new Dummy(); + + $dataPersisterProphecy = $this->prophesize(DataPersisterInterface::class); + $dataPersisterProphecy->supports($dummy)->willReturn(false); + + $iriConverterProphecy = $this->prophesize(IriConverterInterface::class); + + $request = new Request([], [], ['_api_resource_class' => Dummy::class]); + $event = new GetResponseForControllerResultEvent( $this->prophesize(HttpKernelInterface::class)->reveal(), $request, diff --git a/tests/Filter/QueryParameterValidateListenerTest.php b/tests/Filter/QueryParameterValidateListenerTest.php index a05393d24dc..def874accab 100644 --- a/tests/Filter/QueryParameterValidateListenerTest.php +++ b/tests/Filter/QueryParameterValidateListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\Filter; use ApiPlatform\Core\Api\FilterInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Exception\FilterValidationException; use ApiPlatform\Core\Filter\QueryParameterValidateListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; @@ -26,60 +27,61 @@ class QueryParameterValidateListenerTest extends TestCase { + /** @var QueryParameterValidateListener */ private $testedInstance; private $filterLocatorProphecy; /** * unsafe method should not use filter validations. */ - public function testOnKernelRequestWithUnsafeMethod() + public function testWithUnsafeMethod() { $this->setUpWithFilters(); $request = new Request(); $request->setMethod('POST'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $this->assertNull( - $this->testedInstance->onKernelRequest($eventProphecy->reveal()) + $this->testedInstance->handleEvent($eventProphecy->reveal()) ); } /** * If the tested filter is non-existent, then nothing should append. */ - public function testOnKernelRequestWithWrongFilter() + public function testWithWrongFilter() { $this->setUpWithFilters(['some_inexistent_filter']); $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); $request->setMethod('GET'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $this->filterLocatorProphecy->has('some_inexistent_filter')->shouldBeCalled(); $this->filterLocatorProphecy->get('some_inexistent_filter')->shouldNotBeCalled(); $this->assertNull( - $this->testedInstance->onKernelRequest($eventProphecy->reveal()) + $this->testedInstance->handleEvent($eventProphecy->reveal()) ); } /** * if the required parameter is not set, throw an FilterValidationException. */ - public function testOnKernelRequestWithRequiredFilterNotSet() + public function testWithRequiredFilterNotSet() { $this->setUpWithFilters(['some_filter']); $request = new Request([], [], ['_api_resource_class' => Dummy::class, '_api_collection_operation_name' => 'get']); $request->setMethod('GET'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $this->filterLocatorProphecy ->has('some_filter') @@ -104,13 +106,13 @@ public function testOnKernelRequestWithRequiredFilterNotSet() $this->expectException(FilterValidationException::class); $this->expectExceptionMessage('Query parameter "required" is required'); - $this->testedInstance->onKernelRequest($eventProphecy->reveal()); + $this->testedInstance->handleEvent($eventProphecy->reveal()); } /** * if the required parameter is set, no exception should be thrown. */ - public function testOnKernelRequestWithRequiredFilter() + public function testWithRequiredFilter() { $this->setUpWithFilters(['some_filter']); @@ -121,8 +123,8 @@ public function testOnKernelRequestWithRequiredFilter() ); $request->setMethod('GET'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $this->filterLocatorProphecy ->has('some_filter') @@ -146,10 +148,29 @@ public function testOnKernelRequestWithRequiredFilter() ; $this->assertNull( - $this->testedInstance->onKernelRequest($eventProphecy->reveal()) + $this->testedInstance->handleEvent($eventProphecy->reveal()) ); } + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Filter\QueryParameterValidateListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\Filter\QueryParameterValidateListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $this->setUpWithFilters(); + + $request = new Request(); + $request->setMethod('POST'); + + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + + $this->testedInstance->onKernelRequest($eventProphecy->reveal()); + } + private function setUpWithFilters(array $filters = []) { $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); diff --git a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php index 4e9c4226cd4..cac95fb1294 100644 --- a/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Hydra/EventListener/AddLinkHeaderListenerTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\Core\Tests\Hydra\EventListener; use ApiPlatform\Core\Api\UrlGeneratorInterface; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener; use Fig\Link\GenericLinkProvider; use Fig\Link\Link; @@ -35,12 +36,30 @@ public function testAddLinkHeader(string $expected, Request $request) $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); $urlGenerator->generate('api_doc', ['_format' => 'jsonld'], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/docs')->shouldBeCalled(); + $event = $this->prophesize(EventInterface::class); + $event->getContext()->willReturn(['request' => $request])->shouldBeCalled(); + + $listener = new AddLinkHeaderListener($urlGenerator->reveal()); + $listener->handleEvent($event->reveal()); + $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); + } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener::onKernelResponse() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\FilterResponseEvent" as argument of "ApiPlatform\Core\Hydra\EventListener\AddLinkHeaderListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelResponse() + { + $urlGenerator = $this->prophesize(UrlGeneratorInterface::class); + $urlGenerator->generate('api_doc', ['_format' => 'jsonld'], UrlGeneratorInterface::ABS_URL)->willReturn('http://example.com/docs'); + $event = $this->prophesize(FilterResponseEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $event->getRequest()->willReturn(new Request())->shouldBeCalled(); $listener = new AddLinkHeaderListener($urlGenerator->reveal()); $listener->onKernelResponse($event->reveal()); - $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); } public function provider(): array diff --git a/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php b/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php index 1da7b75ba3e..5e07c9a50d5 100644 --- a/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php +++ b/tests/JsonApi/EventListener/TransformFieldsetsParametersListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; @@ -23,6 +24,7 @@ class TransformFieldsetsParametersListenerTest extends TestCase { + /** @var TransformFieldsetsParametersListener */ private $listener; protected function setUp() @@ -33,44 +35,44 @@ protected function setUp() $this->listener = new TransformFieldsetsParametersListener($resourceMetadataFactoryProphecy->reveal()); } - public function testOnKernelRequestWithInvalidFormat() + public function testWithInvalidFormat() { $expectedRequest = new Request(); $expectedRequest->setRequestFormat('badformat'); $request = $expectedRequest->duplicate(); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequestWithInvalidFilter() + public function testWithInvalidFilter() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy = $this->prophesize(EventInterface::class); $expectedRequest = new Request(); $expectedRequest->setRequestFormat('jsonapi'); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); $expectedRequest = $expectedRequest->duplicate(['fields' => 'foo']); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequest() + public function testWithValidFilter() { $request = new Request( ['fields' => ['dummy' => 'id,name,dummyFloat', 'relatedDummy' => 'id,name'], 'include' => 'relatedDummy,foo'], @@ -79,10 +81,10 @@ public function testOnKernelRequest() ); $request->setRequestFormat('jsonapi'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $expectedRequest = new Request( ['fields' => ['dummy' => 'id,name,dummyFloat', 'relatedDummy' => 'id,name'], 'include' => 'relatedDummy,foo'], @@ -98,7 +100,7 @@ public function testOnKernelRequest() $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequestWithIncludeWithoutFields() + public function testWithIncludeWithoutFields() { $request = new Request( ['include' => 'relatedDummy,foo'], @@ -107,10 +109,10 @@ public function testOnKernelRequestWithIncludeWithoutFields() ); $request->setRequestFormat('jsonapi'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $expectedRequest = new Request( ['include' => 'relatedDummy,foo'], @@ -125,7 +127,7 @@ public function testOnKernelRequestWithIncludeWithoutFields() $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequestWithWrongParametersTypesDoesnTAffectRequestAttributes() + public function testWithWrongParametersTypesDoesnTAffectRequestAttributes() { $request = new Request( ['fields' => 'foo', 'include' => ['relatedDummy,foo']], @@ -134,10 +136,10 @@ public function testOnKernelRequestWithWrongParametersTypesDoesnTAffectRequestAt ); $request->setRequestFormat('jsonapi'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $expectedRequest = new Request( ['fields' => 'foo', 'include' => ['relatedDummy,foo']], @@ -148,4 +150,18 @@ public function testOnKernelRequestWithWrongParametersTypesDoesnTAffectRequestAt $this->assertEquals($expectedRequest, $request); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\JsonApi\EventListener\TransformFieldsetsParametersListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); + + $this->listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/JsonApi/EventListener/TransformFilteringParametersListenerTest.php b/tests/JsonApi/EventListener/TransformFilteringParametersListenerTest.php index 72a76c69a59..d37f910f691 100644 --- a/tests/JsonApi/EventListener/TransformFilteringParametersListenerTest.php +++ b/tests/JsonApi/EventListener/TransformFilteringParametersListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; @@ -23,6 +24,7 @@ */ class TransformFilteringParametersListenerTest extends TestCase { + /** @var TransformFilteringParametersListener */ private $listener; protected function setUp() @@ -30,56 +32,70 @@ protected function setUp() $this->listener = new TransformFilteringParametersListener(); } - public function testOnKernelRequestWithInvalidFormat() + public function testWithInvalidFormat() { $expectedRequest = new Request(); $expectedRequest->setRequestFormat('badformat'); $request = $expectedRequest->duplicate(); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequestWithInvalidFilter() + public function testWithInvalidFilter() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy = $this->prophesize(EventInterface::class); $expectedRequest = new Request(); $expectedRequest->setRequestFormat('jsonapi'); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); $expectedRequest = $expectedRequest->duplicate(['filter' => 'foo']); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequest() + public function testWithValidFilter() { $request = new Request(['filter' => ['foo' => 'bar', 'baz' => 'qux']]); $request->setRequestFormat('jsonapi'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $expectedRequest = new Request(['filter' => ['foo' => 'bar', 'baz' => 'qux']], [], ['_api_filters' => ['foo' => 'bar', 'baz' => 'qux']]); $expectedRequest->setRequestFormat('jsonapi'); $this->assertEquals($expectedRequest, $request); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\JsonApi\EventListener\TransformFilteringParametersListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); + + $this->listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/JsonApi/EventListener/TransformPaginationParametersListenerTest.php b/tests/JsonApi/EventListener/TransformPaginationParametersListenerTest.php index 54ae4b9fa35..8fa50cf6f78 100644 --- a/tests/JsonApi/EventListener/TransformPaginationParametersListenerTest.php +++ b/tests/JsonApi/EventListener/TransformPaginationParametersListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; @@ -23,6 +24,7 @@ */ class TransformPaginationParametersListenerTest extends TestCase { + /** @var TransformPaginationParametersListener */ private $listener; protected function setUp() @@ -30,52 +32,52 @@ protected function setUp() $this->listener = new TransformPaginationParametersListener(); } - public function testOnKernelRequestWithInvalidFormat() + public function testWithInvalidFormat() { $expectedRequest = new Request(); $expectedRequest->setRequestFormat('badformat'); $request = $expectedRequest->duplicate(); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequestWithInvalidPage() + public function testWithInvalidPage() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy = $this->prophesize(EventInterface::class); $expectedRequest = new Request(); $expectedRequest->setRequestFormat('jsonapi'); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); $expectedRequest = $expectedRequest->duplicate(['page' => 'foo']); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequest() + public function testWithValidFilter() { $request = new Request(['page' => ['size' => 5, 'number' => 3, 'error' => -1]]); $request->setRequestFormat('jsonapi'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $filters = ['size' => 5, 'number' => 3, 'error' => -1]; @@ -84,4 +86,18 @@ public function testOnKernelRequest() $this->assertEquals($expectedRequest, $request); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\JsonApi\EventListener\TransformPaginationParametersListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); + + $this->listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/JsonApi/EventListener/TransformSortingParametersListenerTest.php b/tests/JsonApi/EventListener/TransformSortingParametersListenerTest.php index d1d9f51bf34..310bb990b80 100644 --- a/tests/JsonApi/EventListener/TransformSortingParametersListenerTest.php +++ b/tests/JsonApi/EventListener/TransformSortingParametersListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\JsonApi\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; @@ -23,6 +24,7 @@ */ class TransformSortingParametersListenerTest extends TestCase { + /** @var TransformSortingParametersListener */ private $listener; protected function setUp() @@ -30,56 +32,70 @@ protected function setUp() $this->listener = new TransformSortingParametersListener(); } - public function testOnKernelRequestWithInvalidFormat() + public function testWithInvalidFormat() { $expectedRequest = new Request(); $expectedRequest->setRequestFormat('badformat'); $request = $expectedRequest->duplicate(); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequestWithInvalidFilter() + public function testWithInvalidFilter() { - $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy = $this->prophesize(EventInterface::class); $expectedRequest = new Request(); $expectedRequest->setRequestFormat('jsonapi'); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); $expectedRequest = $expectedRequest->duplicate(['sort' => ['foo', '-bar']]); $request = $expectedRequest->duplicate(); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $eventProphecy->getContext()->willReturn(['request' => $request]); + $this->listener->handleEvent($eventProphecy->reveal()); $this->assertEquals($expectedRequest, $request); } - public function testOnKernelRequest() + public function testWithValidFilter() { $request = new Request(['sort' => 'foo,-bar,-baz,qux']); $request->setRequestFormat('jsonapi'); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); - $this->listener->onKernelRequest($eventProphecy->reveal()); + $this->listener->handleEvent($eventProphecy->reveal()); $expectedRequest = new Request(['sort' => 'foo,-bar,-baz,qux'], [], ['_api_filters' => ['order' => ['foo' => 'asc', 'bar' => 'desc', 'baz' => 'desc', 'qux' => 'asc']]]); $expectedRequest->setRequestFormat('jsonapi'); $this->assertEquals($expectedRequest, $request); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\JsonApi\EventListener\TransformSortingParametersListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request())->shouldBeCalled(); + + $this->listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php index 7ab4b7d6a51..b76e37ce99e 100644 --- a/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php +++ b/tests/Mercure/EventListener/AddLinkHeaderListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\Mercure\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; @@ -39,10 +40,10 @@ public function testAddLinkHeader(string $expected, Request $request) $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); - $eventProphecy = $this->prophesize(FilterResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); - $listener->onKernelResponse($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertSame($expected, (new HttpHeaderSerializer())->serialize($request->attributes->get('_links')->getLinks())); } @@ -65,10 +66,10 @@ public function testDoNotAddHeader(Request $request) $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); - $eventProphecy = $this->prophesize(FilterResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request])->shouldBeCalled(); - $listener->onKernelResponse($eventProphecy->reveal()); + $listener->handleEvent($eventProphecy->reveal()); $this->assertNull($request->attributes->get('_links')); } @@ -80,4 +81,23 @@ public function doNotAddProvider(): array [new Request([], [], ['_api_resource_class' => Dummy::class])], ]; } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener::onKernelResponse() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\FilterResponseEvent" as argument of "ApiPlatform\Core\Mercure\EventListener\AddLinkHeaderListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelResponse() + { + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceMetadataFactoryProphecy->create(Dummy::class)->willReturn(new ResourceMetadata(null, null, null, null, null, ['mercure' => true])); + + $listener = new AddLinkHeaderListener($resourceMetadataFactoryProphecy->reveal(), 'https://demo.mercure.rocks/hub'); + + $eventProphecy = $this->prophesize(FilterResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request()); + + $listener->onKernelResponse($eventProphecy->reveal()); + } } diff --git a/tests/Security/EventListener/DenyAccessListenerTest.php b/tests/Security/EventListener/DenyAccessListenerTest.php index 63de9ddb29d..973bc22d93f 100644 --- a/tests/Security/EventListener/DenyAccessListenerTest.php +++ b/tests/Security/EventListener/DenyAccessListenerTest.php @@ -13,6 +13,7 @@ namespace ApiPlatform\Core\Tests\Security\EventListener; +use ApiPlatform\Core\Event\EventInterface; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Security\EventListener\DenyAccessListener; @@ -38,8 +39,8 @@ public function testNoResourceClass() { $request = new Request(); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); @@ -47,15 +48,15 @@ public function testNoResourceClass() $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); $listener = $this->getListener($resourceMetadataFactory); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testNoIsGrantedAttribute() { $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(); @@ -64,7 +65,7 @@ public function testNoIsGrantedAttribute() $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $listener = $this->getListener($resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testIsGranted() @@ -72,8 +73,8 @@ public function testIsGranted() $data = new \stdClass(); $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', 'data' => $data]); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -85,7 +86,7 @@ public function testIsGranted() $resourceAccessCheckerProphecy->isGranted('Foo', 'has_role("ROLE_ADMIN")', Argument::type('array'))->willReturn(true)->shouldBeCalled(); $listener = $this->getListener($resourceMetadataFactoryProphecy->reveal(), $resourceAccessCheckerProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testIsNotGranted() @@ -94,8 +95,8 @@ public function testIsNotGranted() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -107,7 +108,7 @@ public function testIsNotGranted() $resourceAccessCheckerProphecy->isGranted('Foo', 'has_role("ROLE_ADMIN")', Argument::type('array'))->willReturn(false)->shouldBeCalled(); $listener = $this->getListener($resourceMetadataFactoryProphecy->reveal(), $resourceAccessCheckerProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } public function testAccessControlMessage() @@ -117,8 +118,8 @@ public function testAccessControlMessage() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")', 'access_control_message' => 'You are not admin.']); @@ -130,7 +131,7 @@ public function testAccessControlMessage() $resourceAccessCheckerProphecy->isGranted('Foo', 'has_role("ROLE_ADMIN")', Argument::type('array'))->willReturn(false)->shouldBeCalled(); $listener = $this->getListener($resourceMetadataFactoryProphecy->reveal(), $resourceAccessCheckerProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } /** @@ -141,8 +142,8 @@ public function testIsGrantedLegacy() $data = new \stdClass(); $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get', 'data' => $data]); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -154,7 +155,7 @@ public function testIsGrantedLegacy() $expressionLanguageProphecy->evaluate('has_role("ROLE_ADMIN")', Argument::type('array'))->willReturn(true)->shouldBeCalled(); $listener = $this->getLegacyListener($resourceMetadataFactoryProphecy->reveal(), $expressionLanguageProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } /** @@ -166,8 +167,8 @@ public function testIsNotGrantedLegacy() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -179,7 +180,7 @@ public function testIsNotGrantedLegacy() $expressionLanguageProphecy->evaluate('has_role("ROLE_ADMIN")', Argument::type('array'))->willReturn(false)->shouldBeCalled(); $listener = $this->getLegacyListener($resourceMetadataFactoryProphecy->reveal(), $expressionLanguageProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } /** @@ -191,8 +192,8 @@ public function testSecurityComponentNotAvailable() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -201,7 +202,7 @@ public function testSecurityComponentNotAvailable() $resourceMetadataFactoryProphecy->create('Foo')->willReturn($resourceMetadata)->shouldBeCalled(); $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } /** @@ -213,8 +214,8 @@ public function testExpressionLanguageNotInstalled() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -227,7 +228,7 @@ public function testExpressionLanguageNotInstalled() $tokenStorageProphecy->getToken()->willReturn($this->prophesize(TokenInterface::class)->reveal()); $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal(), null, $authenticationTrustResolverProphecy->reveal(), null, $tokenStorageProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } /** @@ -239,8 +240,8 @@ public function testNotBehindAFirewall() $request = new Request([], [], ['_api_resource_class' => 'Foo', '_api_collection_operation_name' => 'get']); - $eventProphecy = $this->prophesize(GetResponseEvent::class); - $eventProphecy->getRequest()->willReturn($request)->shouldBeCalled(); + $eventProphecy = $this->prophesize(EventInterface::class); + $eventProphecy->getContext()->willReturn(['request' => $request]); $event = $eventProphecy->reveal(); $resourceMetadata = new ResourceMetadata(null, null, null, null, null, ['access_control' => 'has_role("ROLE_ADMIN")']); @@ -252,7 +253,7 @@ public function testNotBehindAFirewall() $tokenStorageProphecy = $this->prophesize(TokenStorageInterface::class); $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal(), null, $authenticationTrustResolverProphecy->reveal(), null, $tokenStorageProphecy->reveal()); - $listener->onKernelRequest($event); + $listener->handleEvent($event); } private function getListener(ResourceMetadataFactoryInterface $resourceMetadataFactory, ResourceAccessCheckerInterface $resourceAccessChecker = null) @@ -289,4 +290,22 @@ private function getLegacyListener(ResourceMetadataFactoryInterface $resourceMet $authorizationCheckerInterface->reveal() ); } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Security\EventListener\DenyAccessListener::onKernelRequest() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseEvent" as argument of "ApiPlatform\Core\Security\EventListener\DenyAccessListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelRequest() + { + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + $resourceAccessCheckerProphecy = $this->prophesize(ResourceAccessCheckerInterface::class); + + $eventProphecy = $this->prophesize(GetResponseEvent::class); + $eventProphecy->getRequest()->willReturn(new Request()); + + $listener = new DenyAccessListener($resourceMetadataFactoryProphecy->reveal(), $resourceAccessCheckerProphecy->reveal()); + $listener->onKernelRequest($eventProphecy->reveal()); + } } diff --git a/tests/Validator/EventListener/ValidateListenerTest.php b/tests/Validator/EventListener/ValidateListenerTest.php index 6ed24118185..778645d965d 100644 --- a/tests/Validator/EventListener/ValidateListenerTest.php +++ b/tests/Validator/EventListener/ValidateListenerTest.php @@ -13,6 +13,8 @@ namespace ApiPlatform\Core\Tests\Validator\EventListener; +use ApiPlatform\Core\Event\EventInterface; +use ApiPlatform\Core\Event\RespondEvent; use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface; use ApiPlatform\Core\Metadata\Resource\ResourceMetadata; use ApiPlatform\Core\Tests\Fixtures\DummyEntity; @@ -22,7 +24,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; /** * @author Samuel ROZE @@ -45,11 +46,11 @@ public function testNotAnApiPlatformRequest() $request = new Request(); $request->setMethod('POST'); - $event = $this->prophesize(GetResponseForControllerResultEvent::class); - $event->getRequest()->willReturn($request)->shouldBeCalled(); + $event = $this->prophesize(EventInterface::class); + $event->getContext()->willReturn(['request' => $request])->shouldBeCalled(); $listener = new ValidateListener($validator, $resourceMetadataFactory); - $listener->onKernelView($event->reveal()); + $listener->handleEvent($event->reveal()); } public function testValidatorIsCalled() @@ -64,7 +65,7 @@ public function testValidatorIsCalled() list($resourceMetadataFactory, $event) = $this->createEventObject($expectedValidationGroups, $data); $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); + $validationViewListener->handleEvent($event); } public function testDoNotCallWhenReceiveFlagIsFalse() @@ -79,7 +80,7 @@ public function testDoNotCallWhenReceiveFlagIsFalse() list($resourceMetadataFactory, $event) = $this->createEventObject($expectedValidationGroups, $data, false); $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); + $validationViewListener->handleEvent($event); } public function testThrowsValidationExceptionWithViolationsFound() @@ -96,7 +97,25 @@ public function testThrowsValidationExceptionWithViolationsFound() list($resourceMetadataFactory, $event) = $this->createEventObject($expectedValidationGroups, $data); $validationViewListener = new ValidateListener($validator, $resourceMetadataFactory); - $validationViewListener->onKernelView($event); + $validationViewListener->handleEvent($event); + } + + /** + * @group legacy + * + * @expectedDeprecation The method ApiPlatform\Core\Validator\EventListener\ValidateListener::onKernelView() is deprecated since 2.5 and will be removed in 3.0. + * @expectedDeprecation Passing an instance of "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" as argument of "ApiPlatform\Core\Validator\EventListener\ValidateListener::handleEvent" is deprecated since 2.5 and will not be possible anymore in 3.0. Pass an instance of "ApiPlatform\Core\Event\EventInterface" instead. + */ + public function testLegacyOnKernelView() + { + $validatorProphecy = $this->prophesize(ValidatorInterface::class); + $resourceMetadataFactoryProphecy = $this->prophesize(ResourceMetadataFactoryInterface::class); + + $eventProphecy = $this->prophesize(GetResponseForControllerResultEvent::class); + $eventProphecy->getRequest()->willReturn(new Request()); + + $listener = new ValidateListener($validatorProphecy->reveal(), $resourceMetadataFactoryProphecy->reveal()); + $listener->onKernelView($eventProphecy->reveal()); } private function createEventObject($expectedValidationGroups, $data, bool $receive = true): array @@ -111,7 +130,6 @@ private function createEventObject($expectedValidationGroups, $data, bool $recei } $resourceMetadataFactory = $resourceMetadataFactoryProphecy->reveal(); - $kernel = $this->prophesize(HttpKernelInterface::class)->reveal(); $request = new Request([], [], [ '_api_resource_class' => DummyEntity::class, '_api_item_operation_name' => 'create', @@ -121,7 +139,7 @@ private function createEventObject($expectedValidationGroups, $data, bool $recei ]); $request->setMethod('POST'); - $event = new GetResponseForControllerResultEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $data); + $event = new RespondEvent($data, ['request' => $request]); return [$resourceMetadataFactory, $event]; }