library/smarty/libs/sysplugins/smarty_internal_compile_foreach.php
changeset 46 f11c31f7fa3e
parent 45 a56e7f9a0463
child 47 03388ec805b4
equal deleted inserted replaced
45:a56e7f9a0463 46:f11c31f7fa3e
     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_CompileBase {
       
    18     /**
       
    19      * Attribute definition: Overwrites base class.
       
    20      *
       
    21      * @var array
       
    22      * @see Smarty_Internal_CompileBase
       
    23      */
       
    24     public $required_attributes = array('from', 'item');
       
    25     /**
       
    26      * Attribute definition: Overwrites base class.
       
    27      *
       
    28      * @var array
       
    29      * @see Smarty_Internal_CompileBase
       
    30      */
       
    31     public $optional_attributes = array('name', 'key');
       
    32     /**
       
    33      * Attribute definition: Overwrites base class.
       
    34      *
       
    35      * @var array
       
    36      * @see Smarty_Internal_CompileBase
       
    37      */
       
    38     public $shorttag_order = array('from', 'item', 'key', 'name');
       
    39 
       
    40     /**
       
    41      * Compiles code for the {foreach} tag
       
    42      *
       
    43      * @param  array $args array with attributes from parser
       
    44      * @param  object $compiler compiler object
       
    45      * @param  array $parameter array with compilation parameter
       
    46      *
       
    47      * @return string compiled code
       
    48      */
       
    49     public function compile($args, $compiler, $parameter) {
       
    50         // check and get attributes
       
    51         $_attr = $this->getAttributes($compiler, $args);
       
    52 
       
    53         $from = $_attr['from'];
       
    54         $item = $_attr['item'];
       
    55         if (!strncmp("\$_smarty_tpl->tpl_vars[$item]", $from, strlen($item) + 24)) {
       
    56             $compiler->trigger_template_error("item variable {$item} may not be the same variable as at 'from'", $compiler->lex->taglineno);
       
    57         }
       
    58 
       
    59         if (isset($_attr['key'])) {
       
    60             $key = $_attr['key'];
       
    61         } else {
       
    62             $key = null;
       
    63         }
       
    64 
       
    65         $this->openTag($compiler, 'foreach', array('foreach', $compiler->nocache, $item, $key, true));
       
    66         // maybe nocache because of nocache variables
       
    67         $compiler->nocache = $compiler->nocache | $compiler->tag_nocache;
       
    68 
       
    69         if (isset($_attr['name'])) {
       
    70             $name = trim($_attr['name'], '\'"');
       
    71             $has_name = true;
       
    72             $SmartyVarName = "\$smarty.foreach.{$name}.";
       
    73         } else {
       
    74             $has_name = false;
       
    75         }
       
    76         $ItemVarName = '$' . trim($item, '\'"') . '@';
       
    77         // evaluates which Smarty variables and properties have to be computed
       
    78 
       
    79         if ($has_name) {
       
    80             $useSmartyForeach = $usesSmartyFirst = strpos($compiler->lex->data, $SmartyVarName . 'first') !== false;
       
    81             $useSmartyForeach = ($usesSmartyLast = strpos($compiler->lex->data, $SmartyVarName . 'last') !== false) || $useSmartyForeach;
       
    82             $useSmartyForeach = ($usesSmartyIndex = strpos($compiler->lex->data, $SmartyVarName . 'index') !== false) || $useSmartyForeach;
       
    83             $useSmartyForeach = ($usesSmartyIteration = (!$usesSmartyIndex && ($usesSmartyFirst || $usesSmartyLast)) || strpos($compiler->lex->data, $SmartyVarName . 'iteration') !== false) || $useSmartyForeach;
       
    84             $useSmartyForeach = ($usesSmartyShow = strpos($compiler->lex->data, $SmartyVarName . 'show') !== false) || $useSmartyForeach;
       
    85             $useSmartyForeach = ($usesSmartyTotal = $usesSmartyLast || strpos($compiler->lex->data, $SmartyVarName . 'total') !== false) || $useSmartyForeach;
       
    86         } else {
       
    87             $usesSmartyFirst = false;
       
    88             $usesSmartyLast = false;
       
    89             $usesSmartyTotal = false;
       
    90             $usesSmartyShow = false;
       
    91             $useSmartyForeach = false;
       
    92         }
       
    93 
       
    94         $usesPropKey = strpos($compiler->lex->data, $ItemVarName . 'key') !== false;
       
    95         $usesPropFirst = strpos($compiler->lex->data, $ItemVarName . 'first') !== false;
       
    96         $usesPropLast = strpos($compiler->lex->data, $ItemVarName . 'last') !== false;
       
    97         $usesPropIndex = strpos($compiler->lex->data, $ItemVarName . 'index') !== false;
       
    98         $usesPropIteration = (!$usesPropIndex && ($usesPropFirst || $usesPropLast)) || strpos($compiler->lex->data, $ItemVarName . 'iteration') !== false;
       
    99         $usesPropShow = strpos($compiler->lex->data, $ItemVarName . 'show') !== false;
       
   100         $usesPropTotal = $usesPropLast || strpos($compiler->lex->data, $ItemVarName . 'total') !== false;
       
   101 
       
   102         $keyTerm = '';
       
   103         if ($usesPropKey) {
       
   104             $keyTerm = "\$_smarty_tpl->tpl_vars[$item]->key => ";
       
   105         } elseif ($key != null) {
       
   106             $keyTerm = "\$_smarty_tpl->tpl_vars[$key]->value => ";
       
   107         }
       
   108         // generate output code
       
   109         $output = "<?php\n";
       
   110         $output .= "\$_from = $from;\n";
       
   111         $output .= "if (!is_array(\$_from) && !is_object(\$_from)) {\n";
       
   112         $output .= "settype(\$_from, 'array');\n";
       
   113         $output .= "}\n";
       
   114         $output .= "\$_smarty_tpl->tpl_vars[$item] = new Smarty_Variable;\n";
       
   115         $output .= "\$_smarty_tpl->tpl_vars[$item]->_loop = false;\n";
       
   116         if ($key != null) {
       
   117             $output .= "\$_smarty_tpl->tpl_vars[$key] = new Smarty_Variable;\n";
       
   118         }
       
   119         if ($usesPropTotal) {
       
   120             $output .= "\$_smarty_tpl->tpl_vars[$item]->total= \$_smarty_tpl->_count(\$_from);\n";
       
   121         }
       
   122         if ($usesPropIteration) {
       
   123             $output .= "\$_smarty_tpl->tpl_vars[$item]->iteration=0;\n";
       
   124         }
       
   125         if ($usesPropIndex) {
       
   126             $output .= "\$_smarty_tpl->tpl_vars[$item]->index=-1;\n";
       
   127         }
       
   128         if ($usesPropShow) {
       
   129             if ($usesPropTotal) {
       
   130                 $output .= "\$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->tpl_vars[$item]->total > 0);\n";
       
   131             } else {
       
   132                 $output .= "\$_smarty_tpl->tpl_vars[$item]->show = (\$_smarty_tpl->_count(\$_from) > 0);\n";
       
   133             }
       
   134         }
       
   135         if ($has_name) {
       
   136             $prop = array();
       
   137             if ($usesSmartyTotal) {
       
   138                 $prop['total'] = "'total' => ";
       
   139                 $prop['total'] .= $usesSmartyShow ? '$total = ' : '';
       
   140                 $prop['total'] .= '$_smarty_tpl->_count($_from)';
       
   141             }
       
   142             if ($usesSmartyIteration) {
       
   143                 $prop['iteration'] = "'iteration' => 0";
       
   144             }
       
   145             if ($usesSmartyIndex) {
       
   146                 $prop['index'] = "'index' => -1";
       
   147             }
       
   148             if ($usesSmartyShow) {
       
   149                 $prop['show'] = "'show' => ";
       
   150                 if ($usesSmartyTotal) {
       
   151                     $prop['show'] .= "(\$total > 0)";
       
   152                 } else {
       
   153                     $prop['show'] .= "(\$_smarty_tpl->_count(\$_from) > 0)";
       
   154                 }
       
   155             }
       
   156             if ($useSmartyForeach) {
       
   157                 $_vars = 'array(' . join(', ', $prop) . ')';
       
   158                 $foreachVar = "'__foreach_{$name}'";
       
   159                 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar] = new Smarty_Variable({$_vars});\n";
       
   160             }
       
   161         }
       
   162         $output .= "foreach (\$_from as {$keyTerm}\$_smarty_tpl->tpl_vars[$item]->value) {\n";
       
   163         $output .= "\$_smarty_tpl->tpl_vars[$item]->_loop = true;\n";
       
   164         if ($key != null && $usesPropKey) {
       
   165             $output .= "\$_smarty_tpl->tpl_vars[$key]->value = \$_smarty_tpl->tpl_vars[$item]->key;\n";
       
   166         }
       
   167         if ($usesPropIteration) {
       
   168             $output .= "\$_smarty_tpl->tpl_vars[$item]->iteration++;\n";
       
   169         }
       
   170         if ($usesPropIndex) {
       
   171             $output .= "\$_smarty_tpl->tpl_vars[$item]->index++;\n";
       
   172         }
       
   173         if ($usesPropFirst) {
       
   174             if ($usesPropIndex) {
       
   175                 $output .= "\$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->index == 0;\n";
       
   176             } else {
       
   177                 $output .= "\$_smarty_tpl->tpl_vars[$item]->first = \$_smarty_tpl->tpl_vars[$item]->iteration == 1;\n";
       
   178             }
       
   179         }
       
   180         if ($usesPropLast) {
       
   181             if ($usesPropIndex) {
       
   182                 $output .= "\$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->index + 1 == \$_smarty_tpl->tpl_vars[$item]->total;\n";
       
   183             } else {
       
   184                 $output .= "\$_smarty_tpl->tpl_vars[$item]->last = \$_smarty_tpl->tpl_vars[$item]->iteration == \$_smarty_tpl->tpl_vars[$item]->total;\n";
       
   185             }
       
   186         }
       
   187         if ($has_name) {
       
   188             if ($usesSmartyIteration) {
       
   189                 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration']++;\n";
       
   190             }
       
   191             if ($usesSmartyIndex) {
       
   192                 $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['index']++;\n";
       
   193             }
       
   194             if ($usesSmartyFirst) {
       
   195                 if ($usesSmartyIndex) {
       
   196                     $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['first'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['index'] == 0;\n";
       
   197                 } else {
       
   198                     $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['first'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration'] == 1;\n";
       
   199                 }
       
   200             }
       
   201             if ($usesSmartyLast) {
       
   202                 if ($usesSmartyIndex) {
       
   203                     $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['last'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['index'] + 1 == \$_smarty_tpl->tpl_vars[$foreachVar]->value['total'];\n";
       
   204                 } else {
       
   205                     $output .= "\$_smarty_tpl->tpl_vars[$foreachVar]->value['last'] = \$_smarty_tpl->tpl_vars[$foreachVar]->value['iteration'] == \$_smarty_tpl->tpl_vars[$foreachVar]->value['total'];\n";
       
   206                 }
       
   207             }
       
   208         }
       
   209         $itemName = trim($item, "'\"");
       
   210         $output .= "\$foreach_{$itemName}_Sav = \$_smarty_tpl->tpl_vars[$item];\n";
       
   211         $output .= "?>";
       
   212 
       
   213         return $output;
       
   214     }
       
   215 }
       
   216 
       
   217 /**
       
   218  * Smarty Internal Plugin Compile Foreachelse Class
       
   219  *
       
   220  * @package    Smarty
       
   221  * @subpackage Compiler
       
   222  */
       
   223 class Smarty_Internal_Compile_Foreachelse extends Smarty_Internal_CompileBase {
       
   224     /**
       
   225      * Compiles code for the {foreachelse} tag
       
   226      *
       
   227      * @param  array $args array with attributes from parser
       
   228      * @param  object $compiler compiler object
       
   229      * @param  array $parameter array with compilation parameter
       
   230      *
       
   231      * @return string compiled code
       
   232      */
       
   233     public function compile($args, $compiler, $parameter) {
       
   234         // check and get attributes
       
   235         $_attr = $this->getAttributes($compiler, $args);
       
   236 
       
   237         list($openTag, $nocache, $item, $key, $foo) = $this->closeTag($compiler, array('foreach'));
       
   238         $this->openTag($compiler, 'foreachelse', array('foreachelse', $nocache, $item, $key, false));
       
   239         $itemName = trim($item, "'\"");
       
   240         $output = "<?php\n";
       
   241         $output .= "\$_smarty_tpl->tpl_vars[$item] = \$foreach_{$itemName}_Sav;\n";
       
   242         $output .= "}\n";
       
   243         $output .= "if (!\$_smarty_tpl->tpl_vars[$item]->_loop) {\n?>";
       
   244         return $output;
       
   245     }
       
   246 }
       
   247 
       
   248 /**
       
   249  * Smarty Internal Plugin Compile Foreachclose Class
       
   250  *
       
   251  * @package    Smarty
       
   252  * @subpackage Compiler
       
   253  */
       
   254 class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase {
       
   255     /**
       
   256      * Compiles code for the {/foreach} tag
       
   257      *
       
   258      * @param  array $args array with attributes from parser
       
   259      * @param  object $compiler compiler object
       
   260      * @param  array $parameter array with compilation parameter
       
   261      *
       
   262      * @return string compiled code
       
   263      */
       
   264     public function compile($args, $compiler, $parameter) {
       
   265         // check and get attributes
       
   266         $_attr = $this->getAttributes($compiler, $args);
       
   267         // must endblock be nocache?
       
   268         if ($compiler->nocache) {
       
   269             $compiler->tag_nocache = true;
       
   270         }
       
   271 
       
   272         list($openTag, $compiler->nocache, $item, $key, $restore) = $this->closeTag($compiler, array('foreach', 'foreachelse'));
       
   273         $itemName = trim($item, "'\"");
       
   274         $output = "<?php\n";
       
   275         if ($restore) {
       
   276             $output .= "\$_smarty_tpl->tpl_vars[$item] = \$foreach_{$itemName}_Sav;\n";
       
   277         }
       
   278         $output .= "}\n?>";
       
   279 
       
   280         return $output;
       
   281     }
       
   282 }