From 1134405ed53239dfcb71cefc075ef53d4df51cc3 Mon Sep 17 00:00:00 2001 From: Leo Feyer Date: Mon, 11 Jun 2018 17:55:49 +0200 Subject: [PATCH] Auto-clear the session form data (see #1550). Description ----------- See #1389. Commits ------- da6bfc57 Auto-clear the session form data (see #1389). 6847201f Fix a comment and add the unit tests. --- src/EventListener/ClearFormDataListener.php | 42 ++++++ src/Resources/config/listener.yml | 6 + .../ContaoCoreExtensionTest.php | 18 +++ .../ClearFormDataListenerTest.php | 132 ++++++++++++++++++ 4 files changed, 198 insertions(+) create mode 100644 src/EventListener/ClearFormDataListener.php create mode 100644 tests/EventListener/ClearFormDataListenerTest.php diff --git a/src/EventListener/ClearFormDataListener.php b/src/EventListener/ClearFormDataListener.php new file mode 100644 index 0000000000..430590777a --- /dev/null +++ b/src/EventListener/ClearFormDataListener.php @@ -0,0 +1,42 @@ +isMasterRequest()) { + return; + } + + $request = $event->getRequest(); + + if ($request->isMethod('POST')) { + return; + } + + if (null === ($session = $request->getSession()) || !$session->isStarted()) { + return; + } + + unset($_SESSION['FORM_DATA']); + } +} diff --git a/src/Resources/config/listener.yml b/src/Resources/config/listener.yml index 747e6d4481..bf8f957142 100644 --- a/src/Resources/config/listener.yml +++ b/src/Resources/config/listener.yml @@ -41,6 +41,12 @@ services: # and lower than the header replay header (defaults to 7) - { name: kernel.event_listener, event: kernel.request, method: onKernelRequest, priority: 6 } + contao.listener.clear_form_data: + class: Contao\CoreBundle\EventListener\ClearFormDataListener + tags: + # The priority must be higher than the one of the Symfony save session listener (defaults to -1000) + - { name: kernel.event_listener, event: kernel.response, method: onKernelResponse, priority: -768 } + contao.listener.command_scheduler: class: Contao\CoreBundle\EventListener\CommandSchedulerListener arguments: diff --git a/tests/DependencyInjection/ContaoCoreExtensionTest.php b/tests/DependencyInjection/ContaoCoreExtensionTest.php index a075033f40..59eef84e1e 100644 --- a/tests/DependencyInjection/ContaoCoreExtensionTest.php +++ b/tests/DependencyInjection/ContaoCoreExtensionTest.php @@ -35,6 +35,7 @@ use Contao\CoreBundle\EventListener\BackendLocaleListener; use Contao\CoreBundle\EventListener\BackendMenuListener; use Contao\CoreBundle\EventListener\BypassMaintenanceListener; +use Contao\CoreBundle\EventListener\ClearFormDataListener; use Contao\CoreBundle\EventListener\CommandSchedulerListener; use Contao\CoreBundle\EventListener\CsrfTokenCookieListener; use Contao\CoreBundle\EventListener\DoctrineSchemaListener; @@ -268,6 +269,23 @@ public function testRegistersTheBypassMaintenanceListener(): void $this->assertSame(6, $tags['kernel.event_listener'][0]['priority']); } + public function testRegistersTheClearFormDataListener(): void + { + $this->assertTrue($this->container->has('contao.listener.clear_form_data')); + + $definition = $this->container->getDefinition('contao.listener.clear_form_data'); + + $this->assertSame(ClearFormDataListener::class, $definition->getClass()); + $this->assertTrue($definition->isPrivate()); + + $tags = $definition->getTags(); + + $this->assertArrayHasKey('kernel.event_listener', $tags); + $this->assertSame('kernel.response', $tags['kernel.event_listener'][0]['event']); + $this->assertSame('onKernelResponse', $tags['kernel.event_listener'][0]['method']); + $this->assertSame(-768, $tags['kernel.event_listener'][0]['priority']); + } + public function testRegistersTheCommandSchedulerListener(): void { $this->assertTrue($this->container->has('contao.listener.command_scheduler')); diff --git a/tests/EventListener/ClearFormDataListenerTest.php b/tests/EventListener/ClearFormDataListenerTest.php new file mode 100644 index 0000000000..f04939166b --- /dev/null +++ b/tests/EventListener/ClearFormDataListenerTest.php @@ -0,0 +1,132 @@ +assertInstanceOf('Contao\CoreBundle\EventListener\ClearFormDataListener', $listener); + } + + public function testClearsTheFormData(): void + { + $session = $this->createMock(Session::class); + + $session + ->expects($this->once()) + ->method('isStarted') + ->willReturn(true) + ; + + $request = new Request(); + $request->setSession($session); + + $event = new FilterResponseEvent( + $this->createMock(KernelInterface::class), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); + + $_SESSION['FORM_DATA'] = ['foo' => 'bar']; + + $listener = new ClearFormDataListener(); + $listener->onKernelResponse($event); + + $this->assertArrayNotHasKey('FORM_DATA', $_SESSION); + } + + public function testDoesNotClearTheFormDataUponSubrequests(): void + { + $request = $this->createMock(Request::class); + + $request + ->expects($this->never()) + ->method('isMethod') + ; + + $event = new FilterResponseEvent( + $this->createMock(KernelInterface::class), + $request, + HttpKernelInterface::SUB_REQUEST, + new Response() + ); + + $listener = new ClearFormDataListener(); + $listener->onKernelResponse($event); + } + + public function testDoesNotClearTheFormDataUponPostRequests(): void + { + $session = $this->createMock(Session::class); + + $session + ->expects($this->never()) + ->method('isStarted') + ; + + $request = new Request(); + $request->setSession($session); + $request->setMethod('POST'); + + $event = new FilterResponseEvent( + $this->createMock(KernelInterface::class), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); + + $listener = new ClearFormDataListener(); + $listener->onKernelResponse($event); + } + + public function testDoesNotClearTheFormDataIfTheSessionIsNotStarted(): void + { + $session = $this->createMock(Session::class); + + $session + ->expects($this->once()) + ->method('isStarted') + ->willReturn(false) + ; + + $request = new Request(); + $request->setSession($session); + + $event = new FilterResponseEvent( + $this->createMock(KernelInterface::class), + $request, + HttpKernelInterface::MASTER_REQUEST, + new Response() + ); + + $_SESSION['FORM_DATA'] = ['foo' => 'bar']; + + $listener = new ClearFormDataListener(); + $listener->onKernelResponse($event); + + $this->assertSame(['foo' => 'bar'], $_SESSION['FORM_DATA']); + } +}