Skip to content

Commit

Permalink
- improvement rework of 'scope' attribute handling see see NEW_FEATUR…
Browse files Browse the repository at this point in the history
…ES.txt #194

    #186 #179
  • Loading branch information
uwetews committed Mar 9, 2016
1 parent d88168d commit abf5be5
Show file tree
Hide file tree
Showing 9 changed files with 93 additions and 71 deletions.
51 changes: 21 additions & 30 deletions NEW_FEATURES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,54 +50,45 @@ Smarty 3.1.30
Scope Attributes
================
The scope handling has been updated to cover all cases of variable assignments in templates.
A new option flag 'bubble_up' is introduced.


The tags {assign}, {append} direct assignments like {$foo = ...}, {$foo[...]= ...} support
the following optional scope attributes:
scope='parent' - the variable will be assigned in the current template and if the template
was included by {include} the calling template
scope='tpl_root' - the variable will be assigned in the current template and if the template
was included by {include} the outermost root template
scope='smarty' - the variable will be assigned in the current template and the Smarty object
scope='global' - the variable will be assigned in the current template and as Smarty object
global variable
scope='root' - the variable will be assigned in the current template and if a data object was
used for variable definitions in the data object or in the Smarty object otherwise
scope='tpl_root' - the variable will be assigned in the outermost root template called by $smarty->display()
or $smarty->fetch() and is bubbled up all {include} sub-templates to the current template.
scope='smarty' - the variable will be assigned in the Smarty object and is bubbled up all {include} sub-templates
to the current template.
scope='global' - the variable will be assigned as Smarty object global variable and is bubbled up all {include}
sub-templates to the current template.
scope='root' - the variable will be assigned if a data object was used for variable definitions in the data
object or in the Smarty object otherwise and is bubbled up all {include} sub-templates to the
current template.
scope='local' - this scope has only a meaning if the tag is called within a template {function}.
The variable will be assigned in the local scope of the template function and the
template which did call the template function.

The scope attribute can be combined with the new option flag 'bubble_up' like
{$foo = 'bar' scope='global' bubble_up}
In addition to the assignments according to the scope attributes tpl_root, smarty, global, root the varibale
will also be assigned in all templates in the call chain from template root to the current template,
including all local template function scopes of nested template function calls.
In combination with scope local it does update the nested template function scopes.

Example:
$smarty->display('main.tpl');

main.tpl:
{include 'sub.tpl'}

sub.tpl:
{$foo = 'bar' scope='global' bubble_up}

Will assign the variable 'foo' with value 'bar' as Smarty global variable, in 'sub.tpl' and in
'main.tpl' because the 'bubble_up' option.


The {config_load} tag supports all of the above except the global scope.

The scope attribute and bubble_up option flag can be used also with the {include} tag.
The scope attribute can be used also with the {include} tag.
Supported scope are parent, tpl_root, smarty, global and root.
A scope used together with the {include} tag will cause that with some exceptions any variable
assignment within that sub-template will update/assign the variable in other scopes according
to the above rules. It does include also variables assigned by plugins, tags supporting the assign=foo
attribute and direct assignments in {if} and {while} like {if $foo=$bar}.
Excluded are the key and value variables of {foreach}, {for} loop variables , variables passed by attributes
in {include} and direct increments/decrements like {$foo++}, {$foo--}


Note: The scopes should be used only to the extend really need. If a variable value assigned in an included
sub-template should be returned to the calling sub-template just use {$foo='bar' scope='parent'}.
Use scopes only with variables for which it's realy needed. Avoid general scope settings with the
{include} tag as it can have a performance impact.

The {assign}, {append}, {config_load} and {$foo...=...} tags have a new option flag 'noscope'.Thi
Example: {$foo='bar' noscope} This will assign $foo only in the current template and any scope settings
at {include} is ignored.


Caching
=======
Expand Down
4 changes: 4 additions & 0 deletions change_log.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
 ===== 3.1.30-dev ===== (xx.xx.xx)
09.03.2014
- improvement rework of 'scope' attribute handling see see NEW_FEATURES.txt https://github.com/smarty-php/smarty/issues/194
https://github.com/smarty-php/smarty/issues/186 https://github.com/smarty-php/smarty/issues/179

04.03.2016
- bugfix change from 01.03.2016 will cause $smarty->isCached(..) failure if called multiple time for same template
(forum topic 25935)
Expand Down
4 changes: 1 addition & 3 deletions libs/Smarty.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '3.1.30-dev/52';
const SMARTY_VERSION = '3.1.30-dev/53';

