|
1 <?php |
|
2 /** |
|
3 * Smarty Internal Plugin Compile Foreach |
|
4 * Compiles the {foreach} {foreachelse} {/foreach} tags |
|
5 * |
|
6 * @package Smarty |
|
7 * @subpackage Compiler |
|
8 * @author Uwe Tews |
|
9 */ |
|
10 |
|
11 /** |
|
12 * Smarty Internal Plugin Compile Foreach Class |
|
13 * |
|
14 * @package Smarty |
|
15 * @subpackage Compiler |
|
16 */ |
|
17 class Smarty_Internal_Compile_Foreach extends Smarty_Internal_CompileBase { |
|
18 /** |
|
19 * Attribute definition: Overwrites base class. |
|
20 * |
|
21 * @var array |
|
22 * @see Smarty_Internal_CompileBase |
|
23 */ |
|
24 public $required_attributes = array('from', 'item'); |
|
25 /** |
|
26 * Attribute definition: Overwrites base class. |
|
27 * |
|
28 * @var array |
|
29 * @see Smarty_Internal_CompileBase |
|
30 */ |
|
31 public $optional_attributes = array('name', 'key'); |
|
32 /** |
|
33 * Attribute definition: Overwrites base class. |
|
34 * |
|
35 * @var array |
|
36 * @see Smarty_Internal_CompileBase |
|
37 */ |
|
38 public $shorttag_order = array('from', 'item', 'key', 'name'); |
|
39 |
|
40 /** |
|
41 * Compiles code for the {foreach} tag |
|
42 * |
|
43 * @param array $args array with attributes from parser |
|
44 * @param object $compiler compiler object |
|
45 * @param array $parameter array with compilation parameter |
|
46 * |
|
47 * @return string compiled code |
|
48 */ |
|
49 public function compile($args, $compiler, $parameter) { |
|
50 // check and get attributes |
|
51 $_attr = $this->getAttributes($compiler, $args); |
|
52 |
|
53 $from = $_attr['from']; |
|
54 $item = $_attr['item']; |
|
55 if (!strncmp("\$_smarty_tpl->tpl_vars[$item]", $from, strlen($item) + 24)) { |
|
56 $compiler->trigger_template_error("item variable {$item} may not be the same variable as at 'from'", $compiler->lex->taglineno); |
|
57 } |
|
58 |
|
59 if (isset($_attr['key'])) { |
|
60 $key = $_attr['key']; |
|
61 } else { |
|
62 $key = null; |
|
63 } |
|
64 |
|
65 $this->openTag($compiler, 'foreach', array('foreach', $compiler->nocache, $item, $key, true)); |
|
66 // maybe nocache because of nocache variables |
|
67 $compiler->nocache = $compiler->nocache | $compiler->tag_nocache; |
|
68 |
|
69 if (isset($_attr['name'])) { |
|
70 $name = trim($_attr['name'], '\'"'); |
|
71 $has_name = true; |
|
72 $SmartyVarName = "\$smarty.foreach.{$name}."; |
|
73 } else { |
|
74 $has_name = false; |
|
75 } |
|
76 $ItemVarName = '$' . trim($item, '\'"') . '@'; |
|
77 // evaluates which Smarty variables and properties have to be computed |
|
78 |
|
79 if ($has_name) { |
|
80 $useSmartyForeach = $usesSmartyFirst = strpos($compiler->lex->data, $SmartyVarName . 'first') !== false; |
|
81 $useSmartyForeach = ($usesSmartyLast = strpos($compiler->lex->data, $SmartyVarName . 'last') !== false) || $useSmartyForeach; |
|
82 $useSmartyForeach = ($usesSmartyIndex = strpos($compiler->lex->data, $SmartyVarName . 'index') !== false) || $useSmartyForeach; |
|
83 $useSmartyForeach = ($usesSmartyIteration = (!$usesSmartyIndex && ($usesSmartyFirst || $usesSmartyLast)) || strpos($compiler->lex->data, $SmartyVarName . 'iteration') !== false) || $useSmartyForeach; |
|
84 $useSmartyForeach = ($usesSmartyShow = strpos($compiler->lex->data, $SmartyVarName . 'show') !== false) || $useSmartyForeach; |
|
85 $useSmartyForeach = ($usesSmartyTotal = $usesSmartyLast || strpos($compiler->lex->data, $SmartyVarName . 'total') !== false) || $useSmartyForeach; |
|
86 } else { |
|
87 $usesSmartyFirst = false; |
|
88 $usesSmartyLast = false; |
|
89 $usesSmartyTotal = false; |
|
90 $usesSmartyShow = false; |
|
91 $useSmartyForeach = false; |
|
92 } |
|
93 |
|
94 $usesPropKey = strpos($compiler->lex->data, $ItemVarName . 'key') !== false; |
|
95 $usesPropFirst = strpos($compiler->lex->data, $ItemVarName . 'first') !== false; |
|
96 $usesPropLast = strpos($compiler->lex->data, $ItemVarName . 'last') !== false; |
|
97 $usesPropIndex = strpos($compiler->lex->data, $ItemVarName . 'index') !== false; |
|
98 $usesPropIteration = (!$usesPropIndex && ($usesPropFirst || $usesPropLast)) || strpos($compiler->lex->data, $ItemVarName . 'iteration') !== false; |
|
99 $usesPropShow = strpos($compiler->lex->data, $ItemVarName . 'show') !== false; |
|
100 $usesPropTotal = $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'total') !== false; |
|
101 |
|
102 $keyTerm = ''; |
|
103 if ($usesPropKey) { |
|
104 $keyTerm = "\$_smarty_tpl->tpl_vars[$item]->key => "; |
|
105 } elseif ($key != null) { |
|
106 $keyTerm = "\$_smarty_tpl->tpl_vars[$key]->value => "; |
|
107 } |
|
108 // generate output code |
|
109 $output = "<?php\n"; |
|
110 $output .= "\$_from = $from;\n"; |
|
111 $output .= "if (!is_array(\$_from) && !is_object(\$_from)) {\n"; |
|
112 $output .= "settype(\$_from, 'array');\n"; |
|
113 $output .= "}\n"; |
|
114 $output .= "\$_smarty_tpl->tpl_vars[$item] = new Smarty_Variable;\n"; |
|
115 $output .= "\$_smarty_tpl->tpl_vars[$item]->_loop = false;\n"; |
|
116 if ($key != null) { |
|
117 $output .= "\$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable;\n"; |
|
118 } |
|
119 if ($usesPropTotal) { |
|
120 $output .= "\$_smarty_tpl->tpl_vars[$item]->total= \$_smarty_tpl->_count(\$_from);\n"; |
|
121 } |
|
122 if ($usesPropIteration) { |
|
123 $output .= "\$_smarty_tpl->tpl_vars[$item]->iteration=0;\n"; |
|
124 } |
|
125 if ($usesPropIndex) { |
|
126 $output .= "\$_smarty_tpl->tpl_vars[$item]->index=-1;\n"; |
|
127 } |
|
128 if ($usesPropShow) { |
|
129 if ($usesPropTotal) { |
|
130 $output .= "\$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->tpl_vars[$item]->total > 0);\n"; |
|
131 } else { |
|
132 $output .= "\$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->_count(\$_from) > 0);\n"; |
|
133 } |
|
134 } |
|
135 if ($has_name) { |
|
136 $prop = array(); |
|
137 if ($usesSmartyTotal) { |
|
138 $prop['total'] = "'total' => "; |
|
139 $prop['total'] .= $usesSmartyShow ? '$total = ' : ''; |
|
140 $prop['total'] .= '$_smarty_tpl->_count($_from)'; |
|
141 } |
|
142 if ($usesSmartyIteration) { |
|
143 $prop['iteration'] = "'iteration' => 0"; |
|
144 } |
|
145 if ($usesSmartyIndex) { |
|
146 $prop['index'] = "'index' => -1"; |
|
147 } |
|
148 if ($usesSmartyShow) { |
|
149 $prop['show'] = "'show' => "; |
|
150 if ($usesSmartyTotal) { |
|
151 $prop['show'] .= "(\$total > 0)"; |
|
152 } else { |
|
153 $prop['show'] .= "(\$_smarty_tpl->_count(\$_from) > 0)"; |
|
154 } |
|
155 } |
|
156 if ($useSmartyForeach) { |
|
157 $_vars = 'array(' . join(', ', $prop) . ')'; |
|
158 $foreachVar = "'__foreach_{$name}'"; |
|
159 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar] = new Smarty_Variable({$_vars});\n"; |
|
160 } |
|
161 } |
|
162 $output .= "foreach (\$_from as {$keyTerm}\$_smarty_tpl->tpl_vars[$item]->value) {\n"; |
|
163 $output .= "\$_smarty_tpl->tpl_vars[$item]->_loop = true;\n"; |
|
164 if ($key != null && $usesPropKey) { |
|
165 $output .= "\$_smarty_tpl->tpl_vars[$key]->value = \$_smarty_tpl->tpl_vars[$item]->key;\n"; |
|
166 } |
|
167 if ($usesPropIteration) { |
|
168 $output .= "\$_smarty_tpl->tpl_vars[$item]->iteration++;\n"; |
|
169 } |
|
170 if ($usesPropIndex) { |
|
171 $output .= "\$_smarty_tpl->tpl_vars[$item]->index++;\n"; |
|
172 } |
|
173 if ($usesPropFirst) { |
|
174 if ($usesPropIndex) { |
|
175 $output .= "\$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->index == 0;\n"; |
|
176 } else { |
|
177 $output .= "\$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->iteration == 1;\n"; |
|
178 } |
|
179 } |
|
180 if ($usesPropLast) { |
|
181 if ($usesPropIndex) { |
|
182 $output .= "\$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->index + 1 == \$_smarty_tpl->tpl_vars[$item]->total;\n"; |
|
183 } else { |
|
184 $output .= "\$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->iteration == \$_smarty_tpl->tpl_vars[$item]->total;\n"; |
|
185 } |
|
186 } |
|
187 if ($has_name) { |
|
188 if ($usesSmartyIteration) { |
|
189 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration']++;\n"; |
|
190 } |
|
191 if ($usesSmartyIndex) { |
|
192 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['index']++;\n"; |
|
193 } |
|
194 if ($usesSmartyFirst) { |
|
195 if ($usesSmartyIndex) { |
|
196 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['first'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['index'] == 0;\n"; |
|
197 } else { |
|
198 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['first'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration'] == 1;\n"; |
|
199 } |
|
200 } |
|
201 if ($usesSmartyLast) { |
|
202 if ($usesSmartyIndex) { |
|
203 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['last'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['index'] + 1 == \$_smarty_tpl->tpl_vars[$foreachVar]->value['total'];\n"; |
|
204 } else { |
|
205 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['last'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration'] == \$_smarty_tpl->tpl_vars[$foreachVar]->value['total'];\n"; |
|
206 } |
|
207 } |
|
208 } |
|
209 $itemName = trim($item, "'\""); |
|
210 $output .= "\$foreach_{$itemName}_Sav = \$_smarty_tpl->tpl_vars[$item];\n"; |
|
211 $output .= "?>"; |
|
212 |
|
213 return $output; |
|
214 } |
|
215 } |
|
216 |
|
217 /** |
|
218 * Smarty Internal Plugin Compile Foreachelse Class |
|
219 * |
|
220 * @package Smarty |
|
221 * @subpackage Compiler |
|
222 */ |
|
223 class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase { |
|
224 /** |
|
225 * Compiles code for the {foreachelse} tag |
|
226 * |
|
227 * @param array $args array with attributes from parser |
|
228 * @param object $compiler compiler object |
|
229 * @param array $parameter array with compilation parameter |
|
230 * |
|
231 * @return string compiled code |
|
232 */ |
|
233 public function compile($args, $compiler, $parameter) { |
|
234 // check and get attributes |
|
235 $_attr = $this->getAttributes($compiler, $args); |
|
236 |
|
237 list($openTag, $nocache, $item, $key, $foo) = $this->closeTag($compiler, array('foreach')); |
|
238 $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $item, $key, false)); |
|
239 $itemName = trim($item, "'\""); |
|
240 $output = "<?php\n"; |
|
241 $output .= "\$_smarty_tpl->tpl_vars[$item] = \$foreach_{$itemName}_Sav;\n"; |
|
242 $output .= "}\n"; |
|
243 $output .= "if (!\$_smarty_tpl->tpl_vars[$item]->_loop) {\n?>"; |
|
244 return $output; |
|
245 } |
|
246 } |
|
247 |
|
248 /** |
|
249 * Smarty Internal Plugin Compile Foreachclose Class |
|
250 * |
|
251 * @package Smarty |
|
252 * @subpackage Compiler |
|
253 */ |
|
254 class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase { |
|
255 /** |
|
256 * Compiles code for the {/foreach} tag |
|
257 * |
|
258 * @param array $args array with attributes from parser |
|
259 * @param object $compiler compiler object |
|
260 * @param array $parameter array with compilation parameter |
|
261 * |
|
262 * @return string compiled code |
|
263 */ |
|
264 public function compile($args, $compiler, $parameter) { |
|
265 // check and get attributes |
|
266 $_attr = $this->getAttributes($compiler, $args); |
|
267 // must endblock be nocache? |
|
268 if ($compiler->nocache) { |
|
269 $compiler->tag_nocache = true; |
|
270 } |
|
271 |
|
272 list($openTag, $compiler->nocache, $item, $key, $restore) = $this->closeTag($compiler, array('foreach', 'foreachelse')); |
|
273 $itemName = trim($item, "'\""); |
|
274 $output = "<?php\n"; |
|
275 if ($restore) { |
|
276 $output .= "\$_smarty_tpl->tpl_vars[$item] = \$foreach_{$itemName}_Sav;\n"; |
|
277 } |
|
278 $output .= "}\n?>"; |
|
279 |
|
280 return $output; |
|
281 } |
|
282 } |