From 915f440cad6dbf75f480dba8d8c80208bf95255d Mon Sep 17 00:00:00 2001 From: vagrant Date: Tue, 6 Dec 2011 10:41:41 -0800 Subject: [PATCH 1/3] [HttpKernel] removed BC breaks, introduced new TerminableInterface --- .../HttpKernel/Event/PostResponseEvent.php | 6 ++-- .../HttpKernel/HttpCache/HttpCache.php | 11 +++--- .../Component/HttpKernel/HttpKernel.php | 13 ------- .../HttpKernel/HttpKernelInterface.php | 7 ---- src/Symfony/Component/HttpKernel/Kernel.php | 29 +++++++-------- .../HttpKernel/TerminableInterface.php | 36 +++++++++++++++++++ .../HttpKernel/HttpCache/HttpCacheTest.php | 33 +++++++++++++++++ .../Component/HttpKernel/HttpKernelTest.php | 14 -------- 8 files changed, 91 insertions(+), 58 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/TerminableInterface.php diff --git a/src/Symfony/Component/HttpKernel/Event/PostResponseEvent.php b/src/Symfony/Component/HttpKernel/Event/PostResponseEvent.php index ed7d5f9670cd4..6e363b552cc62 100644 --- a/src/Symfony/Component/HttpKernel/Event/PostResponseEvent.php +++ b/src/Symfony/Component/HttpKernel/Event/PostResponseEvent.php @@ -23,7 +23,7 @@ class PostResponseEvent extends Event { /** * The kernel in which this event was thrown - * @var Symfony\Component\HttpKernel\HttpKernelInterface + * @var HttpKernelInterface */ private $kernel; @@ -35,10 +35,10 @@ public function __construct(HttpKernelInterface $kernel) /** * Returns the kernel in which this event was thrown * - * @return Symfony\Component\HttpKernel\HttpKernelInterface + * @return HttpKernelInterface */ public function getKernel() { return $this->kernel; } -} \ No newline at end of file +} diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 9bf5d21ad12b2..827fa3de8ee8e 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -16,6 +16,7 @@ namespace Symfony\Component\HttpKernel\HttpCache; use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -26,7 +27,7 @@ * * @api */ -class HttpCache implements HttpKernelInterface +class HttpCache implements HttpKernelInterface, TerminableInterface { private $kernel; private $store; @@ -216,15 +217,17 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } /** - * Terminates a request/response cycle + * Terminates a request/response cycle. * - * Should be called before shutdown, but after sending the response + * Should be called after sending the response and before shutting down the kernel. * * @api */ public function terminate() { - $this->kernel->terminate(); + if ($this->getKernel() instanceof TerminableInterface) { + $this->getKernel()->terminate(); + } } /** diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index ac04ac6a9a63a..7474ca4a0e652 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -79,19 +79,6 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } } - /** - * Terminates a request/response cycle - * - * Should be called before shutdown, but after sending the response - * - * @api - */ - public function terminate() - { - $event = new PostResponseEvent($this); - $this->dispatcher->dispatch(KernelEvents::TERMINATE, $event); - } - /** * Handles a request to convert it to a response. * diff --git a/src/Symfony/Component/HttpKernel/HttpKernelInterface.php b/src/Symfony/Component/HttpKernel/HttpKernelInterface.php index 086e7dc461fb2..a2a0f1c5fd597 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernelInterface.php +++ b/src/Symfony/Component/HttpKernel/HttpKernelInterface.php @@ -44,11 +44,4 @@ interface HttpKernelInterface * @api */ function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true); - - /** - * Terminates a request/response cycle - * - * Should be called after sending the response - */ - function terminate(); } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 098f830323cfc..e9ebd844aff0a 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -44,7 +44,7 @@ * * @api */ -abstract class Kernel implements KernelInterface +abstract class Kernel implements KernelInterface, TerminableInterface { protected $bundles; protected $bundleMap; @@ -134,6 +134,17 @@ public function boot() $this->booted = true; } + /** + * Terminates a request/response cycle. + * + * Should be called after sending the response and before shutting down the kernel. + * + * @api + */ + public function terminate() + { + } + /** * Shutdowns the kernel. * @@ -171,22 +182,6 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ return $this->getHttpKernel()->handle($request, $type, $catch); } - /** - * Terminates a request/response cycle - * - * Should be called before shutdown, but after sending the response - * - * @api - */ - public function terminate() - { - if (false === $this->booted) { - throw new \LogicException('The kernel has been shutdown already'); - } - - $this->getHttpKernel()->terminate(); - } - /** * Gets a http kernel from the container * diff --git a/src/Symfony/Component/HttpKernel/TerminableInterface.php b/src/Symfony/Component/HttpKernel/TerminableInterface.php new file mode 100644 index 0000000000000..4f2b0b1744eff --- /dev/null +++ b/src/Symfony/Component/HttpKernel/TerminableInterface.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Terminable extends the Kernel request/response cycle with dispatching a post + * response event after sending the response and before shutting down the kernel. + * + * @author Jordi Boggiano + * @author Pierre Minnieur + * + * @api + */ +interface TerminableInterface +{ + /** + * Terminates a request/response cycle. + * + * Should be called after sending the response and before shutting down the kernel. + * + * @api + */ + function terminate(); +} diff --git a/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php b/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php index 512d6ee8ee081..6771362d402bb 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php @@ -11,10 +11,43 @@ namespace Symfony\Tests\Component\HttpKernel\HttpCache; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; +use Symfony\Component\HttpKernel\HttpCache\StoreInterface; +use Symfony\Component\HttpKernel\HttpKernelInterface; require_once __DIR__.'/HttpCacheTestCase.php'; class HttpCacheTest extends HttpCacheTestCase { + public function testTerminateDelegatesTerminationOnlyForTerminableInterface() + { + $storeMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface') + ->disableOriginalConstructor() + ->getMock(); + + // does not implement TerminableInterface + $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpKernelInterface') + ->disableOriginalConstructor() + ->getMock(); + + $kernelMock->expects($this->never()) + ->method('terminate'); + + $kernel = new HttpCache($kernelMock, $storeMock); + $kernel->terminate(); + + // does implement TerminableInterface + $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel') + ->disableOriginalConstructor() + ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration')) + ->getMock(); + + $kernelMock->expects($this->once()) + ->method('terminate'); + + $kernel = new HttpCache($kernelMock, $storeMock); + $kernel->terminate(); + } + public function testPassesOnNonGetHeadRequests() { $this->setNextResponse(200); diff --git a/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php b/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php index 8954cee86bdaa..149cbeb8dea6b 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php @@ -164,20 +164,6 @@ public function testHandleWithAResponseListener() $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); } - public function testTerminate() - { - $dispatcher = new EventDispatcher(); - $kernel = new HttpKernel($dispatcher, $this->getResolver()); - $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel) { - $called = true; - $capturedKernel = $event->getKernel(); - }); - - $kernel->terminate(); - $this->assertTrue($called); - $this->assertEquals($kernel, $capturedKernel); - } - protected function getResolver($controller = null) { if (null === $controller) { From 2a61714df690ab828380b6201dc260efb0b86921 Mon Sep 17 00:00:00 2001 From: vagrant Date: Tue, 6 Dec 2011 11:18:45 -0800 Subject: [PATCH 2/3] [HttpKernel] added PostResponseEvent dispatching to HttpKernel --- .../Component/HttpKernel/HttpKernel.php | 15 ++++- src/Symfony/Component/HttpKernel/Kernel.php | 7 +++ .../HttpKernel/HttpCache/HttpCacheTest.php | 2 +- .../Component/HttpKernel/HttpKernelTest.php | 14 +++++ .../Tests/Component/HttpKernel/KernelTest.php | 60 +++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 7474ca4a0e652..4a3df45686e5b 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -30,7 +30,7 @@ * * @api */ -class HttpKernel implements HttpKernelInterface +class HttpKernel implements HttpKernelInterface, TerminableInterface { private $dispatcher; private $resolver; @@ -79,6 +79,19 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } } + /** + * Terminates a request/response cycle. + * + * Should be called after sending the response and before shutting down the kernel. + * + * @api + */ + public function terminate() + { + $event = new PostResponseEvent($this); + $this->dispatcher->dispatch(KernelEvents::TERMINATE, $event); + } + /** * Handles a request to convert it to a response. * diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index e9ebd844aff0a..e8efa691da354 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -143,6 +143,13 @@ public function boot() */ public function terminate() { + if (false === $this->booted) { + return; + } + + if ($this->getHttpKernel() instanceof TerminableInterface) { + $this->getHttpKernel()->terminate(); + } } /** diff --git a/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php b/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php index 6771362d402bb..18180f38fa2c8 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/HttpCache/HttpCacheTest.php @@ -35,7 +35,7 @@ public function testTerminateDelegatesTerminationOnlyForTerminableInterface() $kernel = new HttpCache($kernelMock, $storeMock); $kernel->terminate(); - // does implement TerminableInterface + // implements TerminableInterface $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel') ->disableOriginalConstructor() ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration')) diff --git a/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php b/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php index 149cbeb8dea6b..8954cee86bdaa 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/HttpKernelTest.php @@ -164,6 +164,20 @@ public function testHandleWithAResponseListener() $this->assertEquals('foo', $kernel->handle(new Request())->getContent()); } + public function testTerminate() + { + $dispatcher = new EventDispatcher(); + $kernel = new HttpKernel($dispatcher, $this->getResolver()); + $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel) { + $called = true; + $capturedKernel = $event->getKernel(); + }); + + $kernel->terminate(); + $this->assertTrue($called); + $this->assertEquals($kernel, $capturedKernel); + } + protected function getResolver($controller = null) { if (null === $controller) { diff --git a/tests/Symfony/Tests/Component/HttpKernel/KernelTest.php b/tests/Symfony/Tests/Component/HttpKernel/KernelTest.php index 2572044b43360..fea6e1199dbb0 100644 --- a/tests/Symfony/Tests/Component/HttpKernel/KernelTest.php +++ b/tests/Symfony/Tests/Component/HttpKernel/KernelTest.php @@ -652,6 +652,66 @@ public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself() $kernel->initializeBundles(); } + public function testTerminateReturnsSilentlyIfKernelIsNotBooted() + { + $kernel = $this->getMockBuilder('Symfony\Tests\Component\HttpKernel\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->never()) + ->method('getHttpKernel'); + + $kernel->setIsBooted(false); + $kernel->terminate(); + } + + public function testTerminateDelegatesTerminationOnlyForTerminableInterface() + { + // does not implement TerminableInterface + $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface') + ->disableOriginalConstructor() + ->getMock(); + + $httpKernelMock + ->expects($this->never()) + ->method('terminate'); + + $kernel = $this->getMockBuilder('Symfony\Tests\Component\HttpKernel\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->once()) + ->method('getHttpKernel') + ->will($this->returnValue($httpKernelMock)); + + $kernel->setIsBooted(true); + $kernel->terminate(); + + // implements TerminableInterface + $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') + ->disableOriginalConstructor() + ->setMethods(array('terminate')) + ->getMock(); + + $httpKernelMock + ->expects($this->once()) + ->method('terminate'); + + $kernel = $this->getMockBuilder('Symfony\Tests\Component\HttpKernel\KernelForTest') + ->disableOriginalConstructor() + ->setMethods(array('getHttpKernel')) + ->getMock(); + + $kernel->expects($this->exactly(2)) + ->method('getHttpKernel') + ->will($this->returnValue($httpKernelMock)); + + $kernel->setIsBooted(true); + $kernel->terminate(); + } + protected function getBundle($dir = null, $parent = null, $className = null, $bundleName = null) { $bundle = $this From 9f4391f9a17a4f3c8d2d39bb2c9db1ac6eeb40d3 Mon Sep 17 00:00:00 2001 From: vagrant Date: Tue, 6 Dec 2011 11:38:33 -0800 Subject: [PATCH 3/3] [HttpKernel] fixed DocBlocks --- src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php | 4 +--- src/Symfony/Component/HttpKernel/HttpKernel.php | 4 +--- src/Symfony/Component/HttpKernel/Kernel.php | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 827fa3de8ee8e..364883150a686 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -217,9 +217,7 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } /** - * Terminates a request/response cycle. - * - * Should be called after sending the response and before shutting down the kernel. + * {@inheritdoc} * * @api */ diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 4a3df45686e5b..fe9e52701da20 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -80,9 +80,7 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ } /** - * Terminates a request/response cycle. - * - * Should be called after sending the response and before shutting down the kernel. + * {@inheritdoc} * * @api */ diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index e8efa691da354..c044826807db5 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -135,9 +135,7 @@ public function boot() } /** - * Terminates a request/response cycle. - * - * Should be called after sending the response and before shutting down the kernel. + * {@inheritdoc} * * @api */