bugfix {break} and {continue} could fail if {foreach}{/foreach} did contain other looping tags like {for}, {section} and {while} https://github.com/smarty-php/smarty/issues/323

This commit is contained in:
Uwe Tews
2017-11-22 01:21:09 +01:00
parent 40ea5d89da
commit 93909aacf8
4 changed files with 27 additions and 30 deletions

View File

@@ -1,4 +1,8 @@
===== 3.1.32 - dev === ===== 3.1.32 - dev ===
22.11.2017
- bugfix {break} and {continue} could fail if {foreach}{/foreach} did contain other
looping tags like {for}, {section} and {while} https://github.com/smarty-php/smarty/issues/323
20.11.2017 20.11.2017
- bugfix rework of newline spacing between tag code and template text. - bugfix rework of newline spacing between tag code and template text.
now again identical with Smarty2 (forum topic 26878) now again identical with Smarty2 (forum topic 26878)

View File

@@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = '3.1.32-dev-37'; const SMARTY_VERSION = '3.1.32-dev-38';
/** /**
* define variable scopes * define variable scopes
*/ */

View File

@@ -32,6 +32,13 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
*/ */
public $shorttag_order = array('levels'); public $shorttag_order = array('levels');
/**
* Tag name may be overloaded by Smarty_Internal_Compile_Continue
*
* @var string
*/
public $tag = 'break';
/** /**
* Compiles code for the {break} tag * Compiles code for the {break} tag
* *
@@ -44,13 +51,16 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
list($levels, $foreachLevels) = $this->checkLevels($args, $compiler); list($levels, $foreachLevels) = $this->checkLevels($args, $compiler);
$output = "<?php\n"; $output = "<?php ";
if ($foreachLevels) { if ($foreachLevels > 0 && $this->tag === 'continue') {
$foreachLevels--;
}
if ($foreachLevels > 0) {
/* @var Smarty_Internal_Compile_Foreach $foreachCompiler */ /* @var Smarty_Internal_Compile_Foreach $foreachCompiler */
$foreachCompiler = $compiler->getTagCompiler('foreach'); $foreachCompiler = $compiler->getTagCompiler('foreach');
$output .= $foreachCompiler->compileRestore($foreachLevels); $output .= $foreachCompiler->compileRestore($foreachLevels);
} }
$output .= "break {$levels};?>"; $output .= "{$this->tag} {$levels};?>";
return $output; return $output;
} }
@@ -59,12 +69,11 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
* *
* @param array $args array with attributes from parser * @param array $args array with attributes from parser
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
* @param string $tag tag name
* *
* @return array * @return array
* @throws \SmartyCompilerException * @throws \SmartyCompilerException
*/ */
public function checkLevels($args, Smarty_Internal_TemplateCompilerBase $compiler, $tag = 'break') public function checkLevels($args, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true); static $_is_loopy = array('for' => true, 'foreach' => true, 'while' => true, 'section' => true);
// check and get attributes // check and get attributes
@@ -86,7 +95,7 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
$stack_count = count($compiler->_tag_stack) - 1; $stack_count = count($compiler->_tag_stack) - 1;
$foreachLevels = 0; $foreachLevels = 0;
$lastTag = ''; $lastTag = '';
while ($level_count >= 0 && $stack_count >= 0) { while ($level_count > 0 && $stack_count >= 0) {
if (isset($_is_loopy[ $compiler->_tag_stack[ $stack_count ][ 0 ] ])) { if (isset($_is_loopy[ $compiler->_tag_stack[ $stack_count ][ 0 ] ])) {
$lastTag = $compiler->_tag_stack[ $stack_count ][ 0 ]; $lastTag = $compiler->_tag_stack[ $stack_count ][ 0 ];
if ($level_count === 0) { if ($level_count === 0) {
@@ -100,9 +109,9 @@ class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase
$stack_count --; $stack_count --;
} }
if ($level_count !== 0) { if ($level_count !== 0) {
$compiler->trigger_template_error("cannot {$tag} {$levels} level(s)", null, true); $compiler->trigger_template_error("cannot {$this->tag} {$levels} level(s)", null, true);
} }
if ($lastTag === 'foreach' && $tag === 'break') { if ($lastTag === 'foreach' && $this->tag === 'break' && $foreachLevels > 0) {
$foreachLevels --; $foreachLevels --;
} }
return array($levels, $foreachLevels); return array($levels, $foreachLevels);

View File

@@ -17,25 +17,9 @@
class Smarty_Internal_Compile_Continue extends Smarty_Internal_Compile_Break class Smarty_Internal_Compile_Continue extends Smarty_Internal_Compile_Break
{ {
/** /**
* Compiles code for the {continue} tag * Tag name
* *
* @param array $args array with attributes from parser * @var string
* @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object
*
* @return string compiled code
* @throws \SmartyCompilerException
* @internal param array $parameter array with compilation parameter
*/ */
public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) public $tag = 'continue';
{
list($levels, $foreachLevels) = $this->checkLevels($args, $compiler, 'continue');
$output = "<?php\n";
if ($foreachLevels > 1) {
/* @var Smarty_Internal_Compile_Foreach $foreachCompiler */
$foreachCompiler = $compiler->getTagCompiler('foreach');
$output .= $foreachCompiler->compileRestore($foreachLevels - 1);
}
$output .= "continue {$levels};?>";
return $output;
}
} }