Fix all foreach unit tests

This commit is contained in:
Simon Wisselink
2023-01-23 15:16:45 +01:00
parent ad2703dd75
commit 68c59e6627
7 changed files with 53 additions and 29 deletions

View File

@@ -32,7 +32,7 @@ class ForeachClose extends Base {
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) { public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
$compiler->loopNesting--; $compiler->loopNesting--;
[$openTag, $nocache_pushed, $local, $itemVar, $restore] = $this->closeTag($compiler, ['foreach', 'foreachelse']); [$openTag, $nocache_pushed, $localVariablePrefix, $item, $restore] = $this->closeTag($compiler, ['foreach', 'foreachelse']);
if ($nocache_pushed) { if ($nocache_pushed) {
// pop the pushed virtual nocache tag // pop the pushed virtual nocache tag
@@ -41,8 +41,8 @@ class ForeachClose extends Base {
} }
$output = "<?php\n"; $output = "<?php\n";
if ($restore === 2) { if ($restore) {
$output .= "{$itemVar} = {$local}saved;\n"; $output .= "\$_smarty_tpl->setVariable('{$item}', {$localVariablePrefix}Backup);\n";
} }
$output .= "}\n"; $output .= "}\n";
/* @var \Smarty\Compile\Tag\ForeachTag $foreachCompiler */ /* @var \Smarty\Compile\Tag\ForeachTag $foreachCompiler */

View File

@@ -22,13 +22,13 @@ class ForeachElse extends Base {
*/ */
public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) { public function compile($args, \Smarty\Compiler\Template $compiler, $parameter = [], $tag = null, $function = null) {
[$openTag, $nocache_pushed, $local, $itemVar, $restore] = $this->closeTag($compiler, ['foreach']); [$openTag, $nocache_pushed, $localVariablePrefix, $item, $restore] = $this->closeTag($compiler, ['foreach']);
$this->openTag($compiler, 'foreachelse', ['foreachelse', $nocache_pushed, $local, $itemVar, 0]); $this->openTag($compiler, 'foreachelse', ['foreachelse', $nocache_pushed, $localVariablePrefix, $item, false]);
$output = "<?php\n"; $output = "<?php\n";
if ($restore === 2) { if ($restore) {
$output .= "{$itemVar} = {$local}saved;\n"; $output .= "\$_smarty_tpl->setVariable('{$item}', {$localVariablePrefix}Backup);\n";
} }
$output .= "}\nif ({$itemVar}->do_else) {\n?>"; $output .= "}\nif ({$localVariablePrefix}DoElse) {\n?>";
return $output; return $output;
} }
} }

View File

