restricted to only URIs the first argument of the render tag
This commit is contained in:
parent
2c9083a6e0
commit
64d43c806b
@ -1,6 +1,24 @@
|
||||
UPGRADE FROM 2.1 to 2.2
|
||||
=======================
|
||||
|
||||
### TwigBridge
|
||||
|
||||
* The `render` tag signature and arguments changed.
|
||||
|
||||
Before:
|
||||
|
||||
```
|
||||
{% render 'BlogBundle:Post:list' with { 'limit': 2 }, { 'alt': 'BlogBundle:Post:error' } %}
|
||||
```
|
||||
|
||||
After:
|
||||
|
||||
```
|
||||
{% render url('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.
|
||||
|
@ -4,6 +4,7 @@ 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
|
||||
* The `app` global variable is now injected even when using the twig service directly.
|
||||
|
||||
|
@ -4,6 +4,10 @@ CHANGELOG
|
||||
2.2.0
|
||||
-----
|
||||
|
||||
* [BC BREAK] restricted the `Symfony\Bundle\FrameworkBundle\HttpKernel::render()` method to only accept URIs as reference
|
||||
* `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`)
|
||||
* 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()
|
||||
|
@ -1,75 +0,0 @@
|
||||
<?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\Controller;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAware;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/**
|
||||
* InternalController.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
*/
|
||||
class InternalController extends ContainerAware
|
||||
{
|
||||
/**
|
||||
* Forwards to the given controller with the given path.
|
||||
*
|
||||
* @param string $path The path
|
||||
* @param string $controller The controller name
|
||||
*
|
||||
* @return Response A Response instance
|
||||
*/
|
||||
public function indexAction($path, $controller)
|
||||
{
|
||||
// safeguard
|
||||
if (!is_string($controller)) {
|
||||
throw new \RuntimeException('A Controller must be a string.');
|
||||
}
|
||||
|
||||
// check that the controller looks like a controller
|
||||
if (false === strpos($controller, '::')) {
|
||||
$count = substr_count($controller, ':');
|
||||
if (2 == $count) {
|
||||
// the convention already enforces the Controller suffix
|
||||
} elseif (1 == $count) {
|
||||
// controller in the service:method notation
|
||||
list($service, $method) = explode(':', $controller, 2);
|
||||
$class = get_class($this->container->get($service));
|
||||
|
||||
if (!preg_match('/Controller$/', $class)) {
|
||||
throw new \RuntimeException('A Controller class name must end with Controller.');
|
||||
}
|
||||
} else {
|
||||
throw new \LogicException('Unable to parse the Controller name.');
|
||||
}
|
||||
} else {
|
||||
list($class, $method) = explode('::', $controller, 2);
|
||||
|
||||
if (!preg_match('/Controller$/', $class)) {
|
||||
throw new \RuntimeException('A Controller class name must end with Controller.');
|
||||
}
|
||||
}
|
||||
|
||||
$request = $this->container->get('request');
|
||||
$attributes = $request->attributes;
|
||||
|
||||
$attributes->remove('path');
|
||||
$attributes->remove('controller');
|
||||
if ('none' !== $path) {
|
||||
parse_str($path, $tmp);
|
||||
$attributes->add($tmp);
|
||||
}
|
||||
|
||||
return $this->container->get('http_kernel')->forward($controller, $attributes->all(), $request->query->all());
|
||||
}
|
||||
}
|
@ -84,54 +84,40 @@ class HttpKernel extends BaseHttpKernel
|
||||
*
|
||||
* Available options:
|
||||
*
|
||||
* * attributes: An array of request attributes (only when the first argument is a controller)
|
||||
* * query: An array of request query parameters (only when the first argument is a controller)
|
||||
* * ignore_errors: true to return an empty string in case of an error
|
||||
* * alt: an alternative controller to execute in case of an error (can be a controller, a URI, or an array with the controller, the attributes, and the query arguments)
|
||||
* * alt: an alternative URI to execute in case of an error
|
||||
* * standalone: whether to generate an esi:include tag or not when ESI is supported
|
||||
* * comment: a comment to add when returning an esi:include tag
|
||||
*
|
||||
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
||||
* @param array $options An array of options
|
||||
* @param string $uri A URI
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @return string The Response content
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function render($controller, array $options = array())
|
||||
public function render($uri, array $options = array())
|
||||
{
|
||||
$request = $this->container->get('request');
|
||||
|
||||
$options = array_merge(array(
|
||||
'attributes' => array(),
|
||||
'query' => array(),
|
||||
'ignore_errors' => !$this->container->getParameter('kernel.debug'),
|
||||
'alt' => array(),
|
||||
'alt' => null,
|
||||
'standalone' => false,
|
||||
'comment' => '',
|
||||
'default' => null,
|
||||
), $options);
|
||||
|
||||
if (!is_array($options['alt'])) {
|
||||
$options['alt'] = array($options['alt']);
|
||||
}
|
||||
|
||||
if (null === $this->esiSupport) {
|
||||
$this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request'));
|
||||
$this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($request);
|
||||
}
|
||||
|
||||
if ($this->esiSupport && (true === $options['standalone'] || 'esi' === $options['standalone'])) {
|
||||
$uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']);
|
||||
|
||||
$alt = '';
|
||||
if ($options['alt']) {
|
||||
$alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array());
|
||||
}
|
||||
|
||||
return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']);
|
||||
return $this->container->get('esi')->renderIncludeTag($uri, $options['alt'], $options['ignore_errors'], $options['comment']);
|
||||
}
|
||||
|
||||
if ('js' === $options['standalone']) {
|
||||
$uri = $this->generateInternalUri($controller, $options['attributes'], $options['query'], false);
|
||||
$defaultContent = null;
|
||||
|
||||
$templating = $this->container->get('templating');
|
||||
@ -149,29 +135,9 @@ class HttpKernel extends BaseHttpKernel
|
||||
return $this->renderHIncludeTag($uri, $defaultContent);
|
||||
}
|
||||
|
||||
$request = $this->container->get('request');
|
||||
|
||||
// controller or URI or path?
|
||||
if (0 === strpos($controller, 'http://') || 0 === strpos($controller, 'https://')) {
|
||||
$subRequest = Request::create($controller, 'get', array(), $request->cookies->all(), array(), $request->server->all());
|
||||
if ($session = $request->getSession()) {
|
||||
$subRequest->setSession($session);
|
||||
}
|
||||
} elseif (0 === strpos($controller, '/')) {
|
||||
$subRequest = Request::create($request->getUriForPath($controller), 'get', array(), $request->cookies->all(), array(), $request->server->all());
|
||||
if ($session = $request->getSession()) {
|
||||
$subRequest->setSession($session);
|
||||
}
|
||||
} else {
|
||||
$options['attributes']['_controller'] = $controller;
|
||||
|
||||
if (!isset($options['attributes']['_format'])) {
|
||||
$options['attributes']['_format'] = $request->getRequestFormat();
|
||||
}
|
||||
|
||||
$options['attributes']['_route'] = '_internal';
|
||||
$subRequest = $request->duplicate($options['query'], null, $options['attributes']);
|
||||
$subRequest->setMethod('GET');
|
||||
$subRequest = Request::create($uri, 'get', array(), $request->cookies->all(), array(), $request->server->all());
|
||||
if ($session = $request->getSession()) {
|
||||
$subRequest->setSession($session);
|
||||
}
|
||||
|
||||
$level = ob_get_level();
|
||||
@ -191,10 +157,8 @@ class HttpKernel extends BaseHttpKernel
|
||||
if ($options['alt']) {
|
||||
$alt = $options['alt'];
|
||||
unset($options['alt']);
|
||||
$options['attributes'] = isset($alt[1]) ? $alt[1] : array();
|
||||
$options['query'] = isset($alt[2]) ? $alt[2] : array();
|
||||
|
||||
return $this->render($alt[0], $options);
|
||||
return $this->render($alt, $options);
|
||||
}
|
||||
|
||||
if (!$options['ignore_errors']) {
|
||||
@ -208,38 +172,6 @@ class HttpKernel extends BaseHttpKernel
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an internal URI for a given controller.
|
||||
*
|
||||
* This method uses the "_internal" route, which should be available.
|
||||
*
|
||||
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
||||
* @param array $attributes An array of request attributes
|
||||
* @param array $query An array of request query parameters
|
||||
* @param boolean $secure
|
||||
*
|
||||
* @return string An internal URI
|
||||
*/
|
||||
public function generateInternalUri($controller, array $attributes = array(), array $query = array(), $secure = true)
|
||||
{
|
||||
if (0 === strpos($controller, '/')) {
|
||||
return $controller;
|
||||
}
|
||||
|
||||
$path = http_build_query($attributes, '', '&');
|
||||
$uri = $this->container->get('router')->generate($secure ? '_internal' : '_internal_public', array(
|
||||
'controller' => $controller,
|
||||
'path' => $path ?: 'none',
|
||||
'_format' => $this->container->get('request')->getRequestFormat(),
|
||||
));
|
||||
|
||||
if ($queryString = http_build_query($query, '', '&')) {
|
||||
$uri .= '?'.$queryString;
|
||||
}
|
||||
|
||||
return $uri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an HInclude tag.
|
||||
*
|
||||
|
@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<routes xmlns="http://symfony.com/schema/routing"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||
|
||||
<route id="_internal" pattern="/secure/{controller}/{path}.{_format}">
|
||||
<default key="_controller">FrameworkBundle:Internal:index</default>
|
||||
<requirement key="path">.+</requirement>
|
||||
<requirement key="_format">[^.]+</requirement>
|
||||
</route>
|
||||
|
||||
<route id="_internal_public" pattern="/{controller}/{path}.{_format}">
|
||||
<default key="_controller">FrameworkBundle:Internal:index</default>
|
||||
<requirement key="path">.+</requirement>
|
||||
<requirement key="_format">[^.]+</requirement>
|
||||
</route>
|
||||
</routes>
|
@ -116,47 +116,6 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public function testGenerateInternalUriHandlesNullValues()
|
||||
{
|
||||
$request = new Request();
|
||||
|
||||
$router = $this->getMock('Symfony\\Component\\Routing\\RouterInterface');
|
||||
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface');
|
||||
$container
|
||||
->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->equalTo('router'))
|
||||
->will($this->returnValue($router))
|
||||
;
|
||||
$container
|
||||
->expects($this->at('1'))
|
||||
->method('get')
|
||||
->with($this->equalTo('request'))
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
|
||||
$controller = 'AController';
|
||||
$attributes = array('anAttribute' => null);
|
||||
$query = array('aQueryParam' => null);
|
||||
|
||||
$expectedPath = 'none';
|
||||
|
||||
$routeParameters = array('controller' => $controller, 'path' => $expectedPath, '_format' => 'html');
|
||||
$router
|
||||
->expects($this->once())
|
||||
->method('generate')
|
||||
->with($this->equalTo('_internal'), $this->equalTo($routeParameters))
|
||||
->will($this->returnValue('GENERATED_URI'))
|
||||
;
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
|
||||
$kernel = new HttpKernel($dispatcher, $container, $resolver);
|
||||
|
||||
$uri = $kernel->generateInternalUri($controller, $attributes, $query);
|
||||
$this->assertEquals('GENERATED_URI', $uri);
|
||||
}
|
||||
|
||||
public function getProviderTypes()
|
||||
{
|
||||
return array(
|
||||
@ -172,22 +131,22 @@ class HttpKernelTest extends \PHPUnit_Framework_TestCase
|
||||
$container = $this->getMock('Symfony\\Component\\DependencyInjection\\ContainerInterface');
|
||||
$container
|
||||
->expects($this->at(0))
|
||||
->method('get')
|
||||
->with($this->equalTo('request'))
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
$container
|
||||
->expects($this->at(1))
|
||||
->method('getParameter')
|
||||
->with($this->equalTo('kernel.debug'))
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$container
|
||||
->expects($this->at(1))
|
||||
->expects($this->at(2))
|
||||
->method('has')
|
||||
->with($this->equalTo('esi'))
|
||||
->will($this->returnValue(false))
|
||||
;
|
||||
$container
|
||||
->expects($this->at(2))
|
||||
->method('get')
|
||||
->with($this->equalTo('request'))
|
||||
->will($this->returnValue($request))
|
||||
;
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
|
||||
|
@ -34,17 +34,16 @@ class ActionsExtension extends \Twig_Extension
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Response content for a given controller or URI.
|
||||
* Returns the Response content for a given URI.
|
||||
*
|
||||
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
|
||||
* @param array $attributes An array of request attributes
|
||||
* @param array $options An array of options
|
||||
* @param string $uri A URI
|
||||
* @param array $options An array of options
|
||||
*
|
||||
* @see Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver::render()
|
||||
*/
|
||||
public function renderAction($controller, array $attributes = array(), array $options = array())
|
||||
public function renderUri($uri, array $options = array())
|
||||
{
|
||||
return $this->container->get('templating.helper.actions')->render($controller, $attributes, $options);
|
||||
return $this->container->get('templating.helper.actions')->render($uri, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -55,7 +54,7 @@ class ActionsExtension extends \Twig_Extension
|
||||
public function getTokenParsers()
|
||||
{
|
||||
return array(
|
||||
// {% render 'BlogBundle:Post:list' with { 'limit': 2 }, { 'alt': 'BlogBundle:Post:error' } %}
|
||||
// {% render url('post_list', { 'limit': 2 }), { 'alt': 'BlogBundle:Post:error' } %}
|
||||
new RenderTokenParser(),
|
||||
);
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ namespace Symfony\Bundle\TwigBundle\Node;
|
||||
*/
|
||||
class RenderNode extends \Twig_Node
|
||||
{
|
||||
public function __construct(\Twig_Node_Expression $expr, \Twig_Node_Expression $attributes, \Twig_Node_Expression $options, $lineno, $tag = null)
|
||||
public function __construct(\Twig_Node_Expression $expr, \Twig_Node_Expression $options, $lineno, $tag = null)
|
||||
{
|
||||
parent::__construct(array('expr' => $expr, 'attributes' => $attributes, 'options' => $options), array(), $lineno, $tag);
|
||||
parent::__construct(array('expr' => $expr, 'options' => $options), array(), $lineno, $tag);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -32,11 +32,9 @@ class RenderNode extends \Twig_Node
|
||||
{
|
||||
$compiler
|
||||
->addDebugInfo($this)
|
||||
->write("echo \$this->env->getExtension('actions')->renderAction(")
|
||||
->write("echo \$this->env->getExtension('actions')->renderUri(")
|
||||
->subcompile($this->getNode('expr'))
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('attributes'))
|
||||
->raw(', ')
|
||||
->subcompile($this->getNode('options'))
|
||||
->raw(");\n")
|
||||
;
|
||||
|
@ -31,29 +31,16 @@ class RenderTokenParser extends \Twig_TokenParser
|
||||
{
|
||||
$expr = $this->parser->getExpressionParser()->parseExpression();
|
||||
|
||||
// attributes
|
||||
if ($this->parser->getStream()->test(\Twig_Token::NAME_TYPE, 'with')) {
|
||||
$this->parser->getStream()->next();
|
||||
|
||||
$hasAttributes = true;
|
||||
$attributes = $this->parser->getExpressionParser()->parseExpression();
|
||||
} else {
|
||||
$hasAttributes = false;
|
||||
$attributes = new \Twig_Node_Expression_Array(array(), $token->getLine());
|
||||
}
|
||||
|
||||
// options
|
||||
if ($hasAttributes && $this->parser->getStream()->test(\Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||
if ($this->parser->getStream()->test(\Twig_Token::PUNCTUATION_TYPE, ',')) {
|
||||
$this->parser->getStream()->next();
|
||||
|
||||
$options = $this->parser->getExpressionParser()->parseExpression();
|
||||
} else {
|
||||
$options = new \Twig_Node_Expression_Array(array(), $token->getLine());
|
||||
}
|
||||
|
||||
$this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE);
|
||||
|
||||
return new RenderNode($expr, $attributes, $options, $token->getLine(), $this->getTag());
|
||||
return new RenderNode($expr, $options, $token->getLine(), $this->getTag());
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user