1: <?php
2: /**
3: * Smarty Internal Plugin Compile For
4: * Compiles the {for} {forelse} {/for} tags
5: *
6: * @package Smarty
7: * @subpackage Compiler
8: * @author Uwe Tews
9: */
10:
11: /**
12: * Smarty Internal Plugin Compile For Class
13: *
14: * @package Smarty
15: * @subpackage Compiler
16: */
17: class Smarty_Internal_Compile_For extends Smarty_Internal_CompileBase
18: {
19: /**
20: * Compiles code for the {for} tag
21: * Smarty 3 does implement two different syntax's:
22: * - {for $var in $array}
23: * For looping over arrays or iterators
24: * - {for $x=0; $x<$y; $x++}
25: * For general loops
26: * The parser is generating different sets of attribute by which this compiler can
27: * determine which syntax is used.
28: *
29: * @param array $args array with attributes from parser
30: * @param object $compiler compiler object
31: * @param array $parameter array with compilation parameter
32: *
33: * @return string compiled code
34: */
35: public function compile($args, $compiler, $parameter)
36: {
37: $compiler->loopNesting++;
38: if ($parameter === 0) {
39: $this->required_attributes = array('start', 'to');
40: $this->optional_attributes = array('max', 'step');
41: } else {
42: $this->required_attributes = array('start', 'ifexp', 'var', 'step');
43: $this->optional_attributes = array();
44: }
45: $this->mapCache = array();
46: // check and get attributes
47: $_attr = $this->getAttributes($compiler, $args);
48: $output = "<?php\n";
49: if ($parameter === 1) {
50: foreach ($_attr[ 'start' ] as $_statement) {
51: if (is_array($_statement[ 'var' ])) {
52: $var = $_statement[ 'var' ][ 'var' ];
53: $index = $_statement[ 'var' ][ 'smarty_internal_index' ];
54: } else {
55: $var = $_statement[ 'var' ];
56: $index = '';
57: }
58: $output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable(null, \$_smarty_tpl->isRenderingCache);\n";
59: $output .= "\$_smarty_tpl->tpl_vars[$var]->value{$index} = {$_statement['value']};\n";
60: }
61: if (is_array($_attr[ 'var' ])) {
62: $var = $_attr[ 'var' ][ 'var' ];
63: $index = $_attr[ 'var' ][ 'smarty_internal_index' ];
64: } else {
65: $var = $_attr[ 'var' ];
66: $index = '';
67: }
68: $output .= "if ($_attr[ifexp]) {\nfor (\$_foo=true;$_attr[ifexp]; \$_smarty_tpl->tpl_vars[$var]->value{$index}$_attr[step]) {\n";
69: } else {
70: $_statement = $_attr[ 'start' ];
71: if (is_array($_statement[ 'var' ])) {
72: $var = $_statement[ 'var' ][ 'var' ];
73: $index = $_statement[ 'var' ][ 'smarty_internal_index' ];
74: } else {
75: $var = $_statement[ 'var' ];
76: $index = '';
77: }
78: $output .= "\$_smarty_tpl->tpl_vars[$var] = new Smarty_Variable(null, \$_smarty_tpl->isRenderingCache);";
79: if (isset($_attr[ 'step' ])) {
80: $output .= "\$_smarty_tpl->tpl_vars[$var]->step = $_attr[step];";
81: } else {
82: $output .= "\$_smarty_tpl->tpl_vars[$var]->step = 1;";
83: }
84: if (isset($_attr[ 'max' ])) {
85: $output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) min(ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step)),$_attr[max]);\n";
86: } else {
87: $output .= "\$_smarty_tpl->tpl_vars[$var]->total = (int) ceil((\$_smarty_tpl->tpl_vars[$var]->step > 0 ? $_attr[to]+1 - ($_statement[value]) : $_statement[value]-($_attr[to])+1)/abs(\$_smarty_tpl->tpl_vars[$var]->step));\n";
88: }
89: $output .= "if (\$_smarty_tpl->tpl_vars[$var]->total > 0) {\n";
90: $output .= "for (\$_smarty_tpl->tpl_vars[$var]->value{$index} = $_statement[value], \$_smarty_tpl->tpl_vars[$var]->iteration = 1;\$_smarty_tpl->tpl_vars[$var]->iteration <= \$_smarty_tpl->tpl_vars[$var]->total;\$_smarty_tpl->tpl_vars[$var]->value{$index} += \$_smarty_tpl->tpl_vars[$var]->step, \$_smarty_tpl->tpl_vars[$var]->iteration++) {\n";
91: $output .= "\$_smarty_tpl->tpl_vars[$var]->first = \$_smarty_tpl->tpl_vars[$var]->iteration === 1;";
92: $output .= "\$_smarty_tpl->tpl_vars[$var]->last = \$_smarty_tpl->tpl_vars[$var]->iteration === \$_smarty_tpl->tpl_vars[$var]->total;";
93: }
94: $output .= '?>';
95: $this->openTag($compiler, 'for', array('for', $compiler->nocache));
96: // maybe nocache because of nocache variables
97: $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
98: // return compiled code
99: return $output;
100: }
101: }
102:
103: /**
104: * Smarty Internal Plugin Compile Forelse Class
105: *
106: * @package Smarty
107: * @subpackage Compiler
108: */
109: class Smarty_Internal_Compile_Forelse extends Smarty_Internal_CompileBase
110: {
111: /**
112: * Compiles code for the {forelse} tag
113: *
114: * @param array $args array with attributes from parser
115: * @param object $compiler compiler object
116: * @param array $parameter array with compilation parameter
117: *
118: * @return string compiled code
119: */
120: public function compile($args, $compiler, $parameter)
121: {
122: // check and get attributes
123: $_attr = $this->getAttributes($compiler, $args);
124: list($openTag, $nocache) = $this->closeTag($compiler, array('for'));
125: $this->openTag($compiler, 'forelse', array('forelse', $nocache));
126: return "<?php }} else { ?>";
127: }
128: }
129:
130: /**
131: * Smarty Internal Plugin Compile Forclose Class
132: *
133: * @package Smarty
134: * @subpackage Compiler
135: */
136: class Smarty_Internal_Compile_Forclose extends Smarty_Internal_CompileBase
137: {
138: /**
139: * Compiles code for the {/for} tag
140: *
141: * @param array $args array with attributes from parser
142: * @param object $compiler compiler object
143: * @param array $parameter array with compilation parameter
144: *
145: * @return string compiled code
146: */
147: public function compile($args, $compiler, $parameter)
148: {
149: $compiler->loopNesting--;
150: // check and get attributes
151: $_attr = $this->getAttributes($compiler, $args);
152: // must endblock be nocache?
153: if ($compiler->nocache) {
154: $compiler->tag_nocache = true;
155: }
156: list($openTag, $compiler->nocache) = $this->closeTag($compiler, array('for', 'forelse'));
157: $output = "<?php }\n";
158: if ($openTag !== 'forelse') {
159: $output .= "}\n";
160: }
161: $output .= "?>";
162: return $output;
163: }
164: }
165: