From e0f20a0c4debf75f42d7b386fe888992e55751ea Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 13 Dec 2010 15:20:03 +0100 Subject: [PATCH] enhanced the for-loop optimizer (patch from nikic) --- lib/Twig/NodeVisitor/Optimizer.php | 25 +++++++++++++++---------- test/Twig/Tests/NodeVisitor/OptimizerTest.php | 14 +++++++++++++- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/lib/Twig/NodeVisitor/Optimizer.php b/lib/Twig/NodeVisitor/Optimizer.php index 8006cd3..005dc51 100644 --- a/lib/Twig/NodeVisitor/Optimizer.php +++ b/lib/Twig/NodeVisitor/Optimizer.php @@ -76,24 +76,29 @@ class Twig_NodeVisitor_Optimizer implements Twig_NodeVisitorInterface * * * "loop" is not used in the "for" tag * * and there is no include tag without the "only" attribute - * * and there is no inner-for tag (in which case we would need to check parent.loop usage) + * * and there is no inner-for tag (in which case we would need to check loop.parent usage) * * This method should be able to optimize for with inner-for tags. */ protected function enterOptimizeFor($node, $env) { if ($node instanceof Twig_Node_For) { + // disable the loop variable by default $node->setAttribute('with_loop', false); - - if ($this->loops) { - $this->loops[0]->setAttribute('with_loop', true); - } - array_unshift($this->loops, $node); - } elseif ($this->loops && $node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) { - $this->loops[0]->setAttribute('with_loop', true); - } elseif ($this->loops && $node instanceof Twig_Node_Include && !$node->getAttribute('only')) { - $this->loops[0]->setAttribute('with_loop', true); + } 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')) + ) + ) { + foreach ($this->loops as $loop) { + $loop->setAttribute('with_loop', true); + } } } diff --git a/test/Twig/Tests/NodeVisitor/OptimizerTest.php b/test/Twig/Tests/NodeVisitor/OptimizerTest.php index b3a9a6f..1501b57 100644 --- a/test/Twig/Tests/NodeVisitor/OptimizerTest.php +++ b/test/Twig/Tests/NodeVisitor/OptimizerTest.php @@ -29,11 +29,23 @@ class Twig_Tests_NodeVisitor_OptimizerTest extends PHPUnit_Framework_TestCase { return array( array('{% for i in foo %}{% endfor %}', array('i' => false)), + array('{% for i in foo %}{{ loop.index }}{% endfor %}', array('i' => true)), - array('{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', array('i' => true, 'j' => false)), + + array('{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)), + array('{% for i in foo %}{% include "foo" %}{% endfor %}', array('i' => true)), + 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.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 %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)), ); } -- 1.7.2.5