Browse code

added the "without loop" option to the for tag (it disables the generation of the loop variable)

git-svn-id: http://svn.twig-project.org/trunk@216 93ef8e89-cb99-4229-a87c-7fa0fa45744b

fabien authored on 08/01/2010 13:16:37
Showing 3 changed files
... ...
@@ -16,6 +16,7 @@ If you have created NodeTransformer classes, you will need to upgrade them to
16 16
 the new interface (please note that the interface is not yet considered
17 17
 stable).
18 18
 
19
+ * added the "without loop" option to the for tag (it disables the generation of the loop variable)
19 20
  * refactored node transformers to node visitors
20 21
  * fixed automatic-escaping for blocks
21 22
  * added a way to specify variables to pass to an included template
... ...
@@ -24,8 +24,9 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
24 24
   protected $seq;
25 25
   protected $body;
26 26
   protected $else;
27
+  protected $withLoop;
27 28
 
28
-  public function __construct($isMultitarget, $item, $seq, Twig_NodeList $body, Twig_Node $else = null, $lineno, $tag = null)
29
+  public function __construct($isMultitarget, $item, $seq, Twig_NodeList $body, Twig_Node $else = null, $withLoop = false, $lineno, $tag = null)
29 30
   {
30 31
     parent::__construct($lineno, $tag);
31 32
     $this->isMultitarget = $isMultitarget;
... ...
@@ -33,6 +34,7 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
33 34
     $this->seq = $seq;
34 35
     $this->body = $body;
35 36
     $this->else = $else;
37
+    $this->withLoop = $withLoop;
36 38
     $this->lineno = $lineno;
37 39
   }
38 40
 
... ...
@@ -72,19 +74,27 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
72 74
       ->write("\$seq$var = twig_iterator_to_array(")
73 75
       ->subcompile($this->seq)
74 76
       ->raw(");\n")
75
-      ->write("\$length = count(\$seq$var);\n")
76
-
77
-      ->write("\$context['loop'] = array(\n")
78
-      ->write("  'parent'    => \$context['_parent'],\n")
79
-      ->write("  'length'    => \$length,\n")
80
-      ->write("  'index0'    => 0,\n")
81
-      ->write("  'index'     => 1,\n")
82
-      ->write("  'revindex0' => \$length - 1,\n")
83
-      ->write("  'revindex'  => \$length,\n")
84
-      ->write("  'first'     => true,\n")
85
-      ->write("  'last'      => 1 === \$length,\n")
86
-      ->write(");\n")
77
+    ;
78
+
79
+    if ($this->withLoop)
80
+    {
81
+      $compiler
82
+        ->write("\$length = count(\$seq$var);\n")
83
+
84
+        ->write("\$context['loop'] = array(\n")
85
+        ->write("  'parent'    => \$context['_parent'],\n")
86
+        ->write("  'length'    => \$length,\n")
87
+        ->write("  'index0'    => 0,\n")
88
+        ->write("  'index'     => 1,\n")
89
+        ->write("  'revindex0' => \$length - 1,\n")
90
+        ->write("  'revindex'  => \$length,\n")
91
+        ->write("  'first'     => true,\n")
92
+        ->write("  'last'      => 1 === \$length,\n")
93
+        ->write(");\n")
94
+      ;
95
+    }
87 96
 
97
+    $compiler
88 98
       ->write("foreach (\$seq$var as \$context[")
89 99
       ->repr($loopVars[0])
90 100
       ->raw("] => \$context[")
... ...
@@ -99,16 +109,21 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
99 109
       $compiler->write("\$context['_iterated'] = true;\n");
100 110
     }
101 111
 
102
-    $compiler
103
-      ->subcompile($this->body)
112
+    $compiler->subcompile($this->body);
104 113
 
105
-      ->write("++\$context['loop']['index0'];\n")
106
-      ->write("++\$context['loop']['index'];\n")
107
-      ->write("--\$context['loop']['revindex0'];\n")
108
-      ->write("--\$context['loop']['revindex'];\n")
109
-      ->write("\$context['loop']['first'] = false;\n")
110
-      ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
114
+    if ($this->withLoop)
115
+    {
116
+      $compiler
117
+        ->write("++\$context['loop']['index0'];\n")
118
+        ->write("++\$context['loop']['index'];\n")
119
+        ->write("--\$context['loop']['revindex0'];\n")
120
+        ->write("--\$context['loop']['revindex'];\n")
121
+        ->write("\$context['loop']['first'] = false;\n")
122
+        ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n")
123
+      ;
124
+    }
111 125
 
126
+    $compiler
112 127
       ->outdent()
113 128
       ->write("}\n")
114 129
     ;
... ...
@@ -126,4 +141,9 @@ class Twig_Node_For extends Twig_Node implements Twig_NodeListInterface
126 141
     }
127 142
     $compiler->popContext();
128 143
   }
144
+
145
+  public function setWithLoop($boolean)
146
+  {
147
+    $this->withLoop = (Boolean) $boolean;
148
+  }
129 149
 }
... ...
@@ -17,6 +17,15 @@ class Twig_TokenParser_For extends Twig_TokenParser
17 17
     list($isMultitarget, $item) = $this->parser->getExpressionParser()->parseAssignmentExpression();
18 18
     $this->parser->getStream()->expect('in');
19 19
     $seq = $this->parser->getExpressionParser()->parseExpression();
20
+
21
+    $withLoop = true;
22
+    if ($this->parser->getStream()->test('without'))
23
+    {
24
+      $this->parser->getStream()->next();
25
+      $this->parser->getStream()->expect('loop');
26
+      $withLoop = false;
27
+    }
28
+
20 29
     $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
21 30
     $body = $this->parser->subparse(array($this, 'decideForFork'));
22 31
     if ($this->parser->getStream()->next()->getValue() == 'else')
... ...
@@ -30,7 +39,7 @@ class Twig_TokenParser_For extends Twig_TokenParser
30 39
     }
31 40
     $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE);
32 41
 
33
-    return new Twig_Node_For($isMultitarget, $item, $seq, $body, $else, $lineno, $this->getTag());
42
+    return new Twig_Node_For($isMultitarget, $item, $seq, $body, $else, $withLoop, $lineno, $this->getTag());
34 43
   }
35 44
 
36 45
   public function decideForFork($token)