/**
* define variable scopes
Expand All @@ -138,8 +138,6 @@ class Smarty extends Smarty_Internal_TemplateBase

const SCOPE_GLOBAL = 32;

const SCOPE_BUBBLE_UP = 64;

/**
* define caching modes
*/
Expand Down
10 changes: 7 additions & 3 deletions libs/sysplugins/smarty_internal_compile_assign.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array('nocache', 'bubble_up');
public $option_flags = array('nocache', 'noscope');

/**
/**
* Valid scope names
*
* @var array
Expand Down Expand Up @@ -65,7 +65,11 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $
$compiler->setNocacheInVariable($_attr[ 'var' ]);
}
// scope setup
$_scope = $compiler->convertScope($_attr, $this->valid_scopes);
if ($_attr[ 'noscope' ]) {
$_scope = - 1;
} else {
$_scope = $compiler->convertScope($_attr, $this->valid_scopes);
}
// optional parameter
$_params = "";
if ($_nocache || $_scope) {
Expand Down
8 changes: 6 additions & 2 deletions libs/sysplugins/smarty_internal_compile_config_load.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class Smarty_Internal_Compile_Config_Load extends Smarty_Internal_CompileBase
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array('nocache', 'bubble_up');
public $option_flags = array('nocache', 'noscope');

/**
* Valid scope names
Expand Down Expand Up @@ -83,7 +83,11 @@ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler)
$section = 'null';
}
// scope setup
$_scope = $compiler->convertScope($_attr, $this->valid_scopes);
if ($_attr[ 'noscope' ]) {
$_scope = - 1;
} else {
$_scope = $compiler->convertScope($_attr, $this->valid_scopes);
}

// create config object
$_output =
Expand Down
4 changes: 2 additions & 2 deletions libs/sysplugins/smarty_internal_compile_include.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
* @var array
* @see Smarty_Internal_CompileBase
*/
public $option_flags = array('nocache', 'inline', 'caching', 'bubble_up');
public $option_flags = array('nocache', 'inline', 'caching');

