bug #2269 Bugfix: When rendering blocks of other templates, don't pass the local blocks array (derrabus, fabpot)

This PR was merged into the 1.x branch.

Discussion
----------

Bugfix: When rendering blocks of other templates, don't pass the local blocks array

This PR fixes symfony/symfony#20556.

When referring to a block of another template from within a template that also has a block with the same name, Twig renders the wrong block.

Commits
-------

8c090a7 added tests for block() when using a template argument
a5526f3 fixed block() is defined call when using a template argument
c04d077 Bugfix: When rendering blocks of other templates, don't pass the local blocks array.
This commit is contained in:
Fabien Potencier
2016-11-18 21:51:10 -08:00
4 changed files with 74 additions and 28 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
* 1.28.1 (2016-XX-XX)
* n/a
* fixed block() function when used with a template argument
* 1.28.0 (2016-11-17)
+34 -27
View File
@@ -39,46 +39,53 @@ class Twig_Node_Expression_BlockReference extends Twig_Node_Expression
public function compile(Twig_Compiler $compiler)
{
if ($this->getAttribute('is_defined_test')) {
$compiler
->raw('$this->hasBlock(')
->subcompile($this->getNode('name'))
->raw(', $context, $blocks)')
;
$this->compileTemplateCall($compiler, 'hasBlock');
} else {
if ($this->getAttribute('output')) {
$compiler->addDebugInfo($this);
$this
->compileTemplateCall($compiler)
->raw('->displayBlock(')
->subcompile($this->getNode('name'))
->raw(", \$context, \$blocks);\n")
;
->compileTemplateCall($compiler, 'displayBlock')
->raw(";\n");
} else {
$this
->compileTemplateCall($compiler)
->raw('->renderBlock(')
->subcompile($this->getNode('name'))
->raw(', $context, $blocks)')
;
$this->compileTemplateCall($compiler, 'renderBlock');
}
}
}
private function compileTemplateCall(Twig_Compiler $compiler)
private function compileTemplateCall(Twig_Compiler $compiler, $method)
{
if (!$this->hasNode('template')) {
return $compiler->write('$this');
$compiler->write('$this');
} else {
$compiler
->write('$this->loadTemplate(')
->subcompile($this->getNode('template'))
->raw(', ')
->repr($this->getTemplateName())
->raw(', ')
->repr($this->getTemplateLine())
->raw(')')
;
}
return $compiler
->write('$this->loadTemplate(')
->subcompile($this->getNode('template'))
->raw(', ')
->repr($this->getTemplateName())
->raw(', ')
->repr($this->getTemplateLine())
->raw(')')
;
$compiler->raw(sprintf('->%s', $method));
$this->compileBlockArguments($compiler);
return $compiler;
}
private function compileBlockArguments(Twig_Compiler $compiler)
{
$compiler
->raw('(')
->subcompile($this->getNode('name'))
->raw(', $context');
if (!$this->hasNode('template')) {
$compiler->raw(', $blocks');
}
return $compiler->raw(')');
}
}
@@ -0,0 +1,22 @@
--TEST--
"block" function with a template argument
--TEMPLATE--
{{ block('foo', 'included.twig') }}
{{ block('foo', included_loaded) }}
{{ block('foo', included_loaded_internal) }}
{% set output = block('foo', 'included.twig') %}
{{ output }}
{% block foo %}NOT FOO{% endblock %}
--TEMPLATE(included.twig)--
{% block foo %}FOO{% endblock %}
--DATA--
return array(
'included_loaded' => $twig->load('included.twig'),
'included_loaded_internal' => $twig->loadTemplate('included.twig'),
)
--EXPECT--
FOO
FOO
FOO
FOO
NOT FOO
@@ -0,0 +1,17 @@
--TEST--
"defined" support for blocks with a template argument
--TEMPLATE--
{{ block('foo', 'included.twig') is defined ? 'ok' : 'ko' }}
{{ block('foo', included_loaded) is defined ? 'ok' : 'ko' }}
{{ block('foo', included_loaded_internal) is defined ? 'ok' : 'ko' }}
--TEMPLATE(included.twig)--
{% block foo %}FOO{% endblock %}
--DATA--
return array(
'included_loaded' => $twig->load('included.twig'),
'included_loaded_internal' => $twig->loadTemplate('included.twig'),
)
--EXPECT--
ok
ok
ok