8000 [WIP] Kernel refactor by fabpot · Pull Request #6459 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[WIP] Kernel refactor #6459

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 11, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions UPGRADE-2.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,9 @@
After:

```
{% render url('post_list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
{% render controller('BlogBundle:Post:list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
```

where `post_list` is the route name for the `BlogBundle:Post:list` controller.

### HttpFoundation

* The MongoDbSessionHandler default field names and timestamp type have changed.
Expand Down Expand Up @@ -409,7 +407,12 @@
<?php echo $view['actions']->render($view['router']->generate('post_list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
```

where `post_list` is the route name for the `BlogBundle:Post:list` controller.
where `post_list` is the route name for the `BlogBundle:Post:list`
controller, or if you don't want to create a route:

```
<?php echo $view['actions']->render(new ControllerReference('BlogBundle:Post:list', array('limit' => 2)), array('alt' => 'BlogBundle:Post:error')) ?>
```

#### Configuration

Expand Down
6 changes: 4 additions & 2 deletions src/Symfony/Bridge/Twig/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ CHANGELOG
2.2.0
-----

* [BC BREAK] restricted the `render` tag to only accept URIs as reference (the signature changed)
* added a render function to render a request
* added a `controller` function to help generating controller references
* added a `render_esi` and a `render_hinclude` function
* [BC BREAK] restricted the `render` tag to only accept URIs or ControllerReference instances (the signature changed)
* added a `render` function to render a request
* The `app` global variable is now injected even when using the twig service directly.
* Added an optional parameter to the `path` and `url` function which allows to generate
relative paths (e.g. "../parent-file") and scheme-relative URLs (e.g. "//example.com/dir/file").
Expand Down
62 changes: 22 additions & 40 deletions src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,83 +11,65 @@

namespace Symfony\Bridge\Twig\Extension;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\HttpContentRenderer;
use Symfony\Component\HttpKernel\Controller\ControllerReference;

/**
* Provides integration with the HttpKernel component.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HttpKernelExtension extends \Twig_Extension implements EventSubscriberInterface
class HttpKernelExtension extends \Twig_Extension
{
private $kernel;
private $request;
private $renderer;

/**
* Constructor.
*
* @param HttpKernelInterface $kernel A HttpKernelInterface install
* @param HttpContentRenderer $kernel A HttpContentRenderer instance
*/
public function __construct(HttpKernelInterface $kernel)
public function __construct(HttpContentRenderer $renderer)
{
$this->kernel = $kernel;
$this->renderer = $renderer;
}

public function getFunctions()
{
return array(
'render' => new \Twig_Function_Method($this, 'render', array('needs_environment' => true, 'is_safe' => array('html'))),
'render' => new \Twig_Function_Method($this, 'render', array('is_safe' => array('html'))),
'render_*' => new \Twig_Function_Method($this, 'renderStrategy', array('is_safe' => array('html'))),
'controller' => new \Twig_Function_Method($this, 'controller'),
);
}

/**
* Renders a URI.
*
* @param \Twig_Environment $twig A \Twig_Environment instance
* @param string $uri The URI to render
* @param string $uri A URI
* @param array $options An array of options
*
* @return string The Response content
*
* @throws \RuntimeException
* @see Symfony\Component\HttpKernel\HttpContentRenderer::render()
*/
public function render(\Twig_Environment $twig, $uri)
public function render($uri, $options = array())
{
if (null !== $this->request) {
$cookies = $this->request->cookies->all();
$server = $this->request->server->all();
} else {
$cookies = array();
$server = array();
}
$options = $this->renderer->fixOptions($options);

$subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server);
if (null !== $this->request && $this->request->getSession()) {
$subRequest->setSession($this->request->getSession());
}
$strategy = isset($options['strategy']) ? $options['strategy'] : 'default';
unset($options['strategy']);

$response = $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);

if (!$response->isSuccessful()) {
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
}

return $response->getContent();
return $this->renderer->render($uri, $strategy, $options);
}

public function onKernelRequest(GetResponseEvent $event)
public function renderStrategy($strategy, $uri, $options = array())
{
$this->request = $event->getRequest();
return $this->renderer->render($uri, $strategy, $options);
}

public static function getSubscribedEvents()
public function controller($controller, $attributes = array(), $query = array())
{
return array(
KernelEvents::REQUEST => array('onKernelRequest'),
);
return new ControllerReference($controller, $attributes, $query);
}

public function getName()
Expand Down
24 changes: 10 additions & 14 deletions src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@

use Symfony\Bridge\Twig\Extension\HttpKernelExtension;
use Symfony\Bridge\Twig\Tests\TestCase;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\HttpContentRenderer;

class HttpKernelExtensionTest extends TestCase
{
Expand All @@ -31,7 +30,7 @@ protected function setUp()

public function testRenderWithoutMasterRequest()
{
$kernel = $this->getKernel($this->returnValue(new Response('foo')));
$kernel = $this->getHttpContentRenderer($this->returnValue('foo'));

$this->assertEquals('foo', $this->renderTemplate($kernel));
}
Expand All @@ -41,7 +40,7 @@ public function testRenderWithoutMasterRequest()
*/
public function testRenderWithError()
{
$kernel = $this->getKernel($this->throwException(new \Exception('foo')));
$kernel = $this->getHttpContentRenderer($this->throwException(new \Exception('foo')));

$loader = new \Twig_Loader_Array(array('index' => '{{ render("foo") }}'));
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
Expand All @@ -50,23 +49,20 @@ public function testRenderWithError()
$this->renderTemplate($kernel);
}

protected function getKernel($return)
protected function getHttpContentRenderer($return)
{
$kernel = $this->getMock('Symfony\Component\HttpKernel\HttpKernelInterface');
$kernel
->expects($this->once())
->method('handle')
->will($return)
;
$strategy = $this->getMock('Symfony\\Component\\HttpKernel\\RenderingStrategy\\RenderingStrategyInterface');
$strategy->expects($this->once())->method('getName')->will($this->returnValue('default'));
$strategy->expects($this->once())->method('render')->will($return);

return $kernel;
return new HttpContentRenderer(array($strategy));
}

protected function renderTemplate(HttpKernelInterface $kernel, $template = '{{ render("foo") }}')
protected function renderTemplate(HttpContentRenderer $renderer, $template = '{{ render("foo") }}')
{
$loader = new \Twig_Loader_Array(array('index' => $template));
$twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false));
$twig->addExtension(new HttpKernelExtension($kernel));
$twig->addExtension(new HttpKernelExtension($renderer));

return $twig->render('index');
}
Expand Down
13 changes: 9 additions & 4 deletions src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ CHANGELOG
2.2.0
-----

* [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs as reference
* added a new `uri_signer` service to help sign URIs
* deprecated `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` and `Symfony\Bundle\FrameworkBundle\HttpKernel::forward()`
* deprecated the `Symfony\Bundle\FrameworkBundle\HttpKernel` class in favor of `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel`
* added support for adding new HTTP content rendering strategies (like ESI and Hinclude)
in the DIC via the `kernel.content_renderer_strategy` tag
* [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs or ControllerReference instances
* `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method signature changed and the first argument
must now be a URI (the `generateInternalUri()` method was removed)
* The internal routes have been removed (`Resources/config/routing/internal.xml`)
* The `render` method of the `actions` templating helper signature and arguments changed:
must now be a URI or a ControllerReference instance (the `generateInternalUri()` method was removed)
* The internal routes (`Resources/config/routing/internal.xml`) have been replaced with a new proxy route (`Resources/config/routing/proxy.xml`)
* The `render` method of the `actions` templating helper signature and arguments changed
* replaced Symfony\Bundle\FrameworkBundle\Controller\TraceableControllerResolver by Symfony\Component\HttpKernel\Controller\TraceableControllerResolver
* replaced Symfony\Component\HttpKernel\Debug\ContainerAwareTraceableEventDispatcher by Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher
* added Client::enableProfiler()
Expand Down
5 changes: 4 additions & 1 deletion src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ public function generateUrl($route, $parameters = array(), $referenceType = UrlG
*/
public function forward($controller, array $path = array(), array $query = array())
{
return $this->container->get('http_kernel')->forward($controller, $path, $query);
$path['_controller'] = $controller;
$subRequest = $this->container->get('request')->duplicate($query, null, $path);

return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;

use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;

/**
* Adds services tagged kernel.content_renderer_strategy as HTTP content rendering strategies.
*
* @author Fabien Potencier <fabien@symfony.com>
*/
class HttpRenderingStrategyPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
if (false === $container->hasDefinition('http_content_renderer')) {
return;
}

$definition = $container->getDefinition('http_content_renderer');
foreach (array_keys($container->findTaggedServiceIds('kernel.content_renderer_strategy')) as $id) {
// We must assume that the class value has been correctly filled, even if the service is created by a factory
$class = $container->getDefinition($id)->getClass();

$refClass = new \ReflectionClass($class);
$interface = 'Symfony\Component\HttpKernel\RenderingStrategy\RenderingStrategyInterface';
if (!$refClass->implementsInterface($interface)) {
throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
}

$definition->addMethodCall('addStrategy', array(new Reference($id)));
}
}
}
1241
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function load(array $configs, ContainerBuilder $container)

$loader->load('web.xml');
$loader->load('services.xml');
$loader->load('content_generator.xml');

// A translator must always be registered (as support is included by
// default in the Form component). If disabled, an identity translator
Expand Down
2 changes: 2 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CompilerDebugDumpPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\HttpRenderingStrategyPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
use Symfony\Component\DependencyInjection\Scope;
Expand Down Expand Up @@ -65,6 +66,7 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new AddCacheClearerPass());
$container->addCompilerPass(new TranslationExtractorPass());
$container->addCompilerPass(new TranslationDumperPass());
$container->addCompilerPass(new HttpRenderingStrategyPass(), PassConfig::TYPE_AFTER_REMOVING);

if ($container->getParameter('kernel.debug')) {
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
Expand Down
Loading
0