- bugfix {foreach} using new style property access like {$item@property} on

Smarty 2 style named foreach loop could produce errors https://github.com/smarty-php/smarty/issues/484
This commit is contained in:
uwetews
2018-09-03 01:18:26 +02:00
parent 2c60503dfc
commit 2d1905cd88
4 changed files with 42 additions and 39 deletions

View File

@@ -1,4 +1,8 @@
===== 3.1.33-dev-10 ===== ===== 3.1.33-dev-12 =====
03.09.2018
- bugfix {foreach} using new style property access like {$item@property} on
Smarty 2 style named foreach loop could produce errors https://github.com/smarty-php/smarty/issues/484
31.08.2018 31.08.2018
- bugfix some custom left and right delimiters like '{^' '^}' did not work - bugfix some custom left and right delimiters like '{^' '^}' did not work
https://github.com/smarty-php/smarty/issues/450 https://github.com/smarty-php/smarty/pull/482 https://github.com/smarty-php/smarty/issues/450 https://github.com/smarty-php/smarty/pull/482

View File

@@ -112,7 +112,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/** /**
* smarty version * smarty version
*/ */
const SMARTY_VERSION = '3.1.33-dev-11'; const SMARTY_VERSION = '3.1.33-dev-12';
/** /**
* define variable scopes * define variable scopes
*/ */

View File

@@ -325,8 +325,9 @@ class Smarty_Internal_Compile_Foreachclose extends Smarty_Internal_CompileBase
if ($compiler->nocache) { if ($compiler->nocache) {
$compiler->tag_nocache = true; $compiler->tag_nocache = true;
} }
list($openTag, $compiler->nocache, $local, $itemVar, $restore) = list(
$this->closeTag($compiler, array('foreach', 'foreachelse')); $openTag, $compiler->nocache, $local, $itemVar, $restore
) = $this->closeTag($compiler, array('foreach', 'foreachelse'));
$output = "<?php\n"; $output = "<?php\n";
if ($restore === 2) { if ($restore === 2) {
$output .= "{$itemVar} = {$local}saved;\n"; $output .= "{$itemVar} = {$local}saved;\n";

View File

@@ -16,27 +16,6 @@
*/ */
class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_CompileBase class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_CompileBase
{ {
/**
* Preg search pattern
*
* @var string
*/
private $propertyPreg = '';
/**
* Offsets in preg match result
*
* @var array
*/
private $resultOffsets = array();
/**
* Start offset
*
* @var int
*/
private $startOffset = 0;
/** /**
* Name of this tag * Name of this tag
* *
@@ -70,6 +49,27 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com
*/ */
public $matchResults = array(); public $matchResults = array();
/**
* Preg search pattern
*
* @var string
*/
private $propertyPreg = '';
/**
* Offsets in preg match result
*
* @var array
*/
private $resultOffsets = array();
/**
* Start offset
*
* @var int
*/
private $startOffset = 0;
/** /**
* Scan sources for used tag attributes * Scan sources for used tag attributes
* *
@@ -81,10 +81,10 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com
public function scanForProperties($attributes, Smarty_Internal_TemplateCompilerBase $compiler) public function scanForProperties($attributes, Smarty_Internal_TemplateCompilerBase $compiler)
{ {
$this->propertyPreg = '~('; $this->propertyPreg = '~(';
$this->startOffset = 0; $this->startOffset = 1;
$this->resultOffsets = array(); $this->resultOffsets = array();
$this->matchResults = array('named' => array(), 'item' => array()); $this->matchResults = array('named' => array(), 'item' => array());
if ($this->isNamed) { if (isset($attributes[ 'name' ])) {
$this->buildPropertyPreg(true, $attributes); $this->buildPropertyPreg(true, $attributes);
} }
if (isset($this->itemProperties)) { if (isset($this->itemProperties)) {
@@ -111,21 +111,19 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com
public function buildPropertyPreg($named, $attributes) public function buildPropertyPreg($named, $attributes)
{ {
if ($named) { if ($named) {
$this->resultOffsets[ 'named' ] = $this->startOffset + 4; $this->resultOffsets[ 'named' ] = $this->startOffset = $this->startOffset + 3;
$this->propertyPreg .= "(([\$]smarty[.]{$this->tagName}[.]" . $this->propertyPreg .= "(([\$]smarty[.]{$this->tagName}[.]" .
($this->tagName === 'section' ? "|[\[]\s*" : '') ($this->tagName === 'section' ? "|[\[]\s*" : '') .
.
"){$attributes['name']}[.]("; "){$attributes['name']}[.](";
$properties = $this->nameProperties; $properties = $this->nameProperties;
} else { } else {
$this->resultOffsets[ 'item' ] = $this->startOffset + 3; $this->resultOffsets[ 'item' ] = $this->startOffset = $this->startOffset + 2;
$this->propertyPreg .= "([\$]{$attributes['item']}[@]("; $this->propertyPreg .= "([\$]{$attributes['item']}[@](";
$properties = $this->itemProperties; $properties = $this->itemProperties;
} }
$this->startOffset += count($properties) + 2;
$propName = reset($properties); $propName = reset($properties);
while ($propName) { while ($propName) {
$this->propertyPreg .= "({$propName})"; $this->propertyPreg .= "{$propName}";
$propName = next($properties); $propName = next($properties);
if ($propName) { if ($propName) {
$this->propertyPreg .= '|'; $this->propertyPreg .= '|';
@@ -141,11 +139,11 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com
*/ */
public function matchProperty($source) public function matchProperty($source)
{ {
preg_match_all($this->propertyPreg, $source, $match, PREG_SET_ORDER); preg_match_all($this->propertyPreg, $source, $match);
foreach ($this->resultOffsets as $key => $offset) { foreach ($this->resultOffsets as $key => $offset) {
foreach ($match as $m) { foreach ($match[ $offset ] as $m) {
if (isset($m[ $offset ]) && !empty($m[ $offset ])) { if (!empty($m)) {
$this->matchResults[ $key ][ strtolower($m[ $offset ]) ] = true; $this->matchResults[ $key ][ strtolower($m) ] = true;
} }
} }
} }
@@ -179,8 +177,8 @@ class Smarty_Internal_Compile_Private_ForeachSection extends Smarty_Internal_Com
$_content = $nextCompiler->template->source->getContent(); $_content = $nextCompiler->template->source->getContent();
if ($_content !== '') { if ($_content !== '') {
// run pre filter if required // run pre filter if required
if ((isset($nextCompiler->smarty->autoload_filters[ 'pre' ]) if ((isset($nextCompiler->smarty->autoload_filters[ 'pre' ]) ||
|| isset($nextCompiler->smarty->registered_filters[ 'pre' ])) isset($nextCompiler->smarty->registered_filters[ 'pre' ]))
) { ) {
$_content = $nextCompiler->smarty->ext->_filterHandler->runFilter( $_content = $nextCompiler->smarty->ext->_filterHandler->runFilter(
'pre', 'pre',