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