* 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
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");
}
}
$body = $this->subparse(null);
if (null !== $this->parent) {
- $this->checkBodyNodes($body);
+ $body = $this->filterBodyNodes($body);
}
} catch (Twig_Error_Syntax $e) {
if (null === $e->getTemplateFile()) {
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;
}
}
$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);
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),
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();
$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