- improve template scope handling

This commit is contained in:
uwetews
2015-10-29 22:17:35 +01:00
parent a0f583078d
commit 55f38125a4
17 changed files with 262 additions and 323 deletions

View File

@@ -1,4 +1,7 @@
 ===== 3.1.28-dev===== (xx.xx.2015)
29.10.2015
- improve template scope handling
24.10.2015
- more optimizations of template processing
- bugfix Error when using {include} within {capture} https://github.com/smarty-php/smarty/issues/100

View File

@@ -87,21 +87,16 @@ if (!class_exists('Smarty_Autoloader', false)) {
/**
* Load always needed external class files
*/
if (false) {
if (!class_exists('Smarty_Internal_Data', false)) {
if (!class_exists('Smarty_Internal_Data', false)) {
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_data.php';
}
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_resource_file.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
}
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_extension_handler.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_templatebase.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_internal_template.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_resource.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_variable.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_source.php';
require_once SMARTY_SYSPLUGINS_DIR . 'smarty_template_resource_base.php';
/**
* This is the main Smarty class
@@ -123,18 +118,24 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '3.1.28-dev/73';
const SMARTY_VERSION = '3.1.28-dev/75';
/**
* define variable scopes
*/
const SCOPE_LOCAL = 0;
const SCOPE_PARENT = 1;
const SCOPE_PARENT = 2;
const SCOPE_ROOT = 2;
const SCOPE_TPL_ROOT = 4;
const SCOPE_GLOBAL = 3;
const SCOPE_ROOT = 8;
const SCOPE_SMARTY = 16;
const SCOPE_GLOBAL = 32;
const SCOPE_BUBBLE_UP = 64;
/**
* define caching modes
@@ -262,7 +263,7 @@ class Smarty extends Smarty_Internal_TemplateBase
*/
/**
* auto literal on delimiters with whitspace
* auto literal on delimiters with whitespace
*
* @var boolean
*/
@@ -276,7 +277,7 @@ class Smarty extends Smarty_Internal_TemplateBase
public $error_unassigned = false;
/**
* look up relative filepaths in include_path
* look up relative file path in include_path
*
* @var boolean
*/
@@ -1070,7 +1071,9 @@ class Smarty extends Smarty_Internal_TemplateBase
} else {
$data = null;
}
if ($this->caching && isset($this->_cache['isCached'][$_templateId = $this->_getTemplateId($template, $cache_id, $compile_id)])) {
if ($this->caching &&
isset($this->_cache['isCached'][$_templateId = $this->_getTemplateId($template, $cache_id, $compile_id)])
) {
$tpl = $do_clone ? clone $this->_cache['isCached'][$_templateId] : $this->_cache['isCached'][$_templateId];
$tpl->parent = $parent;
$tpl->tpl_vars = array();
@@ -1119,6 +1122,7 @@ class Smarty extends Smarty_Internal_TemplateBase
* @param string $template_name
* @param null|mixed $cache_id
* @param null|mixed $compile_id
* @param null $caching
*
* @return string
*/
@@ -1129,7 +1133,8 @@ class Smarty extends Smarty_Internal_TemplateBase
$caching = (int) ($caching === null ? $this->caching : $caching);
if ($this->allow_ambiguous_resources) {
$_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}#{$caching}";
$_templateId =
Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}#{$caching}";
} else {
$_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}";
}
@@ -1156,7 +1161,8 @@ class Smarty extends Smarty_Internal_TemplateBase
if ($pattern == null) {
$nds = DS == '/' ? '\\' : '/';
$ds = '\\' . DS;
$pattern = "#([{$ds}]+[^{$ds}]+[{$ds}]+[.]([{$ds}]+[.])*[.][{$ds}]+([.][{$ds}]+)*)|([{$ds}]+([.][{$ds}]+)+)|[{$ds}]{2,}#";
$pattern =
"#([{$ds}]+[^{$ds}]+[{$ds}]+[.]([{$ds}]+[.])*[.][{$ds}]+([.][{$ds}]+)*)|([{$ds}]+([.][{$ds}]+)+)|[{$ds}]{2,}#";
}
// normalize DS
if (strpos($path, $nds) !== false) {
@@ -1386,8 +1392,8 @@ class Smarty extends Smarty_Internal_TemplateBase
if (!isset(Smarty::$_muted_directories[SMARTY_DIR])) {
$smarty_dir = realpath(SMARTY_DIR);
if ($smarty_dir !== false) {
Smarty::$_muted_directories[SMARTY_DIR] = array('file' => $smarty_dir,
'length' => strlen($smarty_dir),);
Smarty::$_muted_directories[SMARTY_DIR] =
array('file' => $smarty_dir, 'length' => strlen($smarty_dir),);
}
}
@@ -1413,7 +1419,8 @@ class Smarty extends Smarty_Internal_TemplateBase
// or the error was within smarty but masked to be ignored
if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
if (Smarty::$_previous_error_handler) {
return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext);
return call_user_func(Smarty::$_previous_error_handler, $errno, $errstr, $errfile, $errline,
$errcontext);
} else {
return false;
}

