1: | <?php
|
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: |
|
10: |
|
11: | |
12: | |
13: | |
14: | |
15: | |
16: |
|
17: | class Smarty_Internal_Compile_Foreach extends Smarty_Internal_Compile_Private_ForeachSection
|
18: | {
|
19: | |
20: | |
21: | |
22: | |
23: | |
24: |
|
25: | public $required_attributes = array('from', 'item');
|
26: |
|
27: | |
28: | |
29: | |
30: | |
31: | |
32: |
|
33: | public $optional_attributes = array('name', 'key', 'properties');
|
34: |
|
35: | |
36: | |
37: | |
38: | |
39: | |
40: |
|
41: | public $shorttag_order = array('from', 'item', 'key', 'name');
|
42: |
|
43: | |
44: | |
45: | |
46: | |
47: |
|
48: | public $counter = 0;
|
49: |
|
50: | |
51: | |
52: | |
53: | |
54: |
|
55: | public $tagName = 'foreach';
|
56: |
|
57: | |
58: | |
59: | |
60: | |
61: |
|
62: | public $nameProperties = array('first', 'last', 'index', 'iteration', 'show', 'total');
|
63: |
|
64: | |
65: | |
66: | |
67: | |
68: |
|
69: | public $itemProperties = array('first', 'last', 'index', 'iteration', 'show', 'total', 'key');
|
70: |
|
71: | |
72: | |
73: | |
74: | |
75: |
|
76: | public $isNamed = false;
|
77: |
|
78: | |
79: | |
80: | |
81: | |
82: | |
83: | |
84: | |
85: | |
86: | |
87: |
|
88: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
89: | {
|
90: | $compiler->loopNesting++;
|
91: |
|
92: | $this->isNamed = false;
|
93: |
|
94: | $_attr = $this->getAttributes($compiler, $args);
|
95: | $from = $_attr[ 'from' ];
|
96: | $item = $compiler->getId($_attr[ 'item' ]);
|
97: | if ($item === false) {
|
98: | $item = $compiler->getVariableName($_attr[ 'item' ]);
|
99: | }
|
100: | $key = $name = null;
|
101: | $attributes = array('item' => $item);
|
102: | if (isset($_attr[ 'key' ])) {
|
103: | $key = $compiler->getId($_attr[ 'key' ]);
|
104: | if ($key === false) {
|
105: | $key = $compiler->getVariableName($_attr[ 'key' ]);
|
106: | }
|
107: | $attributes[ 'key' ] = $key;
|
108: | }
|
109: | if (isset($_attr[ 'name' ])) {
|
110: | $this->isNamed = true;
|
111: | $name = $attributes[ 'name' ] = $compiler->getId($_attr[ 'name' ]);
|
112: | }
|
113: | foreach ($attributes as $a => $v) {
|
114: | if ($v === false) {
|
115: | $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true);
|
116: | }
|
117: | }
|
118: | $fromName = $compiler->getVariableName($_attr[ 'from' ]);
|
119: | if ($fromName) {
|
120: | foreach (array('item', 'key') as $a) {
|
121: | if (isset($attributes[ $a ]) && $attributes[ $a ] === $fromName) {
|
122: | $compiler->trigger_template_error(
|
123: | "'{$a}' and 'from' may not have same variable name '{$fromName}'",
|
124: | null,
|
125: | true
|
126: | );
|
127: | }
|
128: | }
|
129: | }
|
130: | $itemVar = "\$_smarty_tpl->tpl_vars['{$item}']";
|
131: | $local = '$__foreach_' . $attributes[ 'item' ] . '_' . $this->counter++ . '_';
|
132: |
|
133: | $itemAttr = array();
|
134: | $namedAttr = array();
|
135: | $this->scanForProperties($attributes, $compiler);
|
136: | if (!empty($this->matchResults[ 'item' ])) {
|
137: | $itemAttr = $this->matchResults[ 'item' ];
|
138: | }
|
139: | if (!empty($this->matchResults[ 'named' ])) {
|
140: | $namedAttr = $this->matchResults[ 'named' ];
|
141: | }
|
142: | if (isset($_attr[ 'properties' ]) && preg_match_all('/[\'](.*?)[\']/', $_attr[ 'properties' ], $match)) {
|
143: | foreach ($match[ 1 ] as $prop) {
|
144: | if (in_array($prop, $this->itemProperties)) {
|
145: | $itemAttr[ $prop ] = true;
|
146: | } else {
|
147: | $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
|
148: | }
|
149: | }
|
150: | if ($this->isNamed) {
|
151: | foreach ($match[ 1 ] as $prop) {
|
152: | if (in_array($prop, $this->nameProperties)) {
|
153: | $nameAttr[ $prop ] = true;
|
154: | } else {
|
155: | $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
|
156: | }
|
157: | }
|
158: | }
|
159: | }
|
160: | if (isset($itemAttr[ 'first' ])) {
|
161: | $itemAttr[ 'index' ] = true;
|
162: | }
|
163: | if (isset($namedAttr[ 'first' ])) {
|
164: | $namedAttr[ 'index' ] = true;
|
165: | }
|
166: | if (isset($namedAttr[ 'last' ])) {
|
167: | $namedAttr[ 'iteration' ] = true;
|
168: | $namedAttr[ 'total' ] = true;
|
169: | }
|
170: | if (isset($itemAttr[ 'last' ])) {
|
171: | $itemAttr[ 'iteration' ] = true;
|
172: | $itemAttr[ 'total' ] = true;
|
173: | }
|
174: | if (isset($namedAttr[ 'show' ])) {
|
175: | $namedAttr[ 'total' ] = true;
|
176: | }
|
177: | if (isset($itemAttr[ 'show' ])) {
|
178: | $itemAttr[ 'total' ] = true;
|
179: | }
|
180: | $keyTerm = '';
|
181: | if (isset($attributes[ 'key' ])) {
|
182: | $keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => ";
|
183: | }
|
184: | if (isset($itemAttr[ 'key' ])) {
|
185: | $keyTerm = "{$itemVar}->key => ";
|
186: | }
|
187: | if ($this->isNamed) {
|
188: | $foreachVar = "\$_smarty_tpl->tpl_vars['__smarty_foreach_{$attributes['name']}']";
|
189: | }
|
190: | $needTotal = isset($itemAttr[ 'total' ]);
|
191: |
|
192: | $this->openTag(
|
193: | $compiler,
|
194: | 'foreach',
|
195: | array('foreach', $compiler->nocache, $local, $itemVar, empty($itemAttr) ? 1 : 2)
|
196: | );
|
197: |
|
198: | $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
|
199: |
|
200: | $output = "<?php\n";
|
201: | $output .= "\$_from = \$_smarty_tpl->smarty->ext->_foreach->init(\$_smarty_tpl, $from, " .
|
202: | var_export($item, true);
|
203: | if ($name || $needTotal || $key) {
|
204: | $output .= ', ' . var_export($needTotal, true);
|
205: | }
|
206: | if ($name || $key) {
|
207: | $output .= ', ' . var_export($key, true);
|
208: | }
|
209: | if ($name) {
|
210: | $output .= ', ' . var_export($name, true) . ', ' . var_export($namedAttr, true);
|
211: | }
|
212: | $output .= ");\n";
|
213: | if (isset($itemAttr[ 'show' ])) {
|
214: | $output .= "{$itemVar}->show = ({$itemVar}->total > 0);\n";
|
215: | }
|
216: | if (isset($itemAttr[ 'iteration' ])) {
|
217: | $output .= "{$itemVar}->iteration = 0;\n";
|
218: | }
|
219: | if (isset($itemAttr[ 'index' ])) {
|
220: | $output .= "{$itemVar}->index = -1;\n";
|
221: | }
|
222: | $output .= "{$itemVar}->do_else = true;\n";
|
223: | $output .= "if (\$_from !== null) foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n";
|
224: | $output .= "{$itemVar}->do_else = false;\n";
|
225: | if (isset($attributes[ 'key' ]) && isset($itemAttr[ 'key' ])) {
|
226: | $output .= "\$_smarty_tpl->tpl_vars['{$key}']->value = {$itemVar}->key;\n";
|
227: | }
|
228: | if (isset($itemAttr[ 'iteration' ])) {
|
229: | $output .= "{$itemVar}->iteration++;\n";
|
230: | }
|
231: | if (isset($itemAttr[ 'index' ])) {
|
232: | $output .= "{$itemVar}->index++;\n";
|
233: | }
|
234: | if (isset($itemAttr[ 'first' ])) {
|
235: | $output .= "{$itemVar}->first = !{$itemVar}->index;\n";
|
236: | }
|
237: | if (isset($itemAttr[ 'last' ])) {
|
238: | $output .= "{$itemVar}->last = {$itemVar}->iteration === {$itemVar}->total;\n";
|
239: | }
|
240: | if (isset($foreachVar)) {
|
241: | if (isset($namedAttr[ 'iteration' ])) {
|
242: | $output .= "{$foreachVar}->value['iteration']++;\n";
|
243: | }
|
244: | if (isset($namedAttr[ 'index' ])) {
|
245: | $output .= "{$foreachVar}->value['index']++;\n";
|
246: | }
|
247: | if (isset($namedAttr[ 'first' ])) {
|
248: | $output .= "{$foreachVar}->value['first'] = !{$foreachVar}->value['index'];\n";
|
249: | }
|
250: | if (isset($namedAttr[ 'last' ])) {
|
251: | $output .= "{$foreachVar}->value['last'] = {$foreachVar}->value['iteration'] === {$foreachVar}->value['total'];\n";
|
252: | }
|
253: | }
|
254: | if (!empty($itemAttr)) {
|
255: | $output .= "{$local}saved = {$itemVar};\n";
|
256: | }
|
257: | $output .= '?>';
|
258: | return $output;
|
259: | }
|
260: |
|
261: | |
262: | |
263: | |
264: | |
265: | |
266: | |
267: |
|
268: | public function compileRestore($levels)
|
269: | {
|
270: | return "\$_smarty_tpl->smarty->ext->_foreach->restore(\$_smarty_tpl, {$levels});";
|
271: | }
|
272: | }
|
273: |
|
274: | |
275: | |
276: | |
277: | |
278: | |
279: |
|
280: | class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase
|
281: | {
|
282: | |
283: | |
284: | |
285: | |
286: | |
287: | |
288: | |
289: |
|
290: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
291: | {
|
292: |
|
293: | $_attr = $this->getAttributes($compiler, $args);
|
294: | list($openTag, $nocache, $local, $itemVar, $restore) = $this->closeTag($compiler, array('foreach'));
|
295: | $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $local, $itemVar, 0));
|
296: | $output = "<?php\n";
|
297: | if ($restore === 2) {
|
298: | $output .= "{$itemVar} = {$local}saved;\n";
|
299: | }
|
300: | $output .= "}\nif ({$itemVar}->do_else) {\n?>";
|
301: | return $output;
|
302: | }
|
303: | }
|
304: |
|
305: | |
306: | |
307: | |
308: | |
309: | |
310: |
|
311: | class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase
|
312: | {
|
313: | |
314: | |
315: | |
316: | |
317: | |
318: | |
319: | |
320: | |
321: |
|
322: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
323: | {
|
324: | $compiler->loopNesting--;
|
325: |
|
326: | if ($compiler->nocache) {
|
327: | $compiler->tag_nocache = true;
|
328: | }
|
329: | list(
|
330: | $openTag, $compiler->nocache, $local, $itemVar, $restore
|
331: | ) = $this->closeTag($compiler, array('foreach', 'foreachelse'));
|
332: | $output = "<?php\n";
|
333: | if ($restore === 2) {
|
334: | $output .= "{$itemVar} = {$local}saved;\n";
|
335: | }
|
336: | $output .= "}\n";
|
337: |
|
338: | $foreachCompiler = $compiler->getTagCompiler('foreach');
|
339: | $output .= $foreachCompiler->compileRestore(1);
|
340: | $output .= "?>";
|
341: | return $output;
|
342: | }
|
343: | }
|
344: | |