Explorar o código

[HttpKernel] Move request-stashing behavior to the Kernel class

Previously, HttpKernel performed request-stashing.  By moving this to the Kernel class, the request is now available immediately after the kernel becomes aware of it.  If the kernel is allowed to boot lazily (during the first call to handle()), this also allows an actual master Request to be available during booting.

The old "request" service definition (with a bogus class name) can be replaced with a factory-aware definition that retrieves the request directly from the kernel.
Jeremy Mikola %!s(int64=14) %!d(string=hai) anos
pai
achega
7eea4882db

+ 1 - 1
src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml

@@ -37,7 +37,7 @@
             your front controller (app.php) so that it passes an instance of
             YourRequestClass to the Kernel.
         -->
-        <service id="request" class="WillNeverBeCalled" />
+        <service id="request" factory-service="kernel" factory-method="getRequest" shared="false" />
 
         <service id="response" class="%response.class%" shared="false" />
     </services>

+ 20 - 1
src/Symfony/Component/HttpKernel/Kernel.php

@@ -45,6 +45,7 @@ abstract class Kernel implements HttpKernelInterface, \Serializable
     protected $booted;
     protected $name;
     protected $startTime;
+    protected $request;
 
     const VERSION = '2.0.0-DEV';
 
@@ -174,11 +175,29 @@ abstract class Kernel implements HttpKernelInterface, \Serializable
      */
     public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
     {
+        $masterRequest = HttpKernelInterface::MASTER_REQUEST === $type ? $request : $this->request;
+
+        $this->request = $request;
+
         if (false === $this->booted) {
             $this->boot();
         }
 
-        return $this->container->get('http_kernel')->handle($request, $type, $catch);
+        $response = $this->container->get('http_kernel')->handle($this->request, $type, $catch);
+
+        $this->request = $masterRequest;
+
+        return $response;
+    }
+
+    /**
+     * Gets the current request.
+     *
+     * @return Request
+     */
+    public function getRequest()
+    {
+        return $this->request;
     }
 
     /**

+ 63 - 0
tests/Symfony/Tests/Component/HttpKernel/KernelTest.php

@@ -12,6 +12,8 @@
 namespace Symfony\Tests\Component\HttpKernel;
 
 use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
 
 class KernelTest extends \PHPUnit_Framework_TestCase
@@ -22,6 +24,57 @@ class KernelTest extends \PHPUnit_Framework_TestCase
 
         $this->assertEquals('foo', $kernel->getSafeName());
     }
+
+    public function testHandleSetsTheRequest()
+    {
+        $masterRequest = Request::create('/');
+        $subRequest = Request::create('/');
+
+        $httpKernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
+            ->disableOriginalConstructor()
+            ->setMethods(array('handle'))
+            ->getMock();
+
+        $httpKernel->expects($this->at(0))
+            ->method('handle')
+            ->with($masterRequest);
+
+        $httpKernel->expects($this->at(1))
+            ->method('handle')
+            ->with($subRequest);
+
+        $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\Container')
+            ->disableOriginalConstructor()
+            ->setMethods(array('get'))
+            ->getMock();
+
+        $container->expects($this->exactly(2))
+            ->method('get')
+            ->with('http_kernel')
+            ->will($this->returnValue($httpKernel));
+
+        $kernel = $this->getMockBuilder('Symfony\Tests\Component\HttpKernel\KernelForTest')
+            ->setConstructorArgs(array('dev', true, '-foo-'))
+            ->setMethods(array('boot'))
+            ->getMock();
+
+        $kernel->setContainer($container);
+
+        $testCase = $this;
+        $bootCallback = function() use ($masterRequest, $kernel, $testCase) {
+            $kernel->setBooted(true);
+            $testCase->assertSame($masterRequest, $kernel->getRequest(), '->handle() sets the Request before booting');
+        };
+
+        $kernel->expects($this->once())
+            ->method('boot')
+            ->will($this->returnCallback($bootCallback));
+
+        $kernel->handle($masterRequest);
+        $kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
+
+        $this->assertSame($masterRequest, $kernel->getRequest(), '->handle() restores the master Request after handling a sub-request');
+    }
 }
 
 class KernelForTest extends Kernel
@@ -48,4 +101,14 @@ class KernelForTest extends Kernel
     public function registerContainerConfiguration(LoaderInterface $loader)
     {
     }
+
+    public function setBooted($booted)
+    {
+        $this->booted = $booted;
+    }
+
+    public function setContainer($container)
+    {
+        $this->container = $container;
+    }
 }