- optimization move subtemplate processing back into template object

This commit is contained in:
uwetews
2015-12-23 03:08:23 +01:00
parent 8a0562fb58
commit db2cace210
10 changed files with 192 additions and 218 deletions

View File

@@ -1,6 +1,7 @@
 ===== 3.1.30-dev ===== (xx.xx.xx)
23.12.2015
- optimization move internal method decodeProperties back into template object
- optimization move subtemplate processing back into template object
22.12.2015
- change $xxx_dir properties from private to protected in case Smarty class gets extended

View File

@@ -118,7 +118,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '3.1.30-dev/6';
const SMARTY_VERSION = '3.1.30-dev/7';
/**
* define variable scopes

View File

@@ -216,8 +216,6 @@ abstract class Smarty_CacheResource
public function invalidLoadedCache(Smarty $smarty)
{
$smarty->_cache['isCached'] = array();
if (isset($smarty->ext->_subtemplate)) {
$smarty->ext->_subtemplate->tplObjects = array();
}
$smarty->_cache['tplObjects'] = array();
}
}

View File

@@ -269,7 +269,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
if (isset($_assign)) {
$_output .= "ob_start();\n";
}
$_output .= "\$_smarty_tpl->smarty->ext->_subtemplate->render(\$_smarty_tpl, {$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func']}');\n";
$_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_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->assign({$_assign}, ob_get_clean());\n";
}
@@ -292,7 +292,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
if (isset($_assign)) {
$_output .= "ob_start();\n";
}
$_output .= "\$_smarty_tpl->smarty->ext->_subtemplate->render(\$_smarty_tpl, {$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_scope, {$_cache_tpl});\n";
$_output .= "\$_smarty_tpl->_subTemplateRender({$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_scope, {$_cache_tpl});\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean());\n";
}

View File

@@ -11,7 +11,6 @@
* @author Uwe Tews
*
* @property Smarty_Internal_Runtime_Inheritance $_inheritance
* @property Smarty_Internal_Runtime_SubTemplate $_subTemplate
* @property Smarty_Internal_Runtime_TplFunction $_tplFunction
* @property Smarty_Internal_Runtime_Var $_var
* @property Smarty_Internal_Runtime_Foreach $_foreach

View File

@@ -116,9 +116,7 @@ class Smarty_Internal_Method_ClearCompiledTemplate
}
// clear template objects cache
$smarty->_cache['isCached'] = array();
if (isset($smarty->ext->_subtemplate)) {
$smarty->ext->_subtemplate->tplObjects = array();
}
$smarty->_cache['tplObjects'] = array();
return $_count;
}
}

View File

@@ -1,203 +0,0 @@
<?php
/**
* Sub Template Runtime Methods render, setupSubTemplate
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*
**/
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
*
* @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
*
*/
public function render(Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching,
$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;
// already in template cache?
/* @var Smarty_Internal_Template $tpl */
if (isset($_templateId) && isset($this->tplObjects[$_templateId])) {
// clone cached template object because of possible recursive call
$tpl = clone $this->tplObjects[$_templateId];
$tpl->parent = $parent;
// if $caching mode changed the compiled resource is invalid
if ((bool) $tpl->caching !== (bool) $caching) {
unset($tpl->compiled);
}
// get variables from calling scope
$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)) {
$tpl->ext->_inheritance = $parent->ext->_inheritance;
} else {
unset($tpl->ext->_inheritance);
}
} else {
$tpl = clone $parent;
$tpl->parent = $parent;
if (!isset($tpl->templateId) || $tpl->templateId !== $_templateId) {
$tpl->templateId = $_templateId;
$tpl->template_resource = $template;
$tpl->cache_id = $cache_id;
$tpl->compile_id = $compile_id;
if (isset($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 {
$tpl->source = null;
}
} else {
$tpl->source = null;
}
if (!isset($tpl->source)) {
$tpl->source = Smarty_Template_Source::load($tpl);
unset($tpl->compiled);
}
unset($tpl->cached);
}
}
$tpl->caching = $caching;
$tpl->cache_lifetime = $cache_lifetime;
if ($caching == 9999) {
$tpl->cached = $parent->cached;
}
// 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;
$tpl->config_vars = $tpl->smarty->config_vars;
$scopePtr = true;
} else {
if ($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 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);
// check if template object should be cached
if ($tpl->parent->_objType == 2 && isset($this->tplObjects[$tpl->parent->templateId]) ||
($forceTplCache && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) ||
($tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON)
) {
$this->tplObjects[$tpl->_getTemplateId()] = $tpl;
}
}
if (!empty($data)) {
// set up variable values
foreach ($data as $_key => $_val) {
$tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
}
}
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;
$tpl->smarty->config_vars = $tpl->config_vars;
} else {
$scopePtr->tpl_vars = $tpl->tpl_vars;
$scopePtr->config_vars = $tpl->config_vars;
}
}
}
/**
* Get called subtemplates from compiled template and save call count
*
* @param \Smarty_Internal_Template $tpl
*/
public function registerSubTemplates(Smarty_Internal_Template $tpl)
{
foreach ($tpl->compiled->includes as $name => $count) {
if (isset($this->subTplInfo[$name])) {
$this->subTplInfo[$name] += $count;
} else {
$this->subTplInfo[$name] = $count;
}
}
}
}

View File

