From fcf42961363f23635d0a7627ec7ed1c85ddb0c7a Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Wed, 19 Aug 2020 17:41:10 +0200 Subject: [PATCH] fix(filters): GET request support in ApiRequestHanler After a some fixes and refactoring the filter system were not working anymore. This commit fixes the problem. Please notice that it's not possible to send content in GET. This is invalid on REST POV but could be required in some extremely rare situation. I suggest to redefine the RequestApiHandler in those cases. --- features/crud.feature | 31 ++++++++++++++++ src/Form/ApiRequestHandler.php | 6 +++ tests/Melodiia/Form/ApiRequestHandlerTest.php | 11 ++++++ tests/TestApplication/config/config.yaml | 3 ++ .../src/Filters/TodoContainFilter.php | 37 +++++++++++++++++++ 5 files changed, 88 insertions(+) create mode 100644 tests/TestApplication/src/Filters/TodoContainFilter.php diff --git a/features/crud.feature b/features/crud.feature index 1d802f5..6e83822 100644 --- a/features/crud.feature +++ b/features/crud.feature @@ -59,3 +59,34 @@ Feature: "content": "hello" } """ + + Scenario: filter todo + Given there are some todos + When I make a GET request on "/todos?q=ba" + Then the last response contains: + """ + { + "meta": { + "totalPages": 1, + "totalResults": 2, + "currentPage": 1, + "maxPerPage": 30 + }, + "links": { + "prev": null, + "next": null, + "last": "http://localhost/todos?q=ba", + "first": "http://localhost/todos?q=ba" + }, + "data": [ + { + "id": 2, + "content": "bar" + }, + { + "id": 3, + "content": "baz" + } + ] + } + """ diff --git a/src/Form/ApiRequestHandler.php b/src/Form/ApiRequestHandler.php index 4dfe78c..67b3979 100644 --- a/src/Form/ApiRequestHandler.php +++ b/src/Form/ApiRequestHandler.php @@ -19,6 +19,12 @@ public function handleRequest(FormInterface $form, $request = null) throw new UnexpectedTypeException($request, 'Symfony\Component\HttpFoundation\Request'); } + if ('GET' === $request->getMethod()) { + $form->submit($request->query->all()); + + return; + } + $clearMissing = $form->getConfig()->getOption(ApiType::CLEAR_MISSING_OPTION); if (null === $clearMissing) { $clearMissing = !in_array($request->getMethod(), ['POST', 'PUT']); diff --git a/tests/Melodiia/Form/ApiRequestHandlerTest.php b/tests/Melodiia/Form/ApiRequestHandlerTest.php index dcc8674..c17c60e 100644 --- a/tests/Melodiia/Form/ApiRequestHandlerTest.php +++ b/tests/Melodiia/Form/ApiRequestHandlerTest.php @@ -11,6 +11,7 @@ use Symfony\Component\Form\FormConfigInterface; use Symfony\Component\Form\FormError; use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; class ApiRequestHandlerTest extends TestCase @@ -81,4 +82,14 @@ public function testICanChangeClearMissingOption() $this->subject->handleRequest($this->form->reveal(), $this->request->reveal()); } + + public function testItSupportsGetRequests() + { + $query = new ParameterBag(['hello' => 'foo']); + $this->form->submit(['hello' => 'foo'])->shouldBeCalled(); + $this->request->getMethod()->willReturn('GET'); + $this->request->query = $query; + + $this->subject->handleRequest($this->form->reveal(), $this->request->reveal()); + } } diff --git a/tests/TestApplication/config/config.yaml b/tests/TestApplication/config/config.yaml index baf2573..83cb231 100644 --- a/tests/TestApplication/config/config.yaml +++ b/tests/TestApplication/config/config.yaml @@ -36,3 +36,6 @@ services: TestApplication\Controller\TodoContainsAction: tags: ['controller.service_arguments'] + + TestApplication\Filters\TodoContainFilter: + autoconfigure: true diff --git a/tests/TestApplication/src/Filters/TodoContainFilter.php b/tests/TestApplication/src/Filters/TodoContainFilter.php new file mode 100644 index 0000000..60773d6 --- /dev/null +++ b/tests/TestApplication/src/Filters/TodoContainFilter.php @@ -0,0 +1,37 @@ +get('q')->getData(); + if (!empty($q)) { + $queryBuilder->andWhere($queryBuilder->expr()->like('item.content', ':like')); + $queryBuilder->setParameter('like', '%' . $q . '%'); + } + } + + public function supports(string $class): bool + { + return Todo::class === $class; + } + + public function buildForm(FormBuilderInterface $formBuilder): void + { + $formBuilder->add('q', TextType::class); + } +}