From: Fabien Potencier Date: Tue, 26 Jul 2011 06:02:51 +0000 (+0200) Subject: fixed compilation of templates when the body of a child template is not empty X-Git-Url: http://git.silmor.de/gitweb/?a=commitdiff_plain;h=7f5390a6a713342de829f4580a5f83b121e1dbfa;p=web%2Fkonrad%2Ftwig.git fixed compilation of templates when the body of a child template is not empty --- diff --git a/CHANGELOG b/CHANGELOG index 969b409..cdf0530 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,6 @@ * 1.1.2 + * fixed compilation of templates when the body of a child template is not empty * fixed output when a macro throws an exception * fixed a parsing problem when a large chunk of text is enclosed in a comment tag * added PHPDoc for all Token parsers and Core extension functions diff --git a/lib/Twig/Node/Module.php b/lib/Twig/Node/Module.php index 1af7622..923dea8 100644 --- a/lib/Twig/Node/Module.php +++ b/lib/Twig/Node/Module.php @@ -87,20 +87,10 @@ class Twig_Node_Module extends Twig_Node protected function compileDisplayBody(Twig_Compiler $compiler) { $compiler->write("\$context = array_merge(\$this->env->getGlobals(), \$context);\n\n"); + $compiler->subcompile($this->getNode('body')); if (null !== $this->getNode('parent')) { - // remove all output nodes - foreach ($this->getNode('body') as $node) { - if (!$node instanceof Twig_NodeOutputInterface) { - $compiler->subcompile($node); - } - } - - $compiler - ->write("\$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));\n") - ; - } else { - $compiler->subcompile($this->getNode('body')); + $compiler->write("\$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); } } diff --git a/lib/Twig/Parser.php b/lib/Twig/Parser.php index 0e7a8af..fc41374 100644 --- a/lib/Twig/Parser.php +++ b/lib/Twig/Parser.php @@ -81,7 +81,7 @@ class Twig_Parser implements Twig_ParserInterface $body = $this->subparse(null); if (null !== $this->parent) { - $this->checkBodyNodes($body); + $body = $this->filterBodyNodes($body); } } catch (Twig_Error_Syntax $e) { if (null === $e->getTemplateFile()) { @@ -292,17 +292,27 @@ class Twig_Parser implements Twig_ParserInterface return $this->stream->getCurrent(); } - protected function checkBodyNodes($body) + protected function filterBodyNodes(Twig_NodeInterface $node) { // check that the body does not contain non-empty output nodes - foreach ($body as $node) { - if ( - ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data'))) - || - (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) - ) { - throw new Twig_Error_Syntax(sprintf('A template that extends another one cannot have a body (%s).', $node), $node->getLine(), $this->stream->getFilename()); + if ( + ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data'))) + || + (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) + ) { + throw new Twig_Error_Syntax(sprintf('A template that extends another one cannot have a body (%s).', $node), $node->getLine(), $this->stream->getFilename()); + } + + if ($node instanceof Twig_NodeOutputInterface) { + return null; + } + + foreach ($node as $k => $n) { + if (null === $n = $this->filterBodyNodes($n)) { + $node->removeNode($k); } } + + return $node; } } diff --git a/test/Twig/Tests/Node/ModuleTest.php b/test/Twig/Tests/Node/ModuleTest.php index f928800..d5ea618 100644 --- a/test/Twig/Tests/Node/ModuleTest.php +++ b/test/Twig/Tests/Node/ModuleTest.php @@ -91,7 +91,7 @@ EOF $import = new Twig_Node_Import(new Twig_Node_Expression_Constant('foo.twig', 0), new Twig_Node_Expression_AssignName('macro', 0), 0); - $body = new Twig_Node(array($import, new Twig_Node_Text('foo', 0))); + $body = new Twig_Node(array($import)); $extends = new Twig_Node_Expression_Constant('layout.twig', 0); $node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, $filename); @@ -133,7 +133,7 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template EOF , $twig); - $body = new Twig_Node_Text('foo', 0); + $body = new Twig_Node(); $extends = new Twig_Node_Expression_Conditional( new Twig_Node_Expression_Constant(true, 0), new Twig_Node_Expression_Constant('foo', 0), diff --git a/test/Twig/Tests/Node/SandboxedModuleTest.php b/test/Twig/Tests/Node/SandboxedModuleTest.php index 097574e..0b2b445 100644 --- a/test/Twig/Tests/Node/SandboxedModuleTest.php +++ b/test/Twig/Tests/Node/SandboxedModuleTest.php @@ -96,7 +96,7 @@ class __TwigTemplate_be925a7b06dda0dfdbd18a1509f7eb34 extends Twig_Template EOF , $twig); - $body = new Twig_Node_Text('foo', 0); + $body = new Twig_Node(); $extends = new Twig_Node_Expression_Constant('layout.twig', 0); $blocks = new Twig_Node(); $macros = new Twig_Node(); diff --git a/test/Twig/Tests/ParserTest.php b/test/Twig/Tests/ParserTest.php index 2159a5c..7dfddda 100644 --- a/test/Twig/Tests/ParserTest.php +++ b/test/Twig/Tests/ParserTest.php @@ -18,4 +18,63 @@ class Twig_Tests_ParserTest extends PHPUnit_Framework_TestCase $parser = new Twig_Parser(new Twig_Environment()); $parser->setMacro('display', $this->getMock('Twig_Node_Macro', null, array(), '', null)); } + + /** + * @dataProvider getFilterBodyNodesData + */ + public function testFilterBodyNodes($input, $expected) + { + list($parser, $invoker) = $this->getParserForFilterBodyNodes(); + + $this->assertEquals($expected, $invoker->invoke($parser, $input)); + } + + public function getFilterBodyNodesData() + { + return array( + array( + new Twig_Node(array(new Twig_Node_Text(' ', 0))), + new Twig_Node(array()), + ), + array( + $input = new Twig_Node(array(new Twig_Node_Set(false, new Twig_Node(), new Twig_Node(), 0))), + $input, + ), + ); + } + + /** + * @dataProvider getFilterBodyNodesDataThrowsException + * @expectedException Twig_Error_Syntax + */ + public function testFilterBodyNodesThrowsException($input) + { + list($parser, $invoker) = $this->getParserForFilterBodyNodes(); + + $invoker->invoke($parser, $input); + } + + public function getFilterBodyNodesDataThrowsException() + { + return array( + array(new Twig_Node_Text('foo', 0)), + array(new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 0)))))), + ); + } + + protected function getParserForFilterBodyNodes() + { + $invoker = new ReflectionMethod('Twig_Parser', 'filterBodyNodes'); + $invoker->setAccessible(true); + + $p = new ReflectionProperty('Twig_Parser', 'stream'); + $p->setAccessible(true); + + $parser = new Twig_Parser(new Twig_Environment()); + $parser->setParent(new Twig_Node()); + $p->setValue($parser, $this->getMockBuilder('Twig_TokenStream')->disableOriginalConstructor()->getMock()); + + return array($parser, $invoker); + } } +//Twig_Error_Syntax