@@ -211,6 +211,189 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
}
}
/**
* Runtime function to render sub-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 bool $forceTplCache cache template object
* @param string $uid file dependency uid
* @param string $content_func function name
*
*/
public function _subTemplateRender($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $scope,
$forceTplCache, $uid = null, $content_func = null)
{
$_templateId = $this->smarty->_getTemplateId($template, $cache_id, $compile_id, $caching);
// already in template cache?
/* @var Smarty_Internal_Template $tpl */
if (isset($this->smarty->_cache[ 'tplObjects' ][ $_templateId ])) {
// clone cached template object because of possible recursive call
$tpl = clone $this->smarty->_cache[ 'tplObjects' ][ $_templateId ];
// get variables from calling scope
$tpl->tpl_vars = $this->tpl_vars;
$tpl->config_vars = $this->config_vars;
$tpl->parent = $this;
// get template functions
$tpl->tpl_function = $this->tpl_function;
// copy inheritance object?
if (isset($this->ext->_inheritance)) {
$tpl->ext->_inheritance = $this->ext->_inheritance;
} else {
unset($tpl->ext->_inheritance);
}
// if $caching mode changed the compiled resource is invalid
if ((bool) $tpl->caching !== (bool) $caching) {
unset($tpl->compiled);
}
} else {
$tpl = clone $this;
$tpl->parent = $this;
if (!isset($tpl->templateId) || $tpl->templateId !== $_templateId) {
$tpl->templateId = $_templateId;
$tpl->template_resource = $template;
$tpl->cache_id = $cache_id;
$tpl->compile_id = $compile_id;
if (isset($uid)) {
if (isset($tpl->compiled)) {
$tpl->compiled->isInit = false;
}
// for inline templates we can get all resource information from file dependency
if (isset($tpl->compiled->file_dependency[ $uid ])) {
list($filepath, $timestamp, $type) = $tpl->compiled->file_dependency[ $uid ];
$tpl->source =
new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$type]) ?
$tpl->smarty->_cache['resource_handlers'][$type] :
Smarty_Resource::load($tpl->smarty, $type), $tpl->smarty,
$filepath, $type, $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;
}
if (!isset($tpl->source)) {
$tpl->source = Smarty_Template_Source::load($tpl);
unset($tpl->compiled);
}
unset($tpl->cached);
}
}
$tpl->caching = $caching;
$tpl->cache_lifetime = $cache_lifetime;
if ($caching == 9999) {
$tpl->cached = $this->cached;
}
// 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;
$tpl->config_vars = $tpl->smarty->config_vars;
$scopePtr = true;
} else {
if ($scope == Smarty::SCOPE_PARENT) {
$scopePtr = $this;
} elseif ($scope == Smarty::SCOPE_SMARTY) {
$scopePtr = $tpl->smarty;
} else {
$scopePtr = $tpl;
while (isset($scopePtr->parent)) {
if (!$scopePtr->_isParentTemplate() && $scope & Smarty::SCOPE_TPL_ROOT) {
break;
}
$scopePtr = $scopePtr->parent;
}
}
$tpl->tpl_vars = $scopePtr->tpl_vars;
$tpl->config_vars = $scopePtr->config_vars;
}
}
if (!isset($tpl->smarty->_cache[ 'tplObjects' ][ $tpl->templateId ]) && !$tpl->source->handler->recompiled) {
// if template is called multiple times set flag to to cache template objects
$forceTplCache = $forceTplCache ||
(isset($tpl->smarty->_cache[ 'subTplInfo' ][ $tpl->template_resource ]) &&
$tpl->smarty->_cache[ 'subTplInfo' ][ $tpl->template_resource ] > 1);
// check if template object should be cached
if ($tpl->_isParentTemplate() && isset($tpl->smarty->_cache[ 'tplObjects' ][ $tpl->parent->templateId ]) ||
$forceTplCache) {
$tpl->smarty->_cache[ 'tplObjects' ][ $tpl->templateId ] = $tpl;
}
}
if (!empty($data)) {
// set up variable values
foreach ($data as $_key => $_val) {
$tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val);
}
}
if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) {
$this->cached->hashes[ $tpl->compiled->nocache_hash ] = true;
}
if (isset($uid)) {
if ($this->smarty->debugging) {
$this->smarty->_debug->start_template($tpl);
$this->smarty->_debug->start_render($tpl);
}
$tpl->compiled->getRenderedTemplateCode($tpl, $content_func);
if ($this->smarty->debugging) {
$this->smarty->_debug->end_template($tpl);
$this->smarty->_debug->end_render($tpl);
}
} 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;
$tpl->smarty->config_vars = $tpl->config_vars;
} else {
$scopePtr->tpl_vars = $tpl->tpl_vars;
$scopePtr->config_vars = $tpl->config_vars;
}
}
}
/**
* Get called sub-templates and save call count
*
*/
public function _subTemplateRegister()
{
foreach ($this->compiled->includes as $name => $count) {
if (isset($this->smarty->_cache[ 'subTplInfo' ][ $name ])) {
$this->smarty->_cache[ 'subTplInfo' ][ $name ] += $count;
} else {
$this->smarty->_cache[ 'subTplInfo' ][ $name ] = $count;
}
}
}
/**
* Check if parent is template object
*
* @return bool true if parent is template
*/
public function _isParentTemplate()
{
return isset($this->parent) && $this->parent->_objType == 2;
}
/**
* This function is executed automatically when a compiled or cached template file is included
* - Decode saved properties from compiled template and cache files

View File

@@ -476,7 +476,6 @@ 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_subtemplate.php' => true,
'smarty_internal_runtime_tplfunction.php' => true,
'smarty_internal_runtime_updatecache.php' => true,
'smarty_internal_runtime_updatescope.php' => true,

View File

@@ -152,8 +152,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
$_template->smarty->compile_check = $compileCheck;
}
}
$_template->smarty->ext->_subTemplate->registerSubTemplates($_template);
$_template->_subTemplateRegister();
$this->processed = true;
}