@@ -39,7 +39,7 @@ class ForeachTag extends ForeachSection {
* *
* @var int * @var int
*/ */
protected $counter = 0; private static $counter = 0;
/** /**
* Name of this tag * Name of this tag
@@ -120,8 +120,10 @@ class ForeachTag extends ForeachSection {
} }
} }
} }
$itemVar = "\$_smarty_tpl->tpl_vars['{$item}']";
$local = '$__foreach_' . $attributes['item'] . '_' . $this->counter++ . '_'; $itemVar = "\$_smarty_tpl->getVariable('{$item}')";
$localVariablePrefix = '$foreach' . self::$counter++;
// search for used tag attributes // search for used tag attributes
$itemAttr = []; $itemAttr = [];
$namedAttr = []; $namedAttr = [];
@@ -172,7 +174,7 @@ class ForeachTag extends ForeachSection {
} }
$keyTerm = ''; $keyTerm = '';
if (isset($attributes['key'])) { if (isset($attributes['key'])) {
$keyTerm = "\$_smarty_tpl->tpl_vars['{$key}']->value => "; $keyTerm = "\$_smarty_tpl->getVariable('{$key}')->value => ";
} }
if (isset($itemAttr['key'])) { if (isset($itemAttr['key'])) {
$keyTerm = "{$itemVar}->key => "; $keyTerm = "{$itemVar}->key => ";
@@ -191,7 +193,7 @@ class ForeachTag extends ForeachSection {
$this->openTag( $this->openTag(
$compiler, $compiler,
'foreach', 'foreach',
['foreach', $compiler->tag_nocache, $local, $itemVar, empty($itemAttr) ? 1 : 2] ['foreach', $compiler->tag_nocache, $localVariablePrefix, $item, !empty($itemAttr)]
); );
// generate output code // generate output code
@@ -217,9 +219,9 @@ class ForeachTag extends ForeachSection {
if (isset($itemAttr['index'])) { if (isset($itemAttr['index'])) {
$output .= "{$itemVar}->index = -1;\n"; $output .= "{$itemVar}->index = -1;\n";
} }
$output .= "{$itemVar}->do_else = true;\n"; $output .= "{$localVariablePrefix}DoElse = true;\n";
$output .= "if (\$_from !== null) foreach (\$_from as {$keyTerm}{$itemVar}->value) {\n"; $output .= "foreach (\$_from ?? [] as {$keyTerm}{$itemVar}->value) {\n";
$output .= "{$itemVar}->do_else = false;\n"; $output .= "{$localVariablePrefix}DoElse = false;\n";
if (isset($attributes['key']) && isset($itemAttr['key'])) { if (isset($attributes['key']) && isset($itemAttr['key'])) {
$output .= "\$_smarty_tpl->assign('{$key}', {$itemVar}->key);\n"; $output .= "\$_smarty_tpl->assign('{$key}', {$itemVar}->key);\n";
} }
@@ -250,7 +252,7 @@ class ForeachTag extends ForeachSection {
} }
} }
if (!empty($itemAttr)) { if (!empty($itemAttr)) {
$output .= "{$local}saved = {$itemVar};\n"; $output .= "{$localVariablePrefix}Backup = clone \$_smarty_tpl->getVariable('{$item}');\n";
} }
$output .= '?>'; $output .= '?>';
return $output; return $output;

View File

@@ -126,7 +126,14 @@ class Data
break; break;
case self::SCOPE_LOCAL: case self::SCOPE_LOCAL:
default: default:
$this->tpl_vars[ $tpl_var ] = new Variable($value, $nocache); if ($this->hasVariable($tpl_var)) {
$this->getVariable($tpl_var)->setValue($value);
if ($nocache) {
$this->getVariable($tpl_var)->setNocache(true);
}
} else {
$this->tpl_vars[ $tpl_var ] = new Variable($value, $nocache);
}
} }
return $this; return $this;
@@ -251,6 +258,17 @@ class Data
return new UndefinedVariable(); return new UndefinedVariable();
} }
/**
* Directly sets a complete Variable object in the variable with the given name.
* @param $varName
* @param Variable $variableObject
*
* @return void
*/
public function setVariable($varName, Variable $variableObject) {
$this->tpl_vars[$varName] = $variableObject;
}
/** /**
* Indicates if given variable has been set. * Indicates if given variable has been set.
* @param $varName * @param $varName

View File

@@ -624,12 +624,12 @@ expr(res) ::= ternary(v). {
// ++$a / --$a // ++$a / --$a
expr(res) ::= INCDEC(i2) DOLLARID(i). { expr(res) ::= INCDEC(i2) DOLLARID(i). {
res = '$_smarty_tpl->_getVariable(\''. substr(i,1) .'\')->preIncDec(\'' . i2 . '\')'; res = '$_smarty_tpl->getVariable(\''. substr(i,1) .'\')->preIncDec(\'' . i2 . '\')';
} }
// $a++ / $a-- // $a++ / $a--
expr(res) ::= DOLLARID(i) INCDEC(i2). { expr(res) ::= DOLLARID(i) INCDEC(i2). {
res = '$_smarty_tpl->_getVariable(\''. substr(i,1) .'\')->postIncDec(\'' . i2 . '\')'; res = '$_smarty_tpl->getVariable(\''. substr(i,1) .'\')->postIncDec(\'' . i2 . '\')';
} }
// resources/streams // resources/streams
@@ -845,7 +845,7 @@ variable(res) ::= varindexed(vi). {
// variable with property // variable with property
variable(res) ::= varvar(v) AT ID(p). { variable(res) ::= varvar(v) AT ID(p). {
res = '$_smarty_tpl->_getVariable('. v .')->'.p; res = '$_smarty_tpl->getVariable('. v .')->'.p;
} }
// object // object

View File

@@ -62,7 +62,7 @@ class ForeachRuntime {
if ($tpl->hasVariable($item)) { if ($tpl->hasVariable($item)) {
$saveVars['item'] = [ $saveVars['item'] = [
$item, $item,
$tpl->getVariable($item), $tpl->getVariable($item)->getValue(),
]; ];
} }
$tpl->assign($item,null); $tpl->assign($item,null);
@@ -73,7 +73,7 @@ class ForeachRuntime {
if ($tpl->hasVariable($key)) { if ($tpl->hasVariable($key)) {
$saveVars['key'] = [ $saveVars['key'] = [
$key, $key,
$tpl->getVariable($key), clone $tpl->getVariable($key),
]; ];
} }
$tpl->assign($key, null); $tpl->assign($key, null);
@@ -87,7 +87,7 @@ class ForeachRuntime {
if ($tpl->hasVariable($namedVar)) { if ($tpl->hasVariable($namedVar)) {
$saveVars['named'] = [ $saveVars['named'] = [
$namedVar, $namedVar,
$tpl->getVariable($namedVar), clone $tpl->getVariable($namedVar),
]; ];
} }
$namedProp = []; $namedProp = [];
@@ -147,14 +147,13 @@ class ForeachRuntime {
$saveVars = array_pop($this->stack); $saveVars = array_pop($this->stack);
if (!empty($saveVars)) { if (!empty($saveVars)) {
if (isset($saveVars['item'])) { if (isset($saveVars['item'])) {
$item = &$saveVars['item']; $tpl->getVariable($saveVars['item'][0])->setValue($saveVars['item'][1]);
$tpl->assign($item[0], $item[1]->getValue());
} }
if (isset($saveVars['key'])) { if (isset($saveVars['key'])) {
$tpl->tpl_vars[$saveVars['key'][0]] = $saveVars['key'][1]; $tpl->setVariable($saveVars['key'][0], $saveVars['key'][1]);
} }
if (isset($saveVars['named'])) { if (isset($saveVars['named'])) {
$tpl->tpl_vars[$saveVars['named'][0]] = $saveVars['named'][1]; $tpl->setVariable($saveVars['named'][0], $saveVars['named'][1]);
} }
} }
$levels--; $levels--;

View File

@@ -19,6 +19,11 @@ class Variable
*/ */
public $value = null; public $value = null;
/**
* Other r/w properties for foreach, for, while, etc.
*/
public $step, $total, $first, $last, $key, $show, $iteration, $index = null;
/** /**
* @param mixed|null $value * @param mixed|null $value
*/ */
@@ -31,7 +36,7 @@ class Variable
* *
* @var boolean * @var boolean
*/ */
public $nocache = false; private $nocache = false;
/** /**
* @param bool $nocache * @param bool $nocache