Fixed all scope assignment bugs

This commit is contained in:
Simon Wisselink
2023-01-24 10:16:00 +01:00
parent c5f555eed4
commit 431d77505f
6 changed files with 17 additions and 43 deletions

View File

@@ -6,12 +6,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Changed
- Template variable scope bubbling has been simplified and made more consistent
### Removed ### Removed
- Removed support for $cache_attrs for registered plugins - Removed support for $cache_attrs for registered plugins
- Removed support for undocumented {make_nocache} tag - Removed support for undocumented {make_nocache} tag
- Removed support for deprecated {insert} tag, the 'insert' plugin type and the associated $smarty->trusted_dir variable - Removed support for deprecated {insert} tag, the 'insert' plugin type and the associated $smarty->trusted_dir variable
- Removed the undocumented {block_parent} and {parent} alternatives to {$smarty.block.parent} - Removed the undocumented {block_parent} and {parent} alternatives to {$smarty.block.parent}
- Removed the undocumented {block_child} and {child} alternatives to {$smarty.block.child} - Removed the undocumented {block_child} and {child} alternatives to {$smarty.block.child}
- Removed support for loading config files into a non-local scope using {config_load} from a template
### Fixed ### Fixed
- `$smarty->muteUndefinedOrNullWarnings()` now also mutes PHP7 notices for undefined array indexes [#736](https://github.com/smarty-php/smarty/issues/736) - `$smarty->muteUndefinedOrNullWarnings()` now also mutes PHP7 notices for undefined array indexes [#736](https://github.com/smarty-php/smarty/issues/736)

View File

@@ -194,7 +194,7 @@ abstract class Base implements CompilerInterface {
* @return int * @return int
* @throws Exception * @throws Exception
*/ */
protected function convertScope($scope, $invalidScopes = []): int { protected function convertScope($scope): int {
static $scopes = [ static $scopes = [
'local' => Data::SCOPE_LOCAL, // current scope 'local' => Data::SCOPE_LOCAL, // current scope
@@ -211,7 +211,6 @@ abstract class Base implements CompilerInterface {
return (int) $_scopeName; return (int) $_scopeName;
} }
$_scopeName = trim($_scopeName, '\'"');
if (isset($scopes[$_scopeName])) { if (isset($scopes[$_scopeName])) {
return $scopes[$_scopeName]; return $scopes[$_scopeName];
} }

View File

@@ -78,11 +78,6 @@ class Assign extends Base
} else { } else {
$_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope']) : null; $_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope']) : null;
} }
// optional parameter
$_params = '';
if ($_nocache) {
$_params .= ' ,' . var_export($_nocache, true);
}
if (isset($parameter[ 'smarty_internal_index' ])) { if (isset($parameter[ 'smarty_internal_index' ])) {
$output = $output =
@@ -91,9 +86,9 @@ class Assign extends Base
$output .= "settype(\$_tmp_array, 'array');\n"; $output .= "settype(\$_tmp_array, 'array');\n";
$output .= "}\n"; $output .= "}\n";
$output .= "\$_tmp_array{$parameter['smarty_internal_index']} = {$_attr['value']};\n"; $output .= "\$_tmp_array{$parameter['smarty_internal_index']} = {$_attr['value']};\n";
$output .= "\$_smarty_tpl->assign({$_var}, \$_tmp_array{$_params}, false, " . var_export($_scope, true) . ");?>"; $output .= "\$_smarty_tpl->assign({$_var}, \$_tmp_array, " . var_export($_nocache, true) . ", " . var_export($_scope, true) . ");?>";
} else { } else {
$output = "<?php \$_smarty_tpl->assign({$_var}, {$_attr['value']}{$_params}, false, " . var_export($_scope, true) . ");?>"; $output = "<?php \$_smarty_tpl->assign({$_var}, {$_attr['value']}, " . var_export($_nocache, true) . ", " . var_export($_scope, true) . ");?>";
} }
return $output; return $output;
} }

