1: | <?php
|
2: | |
3: | |
4: | |
5: | |
6: | |
7: | |
8: | |
9: |
|
10: |
|
11: | |
12: | |
13: | |
14: | |
15: | |
16: |
|
17: | class Smarty_Internal_Compile_Section extends Smarty_Internal_Compile_Private_ForeachSection
|
18: | {
|
19: | |
20: | |
21: | |
22: | |
23: | |
24: |
|
25: | public $required_attributes = array('name', 'loop');
|
26: |
|
27: | |
28: | |
29: | |
30: | |
31: | |
32: |
|
33: | public $shorttag_order = array('name', 'loop');
|
34: |
|
35: | |
36: | |
37: | |
38: | |
39: | |
40: |
|
41: | public $optional_attributes = array('start', 'step', 'max', 'show', 'properties');
|
42: |
|
43: | |
44: | |
45: | |
46: | |
47: |
|
48: | public $counter = 0;
|
49: |
|
50: | |
51: | |
52: | |
53: | |
54: |
|
55: | public $tagName = 'section';
|
56: |
|
57: | |
58: | |
59: | |
60: | |
61: |
|
62: | public $nameProperties = array(
|
63: | 'first', 'last', 'index', 'iteration', 'show', 'total', 'rownum', 'index_prev',
|
64: | 'index_next', 'loop'
|
65: | );
|
66: |
|
67: | |
68: | |
69: | |
70: | |
71: |
|
72: | public $itemProperties = null;
|
73: |
|
74: | |
75: | |
76: | |
77: | |
78: |
|
79: | public $isNamed = true;
|
80: |
|
81: | |
82: | |
83: | |
84: | |
85: | |
86: | |
87: | |
88: | |
89: | |
90: |
|
91: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
92: | {
|
93: | $compiler->loopNesting++;
|
94: |
|
95: | $_attr = $this->getAttributes($compiler, $args);
|
96: | $attributes = array('name' => $compiler->getId($_attr[ 'name' ]));
|
97: | unset($_attr[ 'name' ]);
|
98: | foreach ($attributes as $a => $v) {
|
99: | if ($v === false) {
|
100: | $compiler->trigger_template_error("'{$a}' attribute/variable has illegal value", null, true);
|
101: | }
|
102: | }
|
103: | $local = "\$__section_{$attributes['name']}_" . $this->counter++ . '_';
|
104: | $sectionVar = "\$_smarty_tpl->tpl_vars['__smarty_section_{$attributes['name']}']";
|
105: | $this->openTag($compiler, 'section', array('section', $compiler->nocache, $local, $sectionVar));
|
106: |
|
107: | $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
|
108: | $initLocal = array();
|
109: | $initNamedProperty = array();
|
110: | $initFor = array();
|
111: | $incFor = array();
|
112: | $cmpFor = array();
|
113: | $propValue = array(
|
114: | 'index' => "{$sectionVar}->value['index']", 'show' => 'true', 'step' => 1,
|
115: | 'iteration' => "{$local}iteration",
|
116: | );
|
117: | $propType = array('index' => 2, 'iteration' => 2, 'show' => 0, 'step' => 0,);
|
118: |
|
119: | $this->scanForProperties($attributes, $compiler);
|
120: | if (!empty($this->matchResults[ 'named' ])) {
|
121: | $namedAttr = $this->matchResults[ 'named' ];
|
122: | }
|
123: | if (isset($_attr[ 'properties' ]) && preg_match_all("/['](.*?)[']/", $_attr[ 'properties' ], $match)) {
|
124: | foreach ($match[ 1 ] as $prop) {
|
125: | if (in_array($prop, $this->nameProperties)) {
|
126: | $namedAttr[ $prop ] = true;
|
127: | } else {
|
128: | $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
|
129: | }
|
130: | }
|
131: | }
|
132: | $namedAttr[ 'index' ] = true;
|
133: | $output = "<?php\n";
|
134: | foreach ($_attr as $attr_name => $attr_value) {
|
135: | switch ($attr_name) {
|
136: | case 'loop':
|
137: | if (is_numeric($attr_value)) {
|
138: | $v = (int)$attr_value;
|
139: | $t = 0;
|
140: | } else {
|
141: | $v = "(is_array(@\$_loop=$attr_value) ? count(\$_loop) : max(0, (int) \$_loop))";
|
142: | $t = 1;
|
143: | }
|
144: | if ($t === 1) {
|
145: | $initLocal[ 'loop' ] = $v;
|
146: | $v = "{$local}loop";
|
147: | }
|
148: | break;
|
149: | case 'show':
|
150: | if (is_bool($attr_value)) {
|
151: | $v = $attr_value ? 'true' : 'false';
|
152: | $t = 0;
|
153: | } else {
|
154: | $v = "(bool) $attr_value";
|
155: | $t = 3;
|
156: | }
|
157: | break;
|
158: | case 'step':
|
159: | if (is_numeric($attr_value)) {
|
160: | $v = (int)$attr_value;
|
161: | $v = ($v === 0) ? 1 : $v;
|
162: | $t = 0;
|
163: | break;
|
164: | }
|
165: | $initLocal[ 'step' ] = "((int)@$attr_value) === 0 ? 1 : (int)@$attr_value";
|
166: | $v = "{$local}step";
|
167: | $t = 2;
|
168: | break;
|
169: | case 'max':
|
170: | case 'start':
|
171: | if (is_numeric($attr_value)) {
|
172: | $v = (int)$attr_value;
|
173: | $t = 0;
|
174: | break;
|
175: | }
|
176: | $v = "(int)@$attr_value";
|
177: | $t = 3;
|
178: | break;
|
179: | }
|
180: | if ($t === 3 && $compiler->getId($attr_value)) {
|
181: | $t = 1;
|
182: | }
|
183: | $propValue[ $attr_name ] = $v;
|
184: | $propType[ $attr_name ] = $t;
|
185: | }
|
186: | if (isset($namedAttr[ 'step' ])) {
|
187: | $initNamedProperty[ 'step' ] = $propValue[ 'step' ];
|
188: | }
|
189: | if (isset($namedAttr[ 'iteration' ])) {
|
190: | $propValue[ 'iteration' ] = "{$sectionVar}->value['iteration']";
|
191: | }
|
192: | $incFor[ 'iteration' ] = "{$propValue['iteration']}++";
|
193: | $initFor[ 'iteration' ] = "{$propValue['iteration']} = 1";
|
194: | if ($propType[ 'step' ] === 0) {
|
195: | if ($propValue[ 'step' ] === 1) {
|
196: | $incFor[ 'index' ] = "{$sectionVar}->value['index']++";
|
197: | } elseif ($propValue[ 'step' ] > 1) {
|
198: | $incFor[ 'index' ] = "{$sectionVar}->value['index'] += {$propValue['step']}";
|
199: | } else {
|
200: | $incFor[ 'index' ] = "{$sectionVar}->value['index'] -= " . -$propValue[ 'step' ];
|
201: | }
|
202: | } else {
|
203: | $incFor[ 'index' ] = "{$sectionVar}->value['index'] += {$propValue['step']}";
|
204: | }
|
205: | if (!isset($propValue[ 'max' ])) {
|
206: | $propValue[ 'max' ] = $propValue[ 'loop' ];
|
207: | $propType[ 'max' ] = $propType[ 'loop' ];
|
208: | } elseif ($propType[ 'max' ] !== 0) {
|
209: | $propValue[ 'max' ] = "{$propValue['max']} < 0 ? {$propValue['loop']} : {$propValue['max']}";
|
210: | $propType[ 'max' ] = 1;
|
211: | } else {
|
212: | if ($propValue[ 'max' ] < 0) {
|
213: | $propValue[ 'max' ] = $propValue[ 'loop' ];
|
214: | $propType[ 'max' ] = $propType[ 'loop' ];
|
215: | }
|
216: | }
|
217: | if (!isset($propValue[ 'start' ])) {
|
218: | $start_code =
|
219: | array(1 => "{$propValue['step']} > 0 ? ", 2 => '0', 3 => ' : ', 4 => $propValue[ 'loop' ], 5 => ' - 1');
|
220: | if ($propType[ 'loop' ] === 0) {
|
221: | $start_code[ 5 ] = '';
|
222: | $start_code[ 4 ] = $propValue[ 'loop' ] - 1;
|
223: | }
|
224: | if ($propType[ 'step' ] === 0) {
|
225: | if ($propValue[ 'step' ] > 0) {
|
226: | $start_code = array(1 => '0');
|
227: | $propType[ 'start' ] = 0;
|
228: | } else {
|
229: | $start_code[ 1 ] = $start_code[ 2 ] = $start_code[ 3 ] = '';
|
230: | $propType[ 'start' ] = $propType[ 'loop' ];
|
231: | }
|
232: | } else {
|
233: | $propType[ 'start' ] = 1;
|
234: | }
|
235: | $propValue[ 'start' ] = join('', $start_code);
|
236: | } else {
|
237: | $start_code =
|
238: | array(
|
239: | 1 => "{$propValue['start']} < 0 ? ", 2 => 'max(', 3 => "{$propValue['step']} > 0 ? ", 4 => '0',
|
240: | 5 => ' : ', 6 => '-1', 7 => ', ', 8 => "{$propValue['start']} + {$propValue['loop']}", 10 => ')',
|
241: | 11 => ' : ', 12 => 'min(', 13 => $propValue[ 'start' ], 14 => ', ',
|
242: | 15 => "{$propValue['step']} > 0 ? ", 16 => $propValue[ 'loop' ], 17 => ' : ',
|
243: | 18 => $propType[ 'loop' ] === 0 ? $propValue[ 'loop' ] - 1 : "{$propValue['loop']} - 1",
|
244: | 19 => ')'
|
245: | );
|
246: | if ($propType[ 'step' ] === 0) {
|
247: | $start_code[ 3 ] = $start_code[ 5 ] = $start_code[ 15 ] = $start_code[ 17 ] = '';
|
248: | if ($propValue[ 'step' ] > 0) {
|
249: | $start_code[ 6 ] = $start_code[ 18 ] = '';
|
250: | } else {
|
251: | $start_code[ 4 ] = $start_code[ 16 ] = '';
|
252: | }
|
253: | }
|
254: | if ($propType[ 'start' ] === 0) {
|
255: | if ($propType[ 'loop' ] === 0) {
|
256: | $start_code[ 8 ] = $propValue[ 'start' ] + $propValue[ 'loop' ];
|
257: | }
|
258: | $propType[ 'start' ] = $propType[ 'step' ] + $propType[ 'loop' ];
|
259: | $start_code[ 1 ] = '';
|
260: | if ($propValue[ 'start' ] < 0) {
|
261: | for ($i = 11; $i <= 19; $i++) {
|
262: | $start_code[ $i ] = '';
|
263: | }
|
264: | if ($propType[ 'start' ] === 0) {
|
265: | $start_code = array(
|
266: | max(
|
267: | $propValue[ 'step' ] > 0 ? 0 : -1,
|
268: | $propValue[ 'start' ] + $propValue[ 'loop' ]
|
269: | )
|
270: | );
|
271: | }
|
272: | } else {
|
273: | for ($i = 1; $i <= 11; $i++) {
|
274: | $start_code[ $i ] = '';
|
275: | }
|
276: | if ($propType[ 'start' ] === 0) {
|
277: | $start_code =
|
278: | array(
|
279: | min(
|
280: | $propValue[ 'step' ] > 0 ? $propValue[ 'loop' ] : $propValue[ 'loop' ] - 1,
|
281: | $propValue[ 'start' ]
|
282: | )
|
283: | );
|
284: | }
|
285: | }
|
286: | }
|
287: | $propValue[ 'start' ] = join('', $start_code);
|
288: | }
|
289: | if ($propType[ 'start' ] !== 0) {
|
290: | $initLocal[ 'start' ] = $propValue[ 'start' ];
|
291: | $propValue[ 'start' ] = "{$local}start";
|
292: | }
|
293: | $initFor[ 'index' ] = "{$sectionVar}->value['index'] = {$propValue['start']}";
|
294: | if (!isset($_attr[ 'start' ]) && !isset($_attr[ 'step' ]) && !isset($_attr[ 'max' ])) {
|
295: | $propValue[ 'total' ] = $propValue[ 'loop' ];
|
296: | $propType[ 'total' ] = $propType[ 'loop' ];
|
297: | } else {
|
298: | $propType[ 'total' ] =
|
299: | $propType[ 'start' ] + $propType[ 'loop' ] + $propType[ 'step' ] + $propType[ 'max' ];
|
300: | if ($propType[ 'total' ] === 0) {
|
301: | $propValue[ 'total' ] =
|
302: | min(
|
303: | ceil(
|
304: | ($propValue[ 'step' ] > 0 ? $propValue[ 'loop' ] - $propValue[ 'start' ] :
|
305: | (int)$propValue[ 'start' ] + 1) / abs($propValue[ 'step' ])
|
306: | ),
|
307: | $propValue[ 'max' ]
|
308: | );
|
309: | } else {
|
310: | $total_code = array(
|
311: | 1 => 'min(', 2 => 'ceil(', 3 => '(', 4 => "{$propValue['step']} > 0 ? ",
|
312: | 5 => $propValue[ 'loop' ], 6 => ' - ', 7 => $propValue[ 'start' ], 8 => ' : ',
|
313: | 9 => $propValue[ 'start' ], 10 => '+ 1', 11 => ')', 12 => '/ ', 13 => 'abs(',
|
314: | 14 => $propValue[ 'step' ], 15 => ')', 16 => ')', 17 => ", {$propValue['max']})",
|
315: | );
|
316: | if (!isset($propValue[ 'max' ])) {
|
317: | $total_code[ 1 ] = $total_code[ 17 ] = '';
|
318: | }
|
319: | if ($propType[ 'loop' ] + $propType[ 'start' ] === 0) {
|
320: | $total_code[ 5 ] = $propValue[ 'loop' ] - $propValue[ 'start' ];
|
321: | $total_code[ 6 ] = $total_code[ 7 ] = '';
|
322: | }
|
323: | if ($propType[ 'start' ] === 0) {
|
324: | $total_code[ 9 ] = (int)$propValue[ 'start' ] + 1;
|
325: | $total_code[ 10 ] = '';
|
326: | }
|
327: | if ($propType[ 'step' ] === 0) {
|
328: | $total_code[ 13 ] = $total_code[ 15 ] = '';
|
329: | if ($propValue[ 'step' ] === 1 || $propValue[ 'step' ] === -1) {
|
330: | $total_code[ 2 ] = $total_code[ 12 ] = $total_code[ 14 ] = $total_code[ 16 ] = '';
|
331: | } elseif ($propValue[ 'step' ] < 0) {
|
332: | $total_code[ 14 ] = -$propValue[ 'step' ];
|
333: | }
|
334: | $total_code[ 4 ] = '';
|
335: | if ($propValue[ 'step' ] > 0) {
|
336: | $total_code[ 8 ] = $total_code[ 9 ] = $total_code[ 10 ] = '';
|
337: | } else {
|
338: | $total_code[ 5 ] = $total_code[ 6 ] = $total_code[ 7 ] = $total_code[ 8 ] = '';
|
339: | }
|
340: | }
|
341: | $propValue[ 'total' ] = join('', $total_code);
|
342: | }
|
343: | }
|
344: | if (isset($namedAttr[ 'loop' ])) {
|
345: | $initNamedProperty[ 'loop' ] = "'loop' => {$propValue['loop']}";
|
346: | }
|
347: | if (isset($namedAttr[ 'total' ])) {
|
348: | $initNamedProperty[ 'total' ] = "'total' => {$propValue['total']}";
|
349: | if ($propType[ 'total' ] > 0) {
|
350: | $propValue[ 'total' ] = "{$sectionVar}->value['total']";
|
351: | }
|
352: | } elseif ($propType[ 'total' ] > 0) {
|
353: | $initLocal[ 'total' ] = $propValue[ 'total' ];
|
354: | $propValue[ 'total' ] = "{$local}total";
|
355: | }
|
356: | $cmpFor[ 'iteration' ] = "{$propValue['iteration']} <= {$propValue['total']}";
|
357: | foreach ($initLocal as $key => $code) {
|
358: | $output .= "{$local}{$key} = {$code};\n";
|
359: | }
|
360: | $_vars = 'array(' . join(', ', $initNamedProperty) . ')';
|
361: | $output .= "{$sectionVar} = new Smarty_Variable({$_vars});\n";
|
362: | $cond_code = "{$propValue['total']} !== 0";
|
363: | if ($propType[ 'total' ] === 0) {
|
364: | if ($propValue[ 'total' ] === 0) {
|
365: | $cond_code = 'false';
|
366: | } else {
|
367: | $cond_code = 'true';
|
368: | }
|
369: | }
|
370: | if ($propType[ 'show' ] > 0) {
|
371: | $output .= "{$local}show = {$propValue['show']} ? {$cond_code} : false;\n";
|
372: | $output .= "if ({$local}show) {\n";
|
373: | } elseif ($propValue[ 'show' ] === 'true') {
|
374: | $output .= "if ({$cond_code}) {\n";
|
375: | } else {
|
376: | $output .= "if (false) {\n";
|
377: | }
|
378: | $jinit = join(', ', $initFor);
|
379: | $jcmp = join(', ', $cmpFor);
|
380: | $jinc = join(', ', $incFor);
|
381: | $output .= "for ({$jinit}; {$jcmp}; {$jinc}){\n";
|
382: | if (isset($namedAttr[ 'rownum' ])) {
|
383: | $output .= "{$sectionVar}->value['rownum'] = {$propValue['iteration']};\n";
|
384: | }
|
385: | if (isset($namedAttr[ 'index_prev' ])) {
|
386: | $output .= "{$sectionVar}->value['index_prev'] = {$propValue['index']} - {$propValue['step']};\n";
|
387: | }
|
388: | if (isset($namedAttr[ 'index_next' ])) {
|
389: | $output .= "{$sectionVar}->value['index_next'] = {$propValue['index']} + {$propValue['step']};\n";
|
390: | }
|
391: | if (isset($namedAttr[ 'first' ])) {
|
392: | $output .= "{$sectionVar}->value['first'] = ({$propValue['iteration']} === 1);\n";
|
393: | }
|
394: | if (isset($namedAttr[ 'last' ])) {
|
395: | $output .= "{$sectionVar}->value['last'] = ({$propValue['iteration']} === {$propValue['total']});\n";
|
396: | }
|
397: | $output .= '?>';
|
398: | return $output;
|
399: | }
|
400: | }
|
401: |
|
402: | |
403: | |
404: | |
405: | |
406: | |
407: |
|
408: | class Smarty_Internal_Compile_Sectionelse extends Smarty_Internal_CompileBase
|
409: | {
|
410: | |
411: | |
412: | |
413: | |
414: | |
415: | |
416: | |
417: |
|
418: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
419: | {
|
420: |
|
421: | $_attr = $this->getAttributes($compiler, $args);
|
422: | list($openTag, $nocache, $local, $sectionVar) = $this->closeTag($compiler, array('section'));
|
423: | $this->openTag($compiler, 'sectionelse', array('sectionelse', $nocache, $local, $sectionVar));
|
424: | return "<?php }} else {\n ?>";
|
425: | }
|
426: | }
|
427: |
|
428: | |
429: | |
430: | |
431: | |
432: | |
433: |
|
434: | class Smarty_Internal_Compile_Sectionclose extends Smarty_Internal_CompileBase
|
435: | {
|
436: | |
437: | |
438: | |
439: | |
440: | |
441: | |
442: | |
443: |
|
444: | public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
|
445: | {
|
446: | $compiler->loopNesting--;
|
447: |
|
448: | if ($compiler->nocache) {
|
449: | $compiler->tag_nocache = true;
|
450: | }
|
451: | list($openTag, $compiler->nocache, $local, $sectionVar) =
|
452: | $this->closeTag($compiler, array('section', 'sectionelse'));
|
453: | $output = "<?php\n";
|
454: | if ($openTag === 'sectionelse') {
|
455: | $output .= "}\n";
|
456: | } else {
|
457: | $output .= "}\n}\n";
|
458: | }
|
459: | $output .= '?>';
|
460: | return $output;
|
461: | }
|
462: | }
|
463: | |