Skip to content

Commit

Permalink
Bubbling up of parent scope in template blocks with inheritance chain
Browse files Browse the repository at this point in the history
  • Loading branch information
maryo committed Jan 23, 2023
1 parent a34ee98 commit 0940874
Show file tree
Hide file tree
Showing 10 changed files with 36 additions and 7 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Fixed
- Updating variable in parent scope (when the `scope=parent` is explicitly used on a tag like `assign`) now bubbles up (to the including template) even when the included template is part of an inheritance chain as it did pre `v3.1.28`.
- `$smarty->muteUndefinedOrNullWarnings()` now also mutes PHP7 notices for undefined array indexes [#736](https://github.com/smarty-php/smarty/issues/736)
- `$smarty->muteUndefinedOrNullWarnings()` now treats undefined vars and array access of a null or false variables
equivalent across all supported PHP versions
- `$smarty->muteUndefinedOrNullWarnings()` now allows dereferencing of non-objects accross all supported PHP versions [#831](https://github.com/smarty-php/smarty/issues/831)

## [4.3.0] - 2022-11-22

### Added
Expand Down
5 changes: 2 additions & 3 deletions libs/sysplugins/smarty_internal_method_configload.php
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,10 @@ public function _loadConfigVars(Smarty_Internal_Template $tpl, $new_config_vars)
}
}
if ($tpl->parent->_isTplObj() && ($tagScope || $tpl->parent->scope)) {
$mergedScope = $tagScope | $tpl->scope;
if ($mergedScope) {
if ($tagScope | $tpl->scope) {
// update scopes
/* @var \Smarty_Internal_Template|\Smarty|\Smarty_Internal_Data $ptr */
foreach ($tpl->smarty->ext->_updateScope->_getAffectedScopes($tpl->parent, $mergedScope) as $ptr) {
foreach ($tpl->smarty->ext->_updateScope->_getAffectedScopes($tpl->parent, $tagScope) as $ptr) {
$this->_assignConfigVars($ptr->config_vars, $tpl, $new_config_vars);
if ($tagScope && $ptr->_isTplObj() && isset($tpl->_cache[ 'varStack' ])) {
$this->_updateVarStack($tpl, $new_config_vars);
Expand Down
19 changes: 16 additions & 3 deletions libs/sysplugins/smarty_internal_runtime_updatescope.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function _updateScope(Smarty_Internal_Template $tpl, $varName, $tagScope
Smarty::$global_tpl_vars[ $varName ] = $tpl->tpl_vars[ $varName ];
}
// update scopes
foreach ($this->_getAffectedScopes($tpl, $mergedScope) as $ptr) {
foreach ($this->_getAffectedScopes($tpl, $tagScope) as $ptr) {
$this->_updateVariableInOtherScope($ptr->tpl_vars, $tpl, $varName);
if ($tagScope && $ptr->_isTplObj() && isset($tpl->_cache[ 'varStack' ])) {
$this->_updateVarStack($ptr, $varName);
Expand All @@ -44,16 +44,29 @@ public function _updateScope(Smarty_Internal_Template $tpl, $varName, $tagScope
* Get array of objects which needs to be updated by given scope value
*
* @param Smarty_Internal_Template $tpl
* @param int $mergedScope merged tag and template scope to which bubble up variable value
* @param int $tagScope tag scope to which bubble up variable value
*
* @return array
*/
public function _getAffectedScopes(Smarty_Internal_Template $tpl, $mergedScope)
public function _getAffectedScopes(Smarty_Internal_Template $tpl, $tagScope)
{
$mergedScope = $tagScope | $tpl->scope;
$_stack = array();
$ptr = $tpl->parent;
if ($mergedScope && isset($ptr) && $ptr->_isTplObj()) {
$_stack[] = $ptr;
if ($tpl->inheritance && $tagScope & Smarty::SCOPE_PARENT) {
$inheritanceRoot = $tpl;
while ($inheritanceRoot->inheritance && $inheritanceRoot->parent
&& $inheritanceRoot->parent->inheritance === $inheritanceRoot->inheritance
&& $inheritanceRoot->parent->_isTplObj()
) {
$inheritanceRoot = $inheritanceRoot->parent;
}
if ($inheritanceRoot->parent && $inheritanceRoot->parent !== $ptr) {
$_stack[] = $inheritanceRoot->parent;
}
}
$mergedScope = $mergedScope & ~Smarty::SCOPE_PARENT;
if (!$mergedScope) {
// only parent was set, we are done
Expand Down
11 changes: 10 additions & 1 deletion tests/UnitTests/TemplateSource/X_Scopes/ScopeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,16 @@ public function dataTestIncludeScope()
'', $i ++), array('{include \'test_scope_assign_noscope.tpl\' scope=root}', true,
'#test_scope_assign_noscope.tpl:$foo =\'newvar\'#testIncludeScope_' . $i .
'.tpl:$foo =\'data\'#test_scope.tpl:$foo =\'data\'#data:$foo =\'data\'#Smarty:$foo =\'smarty\'#global:$foo =\'global\'',
'', $i ++),);
'', $i ++),
array('{include \'test_scope_inheritance_include.tpl\'}', true,
'#test_scope_inheritance_include.tpl:$foo =\'data\'#testIncludeScope_'. $i .
'.tpl:$foo =\'data\'#test_scope.tpl:$foo =\'data\'#data:$foo =\'data\'#Smarty:$foo =\'smarty\'#global:$foo =\'global\'',
'', $i ++),
array('{include \'test_scope_inheritance_include_assign_parent.tpl\'}', true,
'#test_scope_inheritance_include_assign_parent.tpl:$foo =\'parent\'#testIncludeScope_'. $i .
'.tpl:$foo =\'data\'#test_scope.tpl:$foo =\'data\'#data:$foo =\'data\'#Smarty:$foo =\'smarty\'#global:$foo =\'global\'',
'', $i ++)
);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{extends './test_scope_inheritance_parent.tpl'}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{extends './test_scope_inheritance_parent_assign_parent.tpl'}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{include './test_scope_inheritance_child.tpl'}{checkvar var=foo}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{include './test_scope_inheritance_child_assign_parent.tpl'}{checkvar var=foo}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{$foo = 'parent'}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{$foo = 'parent' scope=parent}

0 comments on commit 0940874

Please sign in to comment.