mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-03 09:54:27 +02:00
Fixed all scope assignment bugs
This commit is contained in:
@@ -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)
|
||||||
|
@@ -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];
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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;
|
||||||
|
@@ -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++,],
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user