git-svn-id: http://svn.twig-project.org/trunk@216 93ef8e89-cb99-4229-a87c-7fa0fa45744b
... | ... |
@@ -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) |