Add support for Escaper and Sandbox for Generator nodes

This commit is contained in:
Fabien Potencier
2024-07-25 16:10:46 +02:00
parent c1933323ba
commit c28f68f807
3 changed files with 73 additions and 16 deletions
+3 -2
View File
@@ -22,6 +22,7 @@ use Twig\Node\Expression\Binary\ConcatBinary;
use Twig\Node\Expression\BlockReferenceExpression;
use Twig\Node\Expression\ConditionalExpression;
use Twig\Node\Expression\ConstantExpression;
use Twig\Node\Expression\FilterExpression;
use Twig\Node\Expression\GetAttrExpression;
use Twig\Node\Expression\MethodCallExpression;
use Twig\Node\Expression\NameExpression;
@@ -465,10 +466,10 @@ class ExpressionParser
if (\count($args) < 1) {
throw new SyntaxError('The "loop" function takes an iterator as an argument.', $line, $this->parser->getStream()->getSourceContext());
}
$recurseArgs = new ArrayExpression([], $line);
$recurseArgs->addElement($args->getNode('0'));
$recurseArgs = new ArrayExpression([new ConstantExpression(0, $line), $args->getNode('0')], $line);
$expr = new GetAttrExpression(new NameExpression('loop', $line), new ConstantExpression('__invoke', $line), $recurseArgs, Template::METHOD_CALL, $line);
$expr->setAttribute('is_generator', true);
$expr = new FilterExpression($expr, new ConstantExpression('raw', $line), new Node(), $line);
return $expr;
default:
+18
View File
@@ -0,0 +1,18 @@
--TEST--
"for" tags can be nested
--TEMPLATE--
{% for key, item in items %}
* {{ key }} ({{ loop.length }}):
{% for value in item %}
* {{ value }} ({{ loop.length }})
{% endfor %}
{% endfor %}
--DATA--
return ['items' => ['a' => ['a1', 'a2', 'a3'], 'b' => ['b1']]]
--EXPECT--
* a (2):
* a1 (3)
* a2 (3)
* a3 (3)
* b (2):
* b1 (1)
+52 -14
View File
@@ -1,18 +1,56 @@
--TEST--
"for" tags can be nested
"for" tags can be recursive
--TEMPLATE--
{% for key, item in items %}
* {{ key }} ({{ loop.length }}):
{% for value in item %}
* {{ value }} ({{ loop.length }})
{% endfor %}
{% endfor %}
{% block block %}block{% endblock %}
{% macro macro() %}macro{% endmacro %}
<ul class="sitemap">
{% for item in sitemap %}
{{- block('block') -}}-{{- _self.macro() -}}
<li>{{ item.title }} ({{ loop.index }}) {{ loop.depth }}
{% if item.children is defined %}
<ul class="submenu">
{{ loop(item.children) }} {{ loop.depth }}
</ul>
{% endif %}</li>
{% endfor %}
</ul>
--DATA--
return ['items' => ['a' => ['a1', 'a2', 'a3'], 'b' => ['b1']]]
return [
'sitemap' => [
[ 'title' => 'foo' ],
[ 'title' => 'bar' ],
[ 'title' => 'foobar' ],
[ 'title' => 'subsitemap',
'children' => [
[ 'title' => 'foobar' ],
[ 'title' => 'baz' ],
],
],
[ 'title' => 'foobar' ],
[ 'title' => 'baz' ],
],
]
--EXPECT--
* a (2):
* a1 (3)
* a2 (3)
* a3 (3)
* b (2):
* b1 (1)
block
<ul class="sitemap">
block-macro<li>foo (1) 1
</li>
block-macro<li>bar (2) 1
</li>
block-macro<li>foobar (3) 1
</li>
block-macro<li>subsitemap (4) 1
<ul class="submenu">
block-macro<li>foobar (1) 2
</li>
block-macro<li>baz (2) 2
</li>
1
</ul>
</li>
block-macro<li>foobar (5) 1
</li>
block-macro<li>baz (6) 1
</li>
</ul>