View File

@@ -107,7 +107,7 @@ class IncludeTag extends Base {
$variable_template = true; $variable_template = true;
} }
// scope setup // scope setup
$_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope'], [Data::SCOPE_LOCAL]) : 0; $_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope']) : 0;
// assume caching is off // assume caching is off
$_caching = Smarty::CACHING_OFF; $_caching = Smarty::CACHING_OFF;

View File

@@ -130,7 +130,7 @@ class ScopeTest extends PHPUnit_Smarty
} }
/* /*
* Data provider für testAssignScope * Data provider for testAssignScope
*/ */
public function dataTestAssignScope() public function dataTestAssignScope()
{ {
@@ -216,9 +216,6 @@ class ScopeTest extends PHPUnit_Smarty
/** /**
* Test scope * Test scope
*
*
*
* @dataProvider dataTestIncludeScope * @dataProvider dataTestIncludeScope
*/ */
public function testIncludeScope($code, $useSmarty, $result, $testName, $testNumber = null) public function testIncludeScope($code, $useSmarty, $result, $testName, $testNumber = null)
@@ -267,12 +264,12 @@ class ScopeTest extends PHPUnit_Smarty
'.tpl:$foo =\'newvar\'#test_scope.tpl:$foo =\'newvar\'#data:$foo =\'newvar\'#global:$foo =\'global\'', '.tpl:$foo =\'newvar\'#test_scope.tpl:$foo =\'newvar\'#data:$foo =\'newvar\'#global:$foo =\'global\'',
'root scope / no smarty', $i++], 'root scope / no smarty', $i++],
['{include \'test_scope_assign.tpl\' scope=global}', true, ['{include \'test_scope_assign.tpl\' scope=global}', true,
'#test_scope_assign.tpl:$foo =\'newvar\'#testIncludeScope_' . $i . '#test_scope_assign.tpl:$foo =\'data\'#testIncludeScope_' . $i .
'.tpl:$foo =\'newvar\'#test_scope.tpl:$foo =\'newvar\'#data:$foo =\'data\'#global:$foo =\'global\'', '.tpl:$foo =\'data\'#test_scope.tpl:$foo =\'data\'#data:$foo =\'data\'#global:$foo =\'newvar\'',
'global scope', $i++], 'global scope', $i++],
['{include \'test_scope_pluginassign.tpl\' scope=global}', true, ['{include \'test_scope_pluginassign.tpl\' scope=global}', true,
'#test_scope_pluginassign.tpl:$foo =\'newvar\'#testIncludeScope_' . $i . '#test_scope_pluginassign.tpl:$foo =\'data\'#testIncludeScope_' . $i .
'.tpl:$foo =\'newvar\'#test_scope.tpl:$foo =\'newvar\'#data:$foo =\'data\'#global:$foo =\'newvar\'', '.tpl:$foo =\'data\'#test_scope.tpl:$foo =\'data\'#data:$foo =\'data\'#global:$foo =\'newvar\'',
'pluginassign global', $i++], 'pluginassign global', $i++],
['{include \'test_scope_assign_noscope.tpl\' scope=root}', true, ['{include \'test_scope_assign_noscope.tpl\' scope=root}', true,
'#test_scope_assign_noscope.tpl:$foo =\'newvar\'#testIncludeScope_' . $i . '#test_scope_assign_noscope.tpl:$foo =\'newvar\'#testIncludeScope_' . $i .
@@ -283,9 +280,6 @@ class ScopeTest extends PHPUnit_Smarty
/** /**
* Test scope * Test scope
*
* @not runInSeparateProcess
*
* @dataProvider dataTestConfigScope * @dataProvider dataTestConfigScope
*/ */
public function testConfigScope($code, $useSmarty, $result, $testName, $testNumber) public function testConfigScope($code, $useSmarty, $result, $testName, $testNumber)
@@ -294,7 +288,7 @@ class ScopeTest extends PHPUnit_Smarty
$this->makeTemplateFile($file, $code . '{checkconfigvar var=foo}'); $this->makeTemplateFile($file, $code . '{checkconfigvar var=foo}');
$this->smarty->configLoad('smarty.conf'); $this->smarty->configLoad('smarty.conf');
$data = $this->smarty->createData($useSmarty ? $this->smarty : null); $data = $this->smarty->createData($useSmarty ? $this->smarty : null);
$this->smarty->assign('file', $file); $data->assign('file', $file);
$data->configLoad('data.conf'); $data->configLoad('data.conf');
$tpl = $this->smarty->createTemplate('scope_tag.tpl', $data); $tpl = $this->smarty->createTemplate('scope_tag.tpl', $data);
$this->assertEquals( $this->assertEquals(
@@ -305,7 +299,7 @@ class ScopeTest extends PHPUnit_Smarty
} }
/* /*
* Data provider für testConfigScope * Data provider for testConfigScope
*/ */
public function dataTestConfigScope() public function dataTestConfigScope()
{ {
@@ -318,26 +312,8 @@ class ScopeTest extends PHPUnit_Smarty
*/ */
return [ return [
['{config_load \'template.conf\'}', true, ['{config_load \'template.conf\'}', true,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'data\'#scope_tag.tpl:$foo =\'data\'#data:$foo =\'data\'', ':$foo =\'newvar\'#scope_include.tpl:$foo =\'data\'#scope_tag.tpl:$foo =\'data\'#data:$foo =\'data\'#global:$foo =\'smarty\'',
'', $i++,], '', $i++,],
['{config_load \'template.conf\' scope=local}', true,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'data\'#scope_tag.tpl:$foo =\'data\'#data:$foo =\'data\'',
'', $i++,],
['{config_load \'template.conf\' scope=parent}', true,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'newvar\'#scope_tag.tpl:$foo =\'data\'#data:$foo =\'data\'',
'', $i++,],
['{config_load \'template.conf\' scope=tpl_root}', true,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'newvar\'#scope_tag.tpl:$foo =\'newvar\'#data:$foo =\'data\'',
'', $i++,],
['{config_load \'template.conf\' scope=root}', true,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'newvar\'#scope_tag.tpl:$foo =\'newvar\'#data:$foo =\'newvar\'',
'', $i++,],
['{config_load \'template.conf\' scope=root}', false,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'newvar\'#scope_tag.tpl:$foo =\'newvar\'#data:$foo =\'newvar\'',
'no smarty', $i++,],
['{config_load \'template.conf\' scope=global}', false,
':$foo =\'newvar\'#scope_include.tpl:$foo =\'newvar\'#scope_tag.tpl:$foo =\'newvar\'#data:$foo =\'data\'#global:$foo =\'newvar\'',
'no smarty', $i++,],
]; ];
} }

View File

@@ -30,7 +30,7 @@ function smarty_function_checkconfigvar($params, $template)
$output .= "#{$ptr->getSource()->name}:\${$var} ="; $output .= "#{$ptr->getSource()->name}:\${$var} =";
$output .= $ptr->hasConfigVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getConfigVariable($var), true)) : 'null'; $output .= $ptr->hasConfigVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getConfigVariable($var), true)) : 'null';
$ptr = $ptr->parent; $ptr = $ptr->parent;
} elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof Smarty)) { } elseif (in_array('data', $types) && !($ptr instanceof Template || $ptr instanceof \Smarty\Smarty)) {
$output .= "#data:\${$var} ="; $output .= "#data:\${$var} =";
$output .= $ptr->hasConfigVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getConfigVariable($var), true)) : 'null'; $output .= $ptr->hasConfigVariable($var) ? preg_replace('/\s/', '', var_export($ptr->getConfigVariable($var), true)) : 'null';
$ptr = $ptr->parent; $ptr = $ptr->parent;