View File

@@ -38,13 +38,6 @@ class Smarty_Data extends Smarty_Internal_Data
*/
public $smarty = null;
/**
* This object type (Smarty = 1, template = 2, data = 4)
*
* @var int
*/
public $_objType = 4;
/**
* create Smarty data object
*

View File

@@ -55,31 +55,30 @@ class Smarty_Internal_Compile_Assign extends Smarty_Internal_CompileBase
$_scope = Smarty::SCOPE_ROOT;
} elseif ($_attr['scope'] == 'global') {
$_scope = Smarty::SCOPE_GLOBAL;
} elseif ($_attr['scope'] == 'smarty') {
$_scope = Smarty::SCOPE_SMARTY;
} elseif ($_attr['scope'] == 'tpl_root') {
$_scope = Smarty::SCOPE_TPL_ROOT;
} else {
$compiler->trigger_template_error('illegal value for "scope" attribute', null, true);
}
$_scope += (isset($_attr['bubble_up']) && $_attr['bubble_up'] == 'false') ? 0 : Smarty::SCOPE_BUBBLE_UP;
}
// compiled output
if (isset($parameter['smarty_internal_index'])) {
$output = "<?php \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, $_attr[var], $_nocache, $_scope);\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value$parameter[smarty_internal_index] = $_attr[value];";
$output = "<?php \$_smarty_tpl->smarty->ext->_var->createLocalArrayVariable(\$_smarty_tpl, $_attr[var], $_nocache);\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value$parameter[smarty_internal_index] = $_attr[value];";
} else {
// implement Smarty2's behaviour of variables assigned by reference
if ($compiler->template->smarty instanceof SmartyBC) {
$output = "<?php if (isset(\$_smarty_tpl->tpl_vars[$_attr[var]])) {\$_smarty_tpl->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
$output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache; \$_smarty_tpl->tpl_vars[$_attr[var]]->scope = $_scope;";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache, $_scope);";
$output .= "\n\$_smarty_tpl->tpl_vars[$_attr[var]]->value = $_attr[value]; \$_smarty_tpl->tpl_vars[$_attr[var]]->nocache = $_nocache;";
$output .= "\n} else \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache);";
} else {
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache, $_scope);";
$output = "<?php \$_smarty_tpl->tpl_vars[$_attr[var]] = new Smarty_Variable($_attr[value], $_nocache);";
}
}
if ($_scope == Smarty::SCOPE_PARENT) {
$output .= "\nif (\$_smarty_tpl->parent != null) \$_smarty_tpl->parent->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
} elseif ($_scope == Smarty::SCOPE_ROOT || $_scope == Smarty::SCOPE_GLOBAL) {
$output .= "\n\$_ptr = \$_smarty_tpl->parent; while (\$_ptr != null) {\$_ptr->tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]]; \$_ptr = \$_ptr->parent; }";
}
if ($_scope == Smarty::SCOPE_GLOBAL) {
$output .= "\nSmarty::\$global_tpl_vars[$_attr[var]] = clone \$_smarty_tpl->tpl_vars[$_attr[var]];";
}
$output .= "\n\$_smarty_tpl->ext->_updateScope->updateScope(\$_smarty_tpl, $_attr[var], $_scope);";
$output .= '?>';
return $output;

View File

@@ -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');
public $option_flags = array('nocache', 'inline', 'caching', 'bubble_up');
/**
* Attribute definition: Overwrites base class.
@@ -113,10 +113,17 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
$_parent_scope = Smarty::SCOPE_ROOT;
} elseif ($_attr['scope'] == 'global') {
$_parent_scope = Smarty::SCOPE_GLOBAL;
} elseif ($_attr['scope'] == 'smarty') {
$_parent_scope = Smarty::SCOPE_SMARTY;
} elseif ($_attr['scope'] == 'tpl_root') {
$_parent_scope = Smarty::SCOPE_TPL_ROOT;
}
}
if ($_attr['bubble_up'] === true) {
$_parent_scope = $_parent_scope + Smarty::SCOPE_BUBBLE_UP;
}
//
// set flag to cache subtemplate object when called within loop or template name is variable.
if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) {
$_cache_tpl = 'true';
} else {
@@ -215,7 +222,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
}
// 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']);
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']);
// remaining attributes must be assigned as smarty variable
$_vars_nc = '';
if (!empty($_attr)) {
@@ -248,9 +255,9 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
if (isset($_assign)) {
$_output .= "ob_start();\n";
}
$_output .= "\$_smarty_tpl->smarty->ext->_inline->render(\$_smarty_tpl, {$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func']}');\n";
$_output .= "\$_smarty_tpl->smarty->ext->_subtemplate->render(\$_smarty_tpl, {$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func']}');\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(ob_get_clean());\n";
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
}
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
@@ -273,7 +280,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
$_output .= "\$_smarty_tpl->smarty->ext->_subtemplate->render(\$_smarty_tpl, {$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl});\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(ob_get_clean());\n";
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
}
if ($update_compile_id) {
$_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";

View File

@@ -20,10 +20,17 @@
* @method Smarty_Internal_Data clearAllAssign()
* @method Smarty_Internal_Data clearConfig(string $varName = null)
* @method Smarty_Internal_Data configLoad(string $config_file, mixed $sections = null, string $scope = 'local')
* @property int $_objType
* @property int $scope
*/
class Smarty_Internal_Data
{
/**
* This object type (Smarty = 1, template = 2, data = 4)
*
* @var int
*/
public $_objType = 4;
/**
* name of class used for templates
*
@@ -34,7 +41,7 @@ class Smarty_Internal_Data
/**
* template variables
*
* @var array
* @var Smarty_Variable[]
*/
public $tpl_vars = array();
@@ -48,7 +55,7 @@ class Smarty_Internal_Data
/**
* configuration settings
*
* @var array
* @var string[]
*/
public $config_vars = array();
@@ -67,6 +74,7 @@ class Smarty_Internal_Data
public function __construct()
{
$this->ext = new Smarty_Internal_Extension_Handler();
$this->ext->objType = $this->_objType;
}
/**
@@ -85,14 +93,19 @@ class Smarty_Internal_Data
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
$this->tpl_vars[$_key] = new Smarty_Variable($_val, $nocache);
if ($this->_objType == 2 && $this->scope) {
$this->ext->_updateScope->updateScope($this, $_key);
}
}
}
} else {
if ($tpl_var != '') {
$this->tpl_vars[$tpl_var] = new Smarty_Variable($value, $nocache);
if ($this->_objType == 2 && $this->scope) {
$this->ext->_updateScope->updateScope($this, $tpl_var);
}
}
}
return $this;
}
@@ -179,7 +192,8 @@ class Smarty_Internal_Data
*
* @param \Smarty_Internal_Data|null $data
*/
public function _mergeVars(Smarty_Internal_Data $data = null) {
public function _mergeVars(Smarty_Internal_Data $data = null)
{
if (isset($data)) {
if (!empty($this->tpl_vars)) {
$data->tpl_vars = array_merge($this->tpl_vars, $data->tpl_vars);

View File

@@ -12,7 +12,6 @@
*
* @property Smarty_Internal_Runtime_Inheritance $_inheritance
* @property Smarty_Internal_Runtime_SubTemplate $_subTemplate
* @property Smarty_Internal_Runtime_Inline $_inline
* @property Smarty_Internal_Runtime_TplFunction $_tplFunction
* @property Smarty_Internal_Runtime_Var $_var
* @property Smarty_Internal_Runtime_Config $_config
@@ -23,7 +22,7 @@
* @property Smarty_Internal_Runtime_CodeFrame $_codeFrame
* @property Smarty_Internal_Runtime_FilterHandler $_filterHandler
* @property Smarty_Internal_Runtime_GetIncludePath $_getIncludePath
* @property Smarty_Internal_Runtime_Source $_source
* @property Smarty_Internal_Runtime_UpdateScope $_updateScope
* @property Smarty_Internal_Runtime_IsCached $_isCached
* @property Smarty_Internal_Runtime_CacheModify $_cacheModify
* @property Smarty_Internal_Runtime_UpdateCache $_updateCache
@@ -40,6 +39,8 @@
class Smarty_Internal_Extension_Handler
{
public $objType = null;
/**
* Cache for property information from generic getter/setter
* Preloaded with names which should not use with generic getter/setter
@@ -52,8 +53,6 @@ class Smarty_Internal_Extension_Handler
private $resolvedProperties = array();
/**
* Call external Method
*
@@ -64,26 +63,29 @@ class Smarty_Internal_Extension_Handler
* @return mixed
* @throws SmartyException
*/
public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args) {
/* @var Smarty $data->smarty */
public function _callExternalMethod(Smarty_Internal_Data $data, $name, $args)
{
/* @var Smarty $data ->smarty */
$smarty = isset($data->smarty) ? $data->smarty : $data;
if (!isset($smarty->ext->$name)) {
$class = 'Smarty_Internal_Method_' . ucfirst($name);
if (preg_match('/^(set|get)([A-Z].*)$/', $name, $match)) {
if (!isset($this->_property_info[$prop = $match[2]])) {
// convert camel case to underscored name
$this->resolvedProperties[$prop] = $pn = strtolower(join('_', preg_split('/([A-Z][^A-Z]*)/', $prop, - 1, PREG_SPLIT_NO_EMPTY |
$this->resolvedProperties[$prop] = $pn = strtolower(join('_',
preg_split('/([A-Z][^A-Z]*)/', $prop, - 1,
PREG_SPLIT_NO_EMPTY |
PREG_SPLIT_DELIM_CAPTURE)));
$this->_property_info[$prop] = property_exists($data, $pn) ? 1 : ($data->_objType == 2 &&
property_exists($smarty, $pn) ? 2 : 0);
$this->_property_info[$prop] = property_exists($data, $pn) ? 1 :
($data->_objType == 2 && property_exists($smarty, $pn) ? 2 : 0);
}
if ($this->_property_info[$prop]) {
$pn = $this->resolvedProperties[$prop];
if ($match[1] == 'get') {
return $this->_property_info[$prop] == 1 ? $data->$pn : $data->smarty->$pn;
} else {
return $this->_property_info[$prop] ==
1 ? $data->$pn = $args[0] : $data->smarty->$pn = $args[0];
return $this->_property_info[$prop] == 1 ? $data->$pn = $args[0] :
$data->smarty->$pn = $args[0];
}
} elseif (!class_exists($class)) {
throw new SmartyException("property '$pn' does not exist.");
@@ -130,7 +132,6 @@ class Smarty_Internal_Extension_Handler
$class = 'Smarty_Internal_Runtime_' . ucfirst(substr($property_name, 1));
} else {
$class = 'Smarty_Internal_Method_' . ucfirst($property_name);
}
if (class_exists($class)) {
return $this->$property_name = new $class();

View File

@@ -39,7 +39,7 @@ class Smarty_Internal_Method_Append
// $tpl_var is an array, ignore $value
foreach ($tpl_var as $_key => $_val) {
if ($_key != '') {
self::append($data, $_key, $_val, $merge, $nocache);
$this->append($data, $_key, $_val, $merge, $nocache);
}
}
} else {
@@ -65,6 +65,9 @@ class Smarty_Internal_Method_Append
$data->tpl_vars[$tpl_var]->value[] = $value;
}
}
if ($data->_objType == 2 && $data->scope) {
$data->ext->_updateScope->updateScope($data, $tpl_var);
}
}
return $data;
}

View File

@@ -41,6 +41,9 @@ class Smarty_Internal_Method_AppendByRef
} else {
$data->tpl_vars[$tpl_var]->value[] = &$value;
}
if ($data->_objType == 2 && $data->scope) {
$data->ext->_updateScope->updateScope($data, $tpl_var);
}
}
return $data;
}

View File

@@ -27,8 +27,10 @@ class Smarty_Internal_Method_AssignByRef
if ($tpl_var != '') {
$data->tpl_vars[$tpl_var] = new Smarty_Variable(null, $nocache);
$data->tpl_vars[$tpl_var]->value = &$value;
if ($data->_objType == 2 && $data->scope) {
$data->ext->_updateScope->updateScope($data, $tpl_var);
}
}
return $data;
}
}

View File

@@ -1,85 +0,0 @@
<?php
/**
* Inline Runtime Methods render, setSourceByUid, setupSubTemplate
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*
**/
class Smarty_Internal_Runtime_Inline
{
/**
* Template code runtime function to set up an inline subtemplate
*
* @param \Smarty_Internal_Template $parent
* @param string $template template name
* @param mixed $cache_id cache id
* @param mixed $compile_id compile id
* @param integer $caching cache mode
* @param integer $cache_lifetime life time of cache data
* @param array $data passed parameter template variables
* @param int $scope scope in which {include} should execute
* @param bool $forceTplCache cache template object
* @param string $uid file dependency uid
* @param string $content_func function name
*
* @throws \Exception
*/
public function render(\Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching,
$cache_lifetime, $data, $scope, $forceTplCache, $uid, $content_func)
{
$tpl = $parent->smarty->ext->_subTemplate->setupSubTemplate($parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data,
$scope, $forceTplCache, $uid);
if ($parent->smarty->debugging) {
$parent->smarty->_debug->start_template($tpl);
$parent->smarty->_debug->start_render($tpl);
}
$tpl->compiled->getRenderedTemplateCode($tpl, $content_func);
if ($parent->smarty->debugging) {
$parent->smarty->_debug->end_template($tpl);
$parent->smarty->_debug->end_render($tpl);
}
if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) {
$parent->cached->hashes[$tpl->compiled->nocache_hash] = true;
}
}
/**
* Set source object of inline template by $uid
*
* @param \Smarty_Internal_Template $tpl
* @param string $uid
*
* @throws \SmartyException
*/
public function setSource(Smarty_Internal_Template $tpl, $uid = null)
{
// $uid is set if template is inline
if (isset($uid)) {
// inline templates have same compiled resource
$tpl->compiled = $tpl->parent->compiled;
if (isset($tpl->compiled->file_dependency[$uid])) {
list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid];
$tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ?
$tpl->smarty->_cache['resource_handlers'][$resource] :
Smarty_Resource::load($tpl->smarty, $resource),
$tpl->smarty, $filepath, $resource, $filepath);
$tpl->source->filepath = $filepath;
$tpl->source->timestamp = $timestamp;
$tpl->source->exists = true;
$tpl->source->uid = $uid;
} else {
$tpl->source = null;
}
} else {
$tpl->source = null;
unset($tpl->compiled);
}
if (!isset($tpl->source)) {
$tpl->source = Smarty_Template_Source::load($tpl);
}
}
}

View File

@@ -11,8 +11,20 @@
class Smarty_Internal_Runtime_SubTemplate
{
/**
* Subtemplate template object cache
*
* @var Smarty_Internal_Template[]
*/
public $tplObjects = array();
/**
* Subtemplate call count
*
* @var int[]
*/
public $subTplInfo = array();
/**
* Runtime function to render subtemplate
*
@@ -25,39 +37,20 @@ class Smarty_Internal_Runtime_SubTemplate
* @param array $data passed parameter template variables
* @param int $scope scope in which {include} should execute
* @param bool $forceTplCache cache template object
* @param string $uid file dependency uid
* @param string $content_func function name
*
*/
public function render(Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching,
$cache_lifetime, $data, $scope, $forceTplCache)
{$this->setupSubTemplate($parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data,
$scope, $forceTplCache)->render();
}
/**
* Runtime function to get subtemplate object from cache or clone from parent
*
* @param \Smarty_Internal_Template $parent calling template
* @param string $template template name
* @param mixed $cache_id cache id
* @param mixed $compile_id compile id
* @param integer $caching cache mode
* @param integer $cache_lifetime life time of cache data
* @param array $data passed parameter template variables
* @param int $scope scope in which {include} should execute
* @param $forceTplCache
* @param string|null $uid source uid
*
* @return \Smarty_Internal_Template template object
*/
public function setupSubTemplate(Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching,
$cache_lifetime, $data, $scope, $forceTplCache, $uid = null)
$cache_lifetime, $data, $scope, $forceTplCache, $uid = null, $content_func = null)
{
// if there are cached template objects calculate $templateID
$_templateId = !empty($this->tplObjects) ?
$parent->smarty->_getTemplateId($template, $cache_id, $compile_id, $caching) : null;
$_templateId =
!empty($this->tplObjects) ? $parent->smarty->_getTemplateId($template, $cache_id, $compile_id, $caching) :
null;
// already in template cache?
/* @var Smarty_Internal_Template $tpl */
if (isset($this->tplObjects[$_templateId])) {
if (isset($_templateId) && isset($this->tplObjects[$_templateId])) {
// clone cached template object because of possible recursive call
$tpl = clone $this->tplObjects[$_templateId];
$tpl->parent = $parent;
@@ -66,10 +59,9 @@ class Smarty_Internal_Runtime_SubTemplate
unset($tpl->compiled);
}
// get variables from calling scope
if ($scope == Smarty::SCOPE_LOCAL && $tpl->scope == Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars = $parent->tpl_vars;
$tpl->config_vars = $parent->config_vars;
}
// get template functions
$tpl->tpl_function = $parent->tpl_function;
// copy inheritance object?
if (isset($parent->ext->_inheritance)) {
@@ -86,9 +78,27 @@ class Smarty_Internal_Runtime_SubTemplate
$tpl->cache_id = $cache_id;
$tpl->compile_id = $compile_id;
if (isset($uid)) {
$tpl->ext->_inline->setSource($tpl, $uid);
// for inline templates we can get all resource information from file dependency
if (isset($tpl->compiled->file_dependency[$uid])) {
list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid];
$tpl->source =
new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ?
$tpl->smarty->_cache['resource_handlers'][$resource] :
Smarty_Resource::load($tpl->smarty, $resource), $tpl->smarty,
$filepath, $resource, $filepath);
$tpl->source->filepath = $filepath;
$tpl->source->timestamp = $timestamp;
$tpl->source->exists = true;
$tpl->source->uid = $uid;
} else {
$this->setSource($tpl, $uid);
$tpl->source = null;
}
} else {
$tpl->source = null;
}
if (!isset($tpl->source)) {
$tpl->source = Smarty_Template_Source::load($tpl);
unset($tpl->compiled);
}
unset($tpl->cached);
}
@@ -98,37 +108,31 @@ class Smarty_Internal_Runtime_SubTemplate
if ($caching == 9999) {
$tpl->cached = $parent->cached;
}
// get variables from calling scope
if ($scope != $tpl->scope) {
if ($tpl->scope != Smarty::SCOPE_LOCAL) {
//We must get rid of pointers
unset($tpl->tpl_vars, $tpl->config_vars);
$tpl->tpl_vars = array();
$tpl->config_vars = array();
}
if ($scope == Smarty::SCOPE_PARENT) {
$tpl->tpl_vars = &$parent->tpl_vars;
$tpl->config_vars = &$parent->config_vars;
} elseif ($scope == Smarty::SCOPE_GLOBAL) {
$tpl->tpl_vars = &Smarty::$global_tpl_vars;
$tpl->config_vars = $parent->config_vars;
} elseif ($scope == Smarty::SCOPE_ROOT) {
$ptr = $tpl->parent;
while (!empty($ptr->parent)) {
$ptr = $ptr->parent;
}
$tpl->tpl_vars = &$ptr->tpl_vars;
$tpl->config_vars = &$ptr->config_vars;
} else {
$tpl->tpl_vars = $parent->tpl_vars;
$tpl->config_vars = $parent->config_vars;
}
// set template scope
$tpl->scope = $scope;
$scopePtr = false;
if ($scope & ~Smarty::SCOPE_BUBBLE_UP) {
if ($scope == Smarty::SCOPE_GLOBAL) {
$tpl->tpl_vars = Smarty::$global_tpl_vars;
$scopePtr = true;
} elseif ($scope == Smarty::SCOPE_PARENT) {
$scopePtr = $parent;
} elseif ($scope == Smarty::SCOPE_SMARTY) {
$scopePtr = $tpl->smarty;
} else {
$scopePtr = $tpl;
while (isset($scopePtr->parent)) {
if ($scopePtr->parent->_objType != 2 && $scope & Smarty::SCOPE_TPL_ROOT) {
break;
}
$scopePtr = $scopePtr->parent;
}
}
$tpl->tpl_vars = $scopePtr->tpl_vars;
$tpl->config_vars = $scopePtr->config_vars;
}
if (!isset($this->tplObjects[$tpl->_getTemplateId()]) &&
!$tpl->source->handler->recompiled
) {
if (!isset($this->tplObjects[$tpl->_getTemplateId()]) && !$tpl->source->handler->recompiled) {
// if template is called multiple times set flag to to cache template objects
$forceTplCache = $forceTplCache ||
(isset($this->subTplInfo[$tpl->template_resource]) && $this->subTplInfo[$tpl->template_resource] > 1);
@@ -147,29 +151,38 @@ class Smarty_Internal_Runtime_SubTemplate
$tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
}
}
return $tpl;
if (isset($uid)) {
if ($parent->smarty->debugging) {
$parent->smarty->_debug->start_template($tpl);
$parent->smarty->_debug->start_render($tpl);
}
$tpl->compiled->getRenderedTemplateCode($tpl, $content_func);
if ($parent->smarty->debugging) {
$parent->smarty->_debug->end_template($tpl);
$parent->smarty->_debug->end_render($tpl);
}
if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) {
$parent->cached->hashes[$tpl->compiled->nocache_hash] = true;
}
} else {
if (isset($tpl->compiled)) {
$tpl->compiled->render($tpl);
} else {
$tpl->render();
}
}
if ($scopePtr) {
if ($scope == Smarty::SCOPE_GLOBAL) {
Smarty::$global_tpl_vars = $tpl->tpl_vars;
} else {
$scopePtr->tpl_vars = $tpl->tpl_vars;
$scopePtr->config_vars = $tpl->config_vars;
}
/**
* Set source object of inline template by $uid
*
* @param \Smarty_Internal_Template $tpl
* @param string $uid
*
* @throws \SmartyException
*/
public function setSource(Smarty_Internal_Template $tpl, $uid = null)
{
//load source
$tpl->source = null;
unset($tpl->compiled);
if (!isset($tpl->source)) {
$tpl->source = Smarty_Template_Source::load($tpl);
}
}
/**
* Get called subtemplates and its call count from compiled template
* Get called subtemplates from compiled template and save call count
*
* @param \Smarty_Internal_Template $tpl
*/
@@ -182,5 +195,5 @@ class Smarty_Internal_Runtime_SubTemplate
}
}
}
}
}