/**
* Attribute definition: Overwrites base class.
Expand Down Expand Up @@ -214,7 +214,7 @@ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler,
}
}
// delete {include} standard attributes
unset($_attr[ 'file' ], $_attr[ 'assign' ], $_attr[ 'cache_id' ], $_attr[ 'compile_id' ], $_attr[ 'cache_lifetime' ], $_attr[ 'nocache' ], $_attr[ 'caching' ], $_attr[ 'scope' ], $_attr[ 'inline' ], $_attr[ 'bubble_up' ]);
unset($_attr[ 'file' ], $_attr[ 'assign' ], $_attr[ 'cache_id' ], $_attr[ 'compile_id' ], $_attr[ 'cache_lifetime' ], $_attr[ 'nocache' ], $_attr[ 'caching' ], $_attr[ 'scope' ], $_attr[ 'inline' ]);
// remaining attributes must be assigned as smarty variable
$_vars_nc = '';
$_vars = 'array()';
Expand Down
73 changes: 48 additions & 25 deletions libs/sysplugins/smarty_internal_method_configload.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,31 @@ public function _loadConfigFile(Smarty_Internal_Data $data, $config_file, $secti
* load config variables into template object
*
* @param \Smarty_Internal_Template $tpl
* @param array $_config_vars
* @param array $new_config_vars
*
*/
public function _loadConfigVars(Smarty_Internal_Template $tpl, $_config_vars)
public function _loadConfigVars(Smarty_Internal_Template $tpl, $new_config_vars)
{
$this->_assignConfigVars($tpl->parent, $tpl, $_config_vars);
if ($tpl->parent->_objType == 2 && ($tpl->source->scope || $tpl->parent->scope)) {
$scope = $tpl->source->scope | $tpl->scope;
if ($scope) {
// update scopes
foreach ($tpl->smarty->ext->_updateScope->_getAffectedScopes($tpl->parent, $scope) as $ptr) {
$this->_assignConfigVars($ptr, $tpl, $_config_vars);
$this->_assignConfigVars($tpl->parent->config_vars, $tpl, $new_config_vars);
$tagScope = $tpl->source->scope;
if ($tagScope >= 0) {
if ($tagScope == Smarty::SCOPE_LOCAL) {
$this->_updateVarStack($tpl, $new_config_vars);
$tagScope = 0;
if (!$tpl->scope) {
return;
}
if ($scope & Smarty::SCOPE_LOCAL) {
//$this->_updateVarStack($tpl, $varName);
}
if ($tpl->parent->_objType == 2 && ($tagScope || $tpl->parent->scope)) {
$mergedScope = $tagScope | $tpl->scope;
if ($mergedScope) {
// update scopes
foreach ($tpl->smarty->ext->_updateScope->_getAffectedScopes($tpl->parent, $mergedScope) as $ptr) {
$this->_assignConfigVars($ptr->config_vars, $tpl, $new_config_vars);
if ($tagScope && $ptr->_objType == 2 && isset($tpl->_cache[ 'varStack' ])) {
$this->_updateVarStack($tpl, $new_config_vars);
}
}
}
}
}
Expand All @@ -99,39 +109,52 @@ public function _loadConfigVars(Smarty_Internal_Template $tpl, $_config_vars)
/**
* Assign all config variables in given scope
*
* @param \Smarty_Internal_Data $scope_ptr
* @param array $config_vars config variables in scope
* @param \Smarty_Internal_Template $tpl
* @param array $_config_vars
* @param array $new_config_vars loaded config variables
*/
public function _assignConfigVars(Smarty_Internal_Data $scope_ptr, Smarty_Internal_Template $tpl, $_config_vars)
public function _assignConfigVars(&$config_vars, Smarty_Internal_Template $tpl, $new_config_vars)
{
// copy global config vars
foreach ($_config_vars[ 'vars' ] as $variable => $value) {
if ($tpl->smarty->config_overwrite || !isset($scope_ptr->config_vars[ $variable ])) {
$scope_ptr->config_vars[ $variable ] = $value;
foreach ($new_config_vars[ 'vars' ] as $variable => $value) {
if ($tpl->smarty->config_overwrite || !isset($config_vars[ $variable ])) {
$config_vars[ $variable ] = $value;
} else {
$scope_ptr->config_vars[ $variable ] =
array_merge((array) $scope_ptr->config_vars[ $variable ], (array) $value);
$config_vars[ $variable ] = array_merge((array) $config_vars[ $variable ], (array) $value);
}
}
// scan sections
$sections = $tpl->source->config_sections;
if (!empty($sections)) {
foreach ((array) $sections as $tpl_section) {
if (isset($_config_vars[ 'sections' ][ $tpl_section ])) {
foreach ($_config_vars[ 'sections' ][ $tpl_section ][ 'vars' ] as $variable => $value) {
if ($tpl->smarty->config_overwrite || !isset($scope_ptr->config_vars[ $variable ])) {
$scope_ptr->config_vars[ $variable ] = $value;
if (isset($new_config_vars[ 'sections' ][ $tpl_section ])) {
foreach ($new_config_vars[ 'sections' ][ $tpl_section ][ 'vars' ] as $variable => $value) {
if ($tpl->smarty->config_overwrite || !isset($config_vars[ $variable ])) {
$config_vars[ $variable ] = $value;
} else {
$scope_ptr->config_vars[ $variable ] =
array_merge((array) $scope_ptr->config_vars[ $variable ], (array) $value);
$config_vars[ $variable ] = array_merge((array) $config_vars[ $variable ], (array) $value);
}
}
}
}
}
}

/**
* Update config variables in template local variable stack
*
* @param \Smarty_Internal_Template $tpl
* @param array $config_vars
*/
public function _updateVarStack(Smarty_Internal_Template $tpl, $config_vars)
{
$i = 0;
while (isset($tpl->_cache[ 'varStack' ][ $i ])) {
$this->_assignConfigVars($tpl->_cache[ 'varStack' ][ $i ][ 'config' ], $tpl, $config_vars);
$i ++;
}
}

/**
* gets a config variable value
*
Expand Down
6 changes: 4 additions & 2 deletions libs/sysplugins/smarty_internal_template.php
Original file line number Diff line number Diff line change
Expand Up @@ -383,8 +383,10 @@ public function _assignInScope($varName, $value, $nocache = false, $scope = 0)
} else {
$this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache || $this->isRenderingCache);
}
if (isset($scope) || isset($this->scope)) {
$this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope);
if ($scope >= 0) {
if (isset($scope) || isset($this->scope)) {
$this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope);
}
}
}

Expand Down
4 changes: 0 additions & 4 deletions libs/sysplugins/smarty_internal_templatecompilerbase.php
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,6 @@ public function compileTemplateSource(Smarty_Internal_Template $template, $nocac
$this->smarty->_debug->end_compile($this->template);
}
$this->_tag_stack = array();
self::$_tag_objects = array();
// free memory
$this->parent_compiler = null;
$this->template = null;
Expand Down Expand Up @@ -1140,9 +1139,6 @@ public function convertScope($_attr, $validScopes)
$err = var_export($_scopeName, true);
$this->trigger_template_error("illegal value '{$err}' for \"scope\" attribute", null, true);
}
if (isset($_attr[ 'bubble_up' ]) && $_attr[ 'bubble_up' ] && $_scope > 2) {
$_scope += Smarty::SCOPE_BUBBLE_UP;
}
}
return $_scope;
}
Expand Down

0 comments on commit abf5be5

Please sign in to comment.