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