fixed for tag loop variable when using a condition
authorFabien Potencier <fabien.potencier@gmail.com>
Sat, 5 Nov 2011 08:49:18 +0000 (09:49 +0100)
committerFabien Potencier <fabien.potencier@gmail.com>
Mon, 7 Nov 2011 13:01:06 +0000 (14:01 +0100)
lib/Twig/Node/For.php
lib/Twig/Node/For/Loop.php [new file with mode: 0644]
test/Twig/Tests/Fixtures/tags/for/condition.test
test/Twig/Tests/Node/ForTest.php

index c866dde..0b0e1b6 100644 (file)
  */
 class Twig_Node_For extends Twig_Node
 {
+    protected $loop;
+
     public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null)
     {
+        $body->setNode('_for_loop', $this->loop = new Twig_Node_For_Loop($lineno, $tag));
+
         if (null !== $ifexpr) {
             $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag);
         }
@@ -72,6 +76,10 @@ class Twig_Node_For extends Twig_Node
             }
         }
 
+        $this->loop->setAttribute('else', null !== $this->getNode('else'));
+        $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop'));
+        $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr'));
+
         $compiler
             ->write("foreach (\$context['_seq'] as ")
             ->subcompile($this->getNode('key_target'))
@@ -79,35 +87,7 @@ class Twig_Node_For extends Twig_Node
             ->subcompile($this->getNode('value_target'))
             ->raw(") {\n")
             ->indent()
-        ;
-
-        $compiler->subcompile($this->getNode('body'));
-
-        if (null !== $this->getNode('else')) {
-            $compiler->write("\$context['_iterated'] = true;\n");
-        }
-
-        if ($this->getAttribute('with_loop')) {
-            $compiler
-                ->write("++\$context['loop']['index0'];\n")
-                ->write("++\$context['loop']['index'];\n")
-                ->write("\$context['loop']['first'] = false;\n")
-            ;
-
-            if (!$this->getAttribute('ifexpr')) {
-                $compiler
-                    ->write("if (isset(\$context['loop']['length'])) {\n")
-                    ->indent()
-                    ->write("--\$context['loop']['revindex0'];\n")
-                    ->write("--\$context['loop']['revindex'];\n")
-                    ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
-                    ->outdent()
-                    ->write("}\n")
-                ;
-            }
-        }
-
-        $compiler
+            ->subcompile($this->getNode('body'))
             ->outdent()
             ->write("}\n")
         ;
diff --git a/lib/Twig/Node/For/Loop.php b/lib/Twig/Node/For/Loop.php
new file mode 100644 (file)
index 0000000..45d754e
--- /dev/null
@@ -0,0 +1,56 @@
+<?php
+
+/*
+ * This file is part of Twig.
+ *
+ * (c) 2011 Fabien Potencier
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Internal node used by the for node.
+ *
+ * @package    twig
+ * @author     Fabien Potencier <fabien@symfony.com>
+ */
+class Twig_Node_For_Loop extends Twig_Node
+{
+    public function __construct($lineno, $tag = null)
+    {
+        parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag);
+    }
+
+    /**
+     * Compiles the node to PHP.
+     *
+     * @param Twig_Compiler A Twig_Compiler instance
+     */
+    public function compile(Twig_Compiler $compiler)
+    {
+        if ($this->getAttribute('else')) {
+            $compiler->write("\$context['_iterated'] = true;\n");
+        }
+
+        if ($this->getAttribute('with_loop')) {
+            $compiler
+                ->write("++\$context['loop']['index0'];\n")
+                ->write("++\$context['loop']['index'];\n")
+                ->write("\$context['loop']['first'] = false;\n")
+            ;
+
+            if (!$this->getAttribute('ifexpr')) {
+                $compiler
+                    ->write("if (isset(\$context['loop']['length'])) {\n")
+                    ->indent()
+                    ->write("--\$context['loop']['revindex0'];\n")
+                    ->write("--\$context['loop']['revindex'];\n")
+                    ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
+                    ->outdent()
+                    ->write("}\n")
+                ;
+            }
+        }
+    }
+}
index 6879903..9e4eb9b 100644 (file)
@@ -1,12 +1,14 @@
 --TEST--
 "for" tag takes a condition
 --TEMPLATE--
-{% for i in [1, 2, 3, 4, 5] if i == 2 %}
-    Hello World!
+{% for i in 1..5 if i is odd -%}
+    {{ loop.index }}.{{ i }}
 {% endfor %}
 --DATA--
 return array()
 --CONFIG--
 return array('strict_variables' => false)
 --EXPECT--
-Hello World!
+1.1
+2.3
+3.5
index bbca85d..68a3daa 100644 (file)
@@ -22,7 +22,7 @@ class Twig_Tests_Node_ForTest extends Twig_Tests_Node_TestCase
         $valueTarget = new Twig_Node_Expression_AssignName('item', 0);
         $seq = new Twig_Node_Expression_Name('items', 0);
         $ifexpr = new Twig_Node_Expression_Constant(true, 0);
-        $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0);
+        $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0)), array(), 0);
         $else = null;
         $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 0);
         $node->setAttribute('with_loop', false);
@@ -58,7 +58,7 @@ class Twig_Tests_Node_ForTest extends Twig_Tests_Node_TestCase
         $valueTarget = new Twig_Node_Expression_AssignName('item', 0);
         $seq = new Twig_Node_Expression_Name('items', 0);
         $ifexpr = null;
-        $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0);
+        $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0)), array(), 0);
         $else = null;
         $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 0);
         $node->setAttribute('with_loop', false);
@@ -79,7 +79,7 @@ EOF
         $valueTarget = new Twig_Node_Expression_AssignName('v', 0);
         $seq = new Twig_Node_Expression_Name('values', 0);
         $ifexpr = null;
-        $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0);
+        $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0)), array(), 0);
         $else = null;
         $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 0);
         $node->setAttribute('with_loop', true);
@@ -121,7 +121,7 @@ EOF
         $valueTarget = new Twig_Node_Expression_AssignName('v', 0);
         $seq = new Twig_Node_Expression_Name('values', 0);
         $ifexpr = new Twig_Node_Expression_Constant(true, 0);
-        $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0);
+        $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0)), array(), 0);
         $else = null;
         $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 0);
         $node->setAttribute('with_loop', true);
@@ -138,10 +138,10 @@ EOF
 foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) {
     if (true) {
         echo \$this->getContext(\$context, "foo");
+        ++\$context['loop']['index0'];
+        ++\$context['loop']['index'];
+        \$context['loop']['first'] = false;
     }
-    ++\$context['loop']['index0'];
-    ++\$context['loop']['index'];
-    \$context['loop']['first'] = false;
 }
 \$_parent = \$context['_parent'];
 unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']);
@@ -153,7 +153,7 @@ EOF
         $valueTarget = new Twig_Node_Expression_AssignName('v', 0);
         $seq = new Twig_Node_Expression_Name('values', 0);
         $ifexpr = null;
-        $body = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0);
+        $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0)), array(), 0);
         $else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 0), 0);
         $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 0);
         $node->setAttribute('with_loop', true);