Handle single-node child template bodies in cleanup

This commit is contained in:
Fabien Potencier
2026-06-08 13:13:35 +02:00
parent a69d3dc71e
commit c0504b90c5
2 changed files with 36 additions and 2 deletions
+8 -2
View File
@@ -121,7 +121,7 @@ class Parser
}
if ($this->parent) {
$this->cleanupBodyForChildTemplates($body);
$body = $this->cleanupBodyForChildTemplates($body);
}
$node = new ModuleNode(
@@ -552,8 +552,12 @@ class Parser
return $test;
}
private function cleanupBodyForChildTemplates(Node $body): void
private function cleanupBodyForChildTemplates(Node $body): Node
{
if ($body instanceof BlockReferenceNode || ($body instanceof TextNode && $body->isBlank())) {
return new EmptyNode();
}
foreach ($body as $k => $node) {
if ($node instanceof BlockReferenceNode) {
// as it has a parent, the block reference won't be used
@@ -563,6 +567,8 @@ class Parser
$body->removeNode($k);
}
}
return $body;
}
private function checkPrecedenceDeprecations(ExpressionParserInterface $expressionParser, AbstractExpression $expr)
+28
View File
@@ -171,6 +171,17 @@ EOF, 'index')));
$this->assertSame('set', $body->getNode('4')->getNodeTag());
}
public function testCleanupBodyForChildTemplatesWithASingleNodeBody()
{
$twig = new Environment(new ArrayLoader());
$twig->addTokenParser(new ParentSettingTokenParser());
$node = $twig->parse($twig->tokenize(new Source('{% set_parent %}', 'index')));
$body = $node->getNode('body')->getNode('0');
$this->assertInstanceOf(EmptyNode::class, $body);
}
public function testBodyForParentTemplates()
{
$twig = new Environment(new ArrayLoader());
@@ -231,3 +242,20 @@ class TestTokenParser extends AbstractTokenParser
return 'test';
}
}
class ParentSettingTokenParser extends AbstractTokenParser
{
public function parse(Token $token): Node
{
$this->parser->setParent(new ConstantExpression('base', $token->getLine()), false);
$this->parser->getStream()->expect(Token::BLOCK_END_TYPE);
// returns a blank text node so the whole child body is a single removable node
return new TextNode(' ', $token->getLine());
}
public function getTag(): string
{
return 'set_parent';
}
}