// disable the loop variable by default
$node->setAttribute('with_loop', false);
array_unshift($this->loops, $node);
- } elseif ($this->loops
- // when do we need to add the loop variable back?
- && (
- // the loop variable is referenced here
- ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name'))
- ||
- // include without the only attribute
- ($this->loops && $node instanceof Twig_Node_Include && !$node->getAttribute('only'))
- )
+ } elseif (!$this->loops) {
+ // we are outside a loop
+ return;
+ }
+
+ // when do we need to add the loop variable back?
+
+ // the loop variable is referenced for the current loop
+ elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) {
+ $this->addLoopToCurrent();
+ }
+
+ // include without the only attribute
+ elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) {
+ $this->addLoopToAll();
+ }
+
+ // the loop variable is referenced via an attribute
+ elseif ($node instanceof Twig_Node_Expression_GetAttr
+ && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant
+ || 'parent' === $node->getNode('attribute')->getAttribute('value')
+ )
+ && (true === $this->loops[0]->getAttribute('with_loop')
+ || ($node->getNode('node') instanceof Twig_Node_Expression_Name
+ && 'loop' === $node->getNode('node')->getAttribute('name')
+ )
+ )
) {
- foreach ($this->loops as $loop) {
- $loop->setAttribute('with_loop', true);
- }
+ $this->addLoopToAll();
}
}
}
}
+ protected function addLoopToCurrent()
+ {
+ $this->loops[0]->setAttribute('with_loop', true);
+ }
+
+ protected function addLoopToAll()
+ {
+ foreach ($this->loops as $loop) {
+ $loop->setAttribute('with_loop', true);
+ }
+ }
+
/**
* {@inheritdoc}
*/
$stream = $env->parse($env->tokenize($template, 'index'));
foreach ($expected as $target => $withLoop) {
- $this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop));
+ $this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : ''));
}
}
array('{% for i in foo %}{% include "foo" only %}{% endfor %}', array('i' => false)),
- // "i" should be false
- array('{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
+ array('{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => true)),
array('{% for i in foo %}{% for j in foo %}{{ loop.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
- //array('{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)),
+ array('{% for i in foo %}{% set l = loop %}{% for j in foo %}{{ l.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => false)),
+
+ array('{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)),
array('{% for i in foo %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)),
);