fixed variables defined outside a loop and for which the value changes in a for loop...
authorFabien Potencier <fabien.potencier@gmail.com>
Tue, 11 May 2010 09:54:06 +0000 (11:54 +0200)
committerFabien Potencier <fabien.potencier@gmail.com>
Tue, 11 May 2010 09:54:06 +0000 (11:54 +0200)
CHANGELOG
lib/Twig/Compiler.php
lib/Twig/Node/For.php
test/fixtures/tags/for/inner_variables.test [new file with mode: 0644]

index 4cd52f7..5006f50 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,5 +1,6 @@
 * 0.9.6-DEV
 
+ * fixed variables defined outside a loop and for which the value changes in a for loop
  * fixed the test suite for PHP 5.2 and older versions of PHPUnit
  * added support for __call() in expression resolution
  * fixed node visiting for macros (macros are now visited by visitors as any other node)
index 960e98f..eb7fa22 100644 (file)
@@ -152,31 +152,6 @@ class Twig_Compiler implements Twig_CompilerInterface
     }
 
     /**
-     * Pushes the current context on the stack.
-     *
-     * @return Twig_Compiler The current compiler instance
-     */
-    public function pushContext()
-    {
-        // the (array) cast bypasses a PHP 5.2.6 bug
-        $this->write('$context[\'_parent\'] = (array) $context;'."\n");
-
-        return $this;
-    }
-
-    /**
-     * Pops a context from the stack.
-     *
-     * @return Twig_Compiler The current compiler instance
-     */
-    public function popContext()
-    {
-        $this->write('$context = $context[\'_parent\'];'."\n");
-
-        return $this;
-    }
-
-    /**
      * Adds debugging information.
      *
      * @param Twig_Node $node The related twig node
index a86c35c..b1b11b0 100644 (file)
@@ -52,7 +52,8 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
     {
         $compiler
             ->addDebugInfo($this)
-            ->pushContext()
+            // the (array) cast bypasses a PHP 5.2.6 bug
+            ->write('$context[\'_parent\'] = (array) $context;'."\n")
         ;
 
         if (!is_null($this->else)) {
@@ -130,7 +131,14 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
                 ->write("}\n")
             ;
         }
-        $compiler->popContext();
+
+        $compiler->write('$_parent = $context[\'_parent\'];'."\n");
+
+        // remove some "private" loop variables (needed for nested loops)
+        $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$loopVars[0].'\'], $context[\''.$loopVars[1].'\'], $context[\'_parent\'], $context[\'loop\']);'."\n");
+
+        /// keep the values set in the inner context for variables defined in the outer context
+        $compiler->write('$context = array_merge($_parent, array_intersect_key($context, $_parent));'."\n");
     }
 
     public function setWithLoop($boolean)
diff --git a/test/fixtures/tags/for/inner_variables.test b/test/fixtures/tags/for/inner_variables.test
new file mode 100644 (file)
index 0000000..3e9ad56
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+"for" tag does not reset inner variables
+--TEMPLATE--
+{% for i in 1..2 %}
+  {% for j in 0..2 %}
+    {{k}}{% set k as k+1 %} {{ loop.parent.loop.index }}
+  {% endfor %}
+{% endfor %}
+--DATA--
+return array('k' => 0)
+--EXPECT--
+      0 1
+      1 1
+      2 1
+        3 2
+      4 2
+      5 2