View File

@@ -16,18 +16,13 @@ class Smarty_Internal_Runtime_Var
* @param \Smarty_Internal_Template $tpl template object
* @param string $varName template variable name
* @param bool $nocache cache mode of variable
* @param int $scope scope of variable
*/
public function createLocalArrayVariable(\Smarty_Internal_Template $tpl, $varName, $nocache = false,
$scope = Smarty::SCOPE_LOCAL)
public function createLocalArrayVariable(\Smarty_Internal_Template $tpl, $varName, $nocache = false)
{
if (!isset($tpl->tpl_vars[$varName])) {
$tpl->tpl_vars[$varName] = new Smarty_Variable(array(), $nocache, $scope);
$tpl->tpl_vars[$varName] = new Smarty_Variable(array(), $nocache);
} else {
$tpl->tpl_vars[$varName] = clone $tpl->tpl_vars[$varName];
if ($scope != Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars[$varName]->scope = $scope;
}
if (!(is_array($tpl->tpl_vars[$varName]->value) ||
$tpl->tpl_vars[$varName]->value instanceof ArrayAccess)
) {

View File

@@ -166,7 +166,8 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
// display or fetch
if ($display) {
if ($this->caching && $this->smarty->cache_modified_check) {
$this->smarty->ext->_cachemodify->cacheModifiedCheck($this->cached, $this, isset($content) ? $content : ob_get_clean());
$this->smarty->ext->_cachemodify->cacheModifiedCheck($this->cached, $this,
isset($content) ? $content : ob_get_clean());
} else {
if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) &&
!$no_output_filter && (isset($this->smarty->autoload_filters['output']) ||
@@ -324,8 +325,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
case 'compiled':
case 'cached':
case 'compiler':
case 'tpl_vars':
case 'config_vars':
$this->$property_name = $value;
return;
default:

View File

@@ -14,12 +14,12 @@
* @package Smarty
* @subpackage Template
*
* @property Smarty $smarty
* @method Smarty_Internal_TemplateBase setAutoloadFilters(mixed $filters, string $type = null)
* @method Smarty_Internal_TemplateBase addAutoloadFilters(mixed $filters, string $type = null)
* @method array getAutoloadFilters(string $type = null)
* @local_method Smarty_Internal_TemplateBase registerFilter(string $type, callback $callback, string $name = null)
* @method Smarty_Internal_TemplateBase unregisterFilter(string $type, mixed $callback)
* @local_method bool loadFilter(string $type, string $name)
* @method Smarty_Internal_TemplateBase unloadFilter(string $type, string $name)
* @method string getDebugTemplate()
* @method Smarty_Internal_TemplateBase setDebugTemplate(string $tpl_name)
@@ -31,11 +31,7 @@
* @method Smarty_Internal_TemplateBase unregisterResource(string $name)
* @method Smarty_Internal_TemplateBase registerCacheResource(string $name, Smarty_CacheResource $resource_handler)
* @method Smarty_Internal_TemplateBase unregisterCacheResource(string $name)
* @local_method Smarty_Internal_TemplateBase registerPlugin(string $type, string $name, callback $callback, bool
* $cacheable = true, mixed $cache_attr = null)
* @method Smarty_Internal_TemplateBase unregisterPlugin(string $type, string $name)
* @local_method Smarty_Internal_TemplateBase registerObject(string $object_name, object $object, array
* $allowed_methods_properties = array(), bool $format = true, array $block_methods = array())
* @method Smarty_Internal_TemplateBase unregisterObject(string $object_name)
* @method object getRegisteredObject(string $object_name)
* @method Smarty_Internal_TemplateBase registerClass(string $class_name, string $class_impl)
@@ -146,17 +142,19 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*/
private function _execute($template, $cache_id, $compile_id, $parent, $function)
{
/* @var Smarty $this ->smarty */
$smarty = $this->_objType == 1 ? $this : $this->smarty;
if ($template === null) {
if ($this->_objType != 2) {
throw new SmartyException($function . '():Missing \'$template\' parameter');
} else {
$template = $this;
$template = clone $this;
}
} elseif (is_object($template)) {
if (!isset($template->_objType) || $template->_objType != 2) {
throw new SmartyException($function . '():Template object expected');
} else {
/* @var Smarty_Internal_Template $template */
$template = clone $template;
}
} else {
// get template object
@@ -186,16 +184,11 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
}
} else {
ob_start();
$save_tpl_vars = $template->tpl_vars;
$save_config_vars = $template->config_vars;
$template->_mergeVars();
if (!empty(Smarty::$global_tpl_vars)) {
$template->tpl_vars = array_merge(Smarty::$global_tpl_vars, $template->tpl_vars);
}
$result = $template->render(false, $function);
// restore local variables
$template->tpl_vars = $save_tpl_vars;
$template->config_vars = $save_config_vars;
}
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);

View File

@@ -477,11 +477,11 @@ class Smarty_Internal_TestInstall
'smarty_internal_runtime_getincludepath.php' => true,
'smarty_internal_runtime_hhvm.php' => true,
'smarty_internal_runtime_inheritance.php' => true,
'smarty_internal_runtime_inline.php' => true,
'smarty_internal_runtime_iscached.php' => true,
'smarty_internal_runtime_subtemplate.php' => true,
'smarty_internal_runtime_tplfunction.php' => true,
'smarty_internal_runtime_updatecache.php' => true,
'smarty_internal_runtime_updatescope.php' => true,
'smarty_internal_runtime_validatecompiled.php' => true,
'smarty_internal_runtime_var.php' => true,
'smarty_internal_runtime_writefile.php' => true,

View File

@@ -21,25 +21,17 @@ class Smarty_Variable
* @var boolean
*/
public $nocache = false;
/**
* the scope the variable will have (local,parent or root)
*
* @var int
*/
public $scope = Smarty::SCOPE_LOCAL;
/**
* create Smarty variable object
*
* @param mixed $value the value to assign
* @param boolean $nocache if true any output of this variable will be not cached
* @param int $scope the scope the variable will have (local,parent or root)
*/
public function __construct($value = null, $nocache = false, $scope = Smarty::SCOPE_LOCAL)
public function __construct($value = null, $nocache = false)
{
$this->value = $value;
$this->nocache = $nocache;
$this->scope = $scope;
}
/**