]> git.mxchange.org Git - friendica.git/blob - vendor/smarty/smarty/libs/sysplugins/smarty_internal_compile_foreach.php
Add Smarty to Composer
[friendica.git] / vendor / smarty / smarty / libs / sysplugins / smarty_internal_compile_foreach.php
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_Compile_Private_ForeachSection
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     /**
28      * Attribute definition: Overwrites base class.
29      *
30      * @var array
31      * @see Smarty_Internal_CompileBase
32      */
33     public $optional_attributes = array('name', 'key', 'properties');
34
35     /**
36      * Attribute definition: Overwrites base class.
37      *
38      * @var array
39      * @see Smarty_Internal_CompileBase
40      */
41     public $shorttag_order = array('from', 'item', 'key', 'name');
42
43     /**
44      * counter
45      *
46      * @var int
47      */
48     public $counter = 0;
49
50     /**
51      * Name of this tag
52      *
53      * @var string
54      */
55     public $tagName = 'foreach';
56
57     /**
58      * Valid properties of $smarty.foreach.name.xxx variable
59      *
60      * @var array
61      */
62     public $nameProperties = array('first', 'last', 'index', 'iteration', 'show', 'total');
63
64     /**
65      * Valid properties of $item@xxx variable
66      *
67      * @var array
68      */
69     public $itemProperties = array('first', 'last', 'index', 'iteration', 'show', 'total', 'key');
70
71     /**
72      * Flag if tag had name attribute
73      *
74      * @var bool
75      */
76     public $isNamed = false;
77
78     /**
79      * Compiles code for the {foreach} tag
80      *
81      * @param  array                                $args      array with attributes from parser
82      * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
83      * @param  array                                $parameter array with compilation parameter
84      *
85      * @return string compiled code
86      * @throws \SmartyCompilerException
87      */
88     public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
89     {
90         $compiler->loopNesting ++;
91         // init
92         $this->isNamed = false;
93         // check and get attributes
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("'{$a}' and 'from' may not have same variable name '{$fromName}'",
123                                                       null, true);
124                 }
125             }
126         }
127
128         $itemVar = "\$_smarty_tpl->tpl_vars['{$item}']";
129         $local = '$__foreach_' . $attributes[ 'item' ] . '_' . $this->counter ++ . '_';
130         // search for used tag attributes
131         $itemAttr = array();
132         $namedAttr = array();
133         $this->scanForProperties($attributes, $compiler);
134         if (!empty($this->matchResults[ 'item' ])) {
135             $itemAttr = $this->matchResults[ 'item' ];
136         }
137         if (!empty($this->matchResults[ 'named' ])) {
138             $namedAttr = $this->matchResults[ 'named' ];
139         }
140         if (isset($_attr[ 'properties' ]) && preg_match_all("/['](.*?)[']/", $_attr[ 'properties' ], $match)) {
141             foreach ($match[ 1 ] as $prop) {
142                 if (in_array($prop, $this->itemProperties)) {
143                     $itemAttr[ $prop ] = true;
144                 } else {
145                     $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
146                 }
147             }
148             if ($this->isNamed) {
149                 foreach ($match[ 1 ] as $prop) {
150                     if (in_array($prop, $this->nameProperties)) {
151                         $nameAttr[ $prop ] = true;
152                     } else {
153                         $compiler->trigger_template_error("Invalid property '{$prop}'", null, true);
154                     }
155                 }
156             }
157         }
158         if (isset($itemAttr[ 'first' ])) {
159             $itemAttr[ 'index' ] = true;
160         }
161         if (isset($namedAttr[ 'first' ])) {
162             $namedAttr[ 'index' ] = true;
163         }
164         if (isset($namedAttr[ 'last' ])) {
165             $namedAttr[ 'iteration' ] = true;
166             $namedAttr[ 'total' ] = true;
167         }
168         if (isset($itemAttr[ 'last' ])) {
169             $itemAttr[ 'iteration' ] = true;
170             $itemAttr[ 'total' ] = true;
171         }
172         if (isset($namedAttr[ 'show' ])) {
173             $namedAttr[ 'total' ] = true;
174         }
175         if (isset($itemAttr[ 'show' ])) {
176             $itemAttr[ 'total' ] = true;
177         }
178         $keyTerm = '';
179         if (isset($attributes[ 'key' ])) {
180             $keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => ";
181         }
182         if (isset($itemAttr[ 'key' ])) {
183             $keyTerm = "{$itemVar}->key => ";
184         }
185         if ($this->isNamed) {
186             $foreachVar = "\$_smarty_tpl->tpl_vars['__smarty_foreach_{$attributes['name']}']";
187         }
188         $needTotal = isset($itemAttr[ 'total' ]);
189         // Register tag
190         $this->openTag($compiler, 'foreach',
191                        array('foreach', $compiler->nocache, $local, $itemVar, empty($itemAttr) ? 1 : 2));
192         // maybe nocache because of nocache variables
193         $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
194         // generate output code
195         $output = "<?php\n";
196         $output .= "\$_from = \$_smarty_tpl->smarty->ext->_foreach->init(\$_smarty_tpl, $from, " .
197                    var_export($item, true);
198         if ($name || $needTotal || $key) {
199             $output .= ', ' . var_export($needTotal, true);
200         }
201         if ($name || $key) {
202             $output .= ', ' . var_export($key, true);
203         }
204         if ($name) {
205             $output .= ', ' . var_export($name, true) . ', ' . var_export($namedAttr, true);
206         }
207         $output .= ");\n";
208         if (isset($itemAttr[ 'show' ])) {
209             $output .= "{$itemVar}->show = ({$itemVar}->total > 0);\n";
210         }
211         if (isset($itemAttr[ 'iteration' ])) {
212             $output .= "{$itemVar}->iteration = 0;\n";
213         }
214         if (isset($itemAttr[ 'index' ])) {
215             $output .= "{$itemVar}->index = -1;\n";
216         }
217         $output .= "if (\$_from !== null) {\n";
218         $output .= "foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n";
219         if (isset($attributes[ 'key' ]) && isset($itemAttr[ 'key' ])) {
220             $output .= "\$_smarty_tpl->tpl_vars['{$key}']->value = {$itemVar}->key;\n";
221         }
222         if (isset($itemAttr[ 'iteration' ])) {
223             $output .= "{$itemVar}->iteration++;\n";
224         }
225         if (isset($itemAttr[ 'index' ])) {
226             $output .= "{$itemVar}->index++;\n";
227         }
228         if (isset($itemAttr[ 'first' ])) {
229             $output .= "{$itemVar}->first = !{$itemVar}->index;\n";
230         }
231         if (isset($itemAttr[ 'last' ])) {
232             $output .= "{$itemVar}->last = {$itemVar}->iteration == {$itemVar}->total;\n";
233         }
234         if (isset($foreachVar)) {
235             if (isset($namedAttr[ 'iteration' ])) {
236                 $output .= "{$foreachVar}->value['iteration']++;\n";
237             }
238             if (isset($namedAttr[ 'index' ])) {
239                 $output .= "{$foreachVar}->value['index']++;\n";
240             }
241             if (isset($namedAttr[ 'first' ])) {
242                 $output .= "{$foreachVar}->value['first'] = !{$foreachVar}->value['index'];\n";
243             }
244             if (isset($namedAttr[ 'last' ])) {
245                 $output .= "{$foreachVar}->value['last'] = {$foreachVar}->value['iteration'] == {$foreachVar}->value['total'];\n";
246             }
247         }
248         if (!empty($itemAttr)) {
249             $output .= "{$local}saved = {$itemVar};\n";
250         }
251         $output .= "?>";
252
253         return $output;
254     }
255
256     /**
257      * Compiles code for to restore saved template variables
258      *
259      * @param int $levels number of levels to restore
260      *
261      * @return string compiled code
262      */
263     public function compileRestore($levels)
264     {
265         return "\$_smarty_tpl->smarty->ext->_foreach->restore(\$_smarty_tpl, {$levels});\n";
266     }
267 }
268
269 /**
270  * Smarty Internal Plugin Compile Foreachelse Class
271  *
272  * @package    Smarty
273  * @subpackage Compiler
274  */
275 class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase
276 {
277     /**
278      * Compiles code for the {foreachelse} tag
279      *
280      * @param  array                                $args      array with attributes from parser
281      * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
282      * @param  array                                $parameter array with compilation parameter
283      *
284      * @return string compiled code
285      */
286     public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
287     {
288         // check and get attributes
289         $_attr = $this->getAttributes($compiler, $args);
290
291         list($openTag, $nocache, $local, $itemVar, $restore) = $this->closeTag($compiler, array('foreach'));
292         $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $local, $itemVar, 0));
293         $output = "<?php\n";
294         if ($restore == 2) {
295             $output .= "{$itemVar} = {$local}saved;\n";
296         }
297         $output .= "}\n} else {\n?>\n";
298         return $output;
299     }
300 }
301
302 /**
303  * Smarty Internal Plugin Compile Foreachclose Class
304  *
305  * @package    Smarty
306  * @subpackage Compiler
307  */
308 class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase
309 {
310     /**
311      * Compiles code for the {/foreach} tag
312      *
313      * @param  array                                $args      array with attributes from parser
314      * @param \Smarty_Internal_TemplateCompilerBase $compiler  compiler object
315      * @param  array                                $parameter array with compilation parameter
316      *
317      * @return string compiled code
318      */
319     public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter)
320     {
321         $compiler->loopNesting --;
322         // must endblock be nocache?
323         if ($compiler->nocache) {
324             $compiler->tag_nocache = true;
325         }
326
327         list($openTag, $compiler->nocache, $local, $itemVar, $restore) =
328             $this->closeTag($compiler, array('foreach', 'foreachelse'));
329         $output = "<?php\n";
330
331         if ($restore == 2) {
332             $output .= "{$itemVar} = {$local}saved;\n";
333         }
334         if ($restore > 0) {
335             $output .= "}\n";
336         }
337         $output .= "}\n";
338         /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */
339         $foreachCompiler = $compiler->getTagCompiler('foreach');
340         $output .= $foreachCompiler->compileRestore(1);
341         $output .= "?>\n";
342         return $output;
343     }
344 }