- optimize internal subtemplate handling

This commit is contained in:
uwetews
2015-09-14 23:12:03 +02:00
parent 56a884a428
commit df0824675a
5 changed files with 48 additions and 278 deletions

View File

@@ -1,6 +1,7 @@
 ===== 3.1.28-dev===== (xx.xx.2015)
14.09.2015
- optimize autoloader
- optimize subtemplate handling
30.08.2015
- size optimization move some runtime functions into extension

View File

@@ -119,7 +119,7 @@ class Smarty extends Smarty_Internal_TemplateBase
/**
* smarty version
*/
const SMARTY_VERSION = '3.1.28-dev/55';
const SMARTY_VERSION = '3.1.28-dev/56';
/**
* define variable scopes

View File

@@ -71,15 +71,35 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
// check and get attributes
$_attr = $this->getAttributes($compiler, $args);
// save possible attributes
$include_file = $_attr['file'];
if ($compiler->has_variable_string ||
!((substr_count($include_file, '"') == 2 || substr_count($include_file, "'") == 2)) ||
substr_count($include_file, '(') != 0 || substr_count($include_file, '$_smarty_tpl->') != 0
) {
$variable_template = true;
$hashResourceName = $fullResourceName = $source_resource = $_attr['file'];
$variable_template = false;
$cache_tpl = false;
// parse resource_name
if (preg_match('/^([\'"])(([A-Za-z0-9_\-]{2,})[:])?(([^$()]+)|(.+))\1$/', $source_resource, $match)) {
$type = !empty($match[3]) ? $match[3] : $compiler->template->smarty->default_resource_type;
$name = !empty($match[5]) ? $match[5] : $match[6];
$handler = Smarty_Resource::load($compiler->smarty, $type);
if ($handler->recompiled || $handler->uncompiled) {
$variable_template = true;
}
if (!$variable_template) {
if ($type != 'string') {
$fullResourceName = "{$type}:{$name}";
$compiled = $compiler->parent_compiler->template->compiled;
if (isset($compiled->includes[$fullResourceName])) {
$compiled->includes[$fullResourceName] ++;
$cache_tpl = true;
} else {
$compiled->includes[$fullResourceName] = 1;
}
$fullResourceName = "'{$fullResourceName}'";
}
}
if (empty($match[5])) {
$variable_template = true;
}
} else {
$variable_template = false;
$variable_template = true;
}
if (isset($_attr['assign'])) {
@@ -100,7 +120,7 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
//
if ($variable_template || $compiler->loopNesting > 0) {
if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) {
$_cache_tpl = 'true';
} else {
$_cache_tpl = 'false';
@@ -191,28 +211,26 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
$t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
$tpl_name = null;
/** @var Smarty_Internal_Template $_smarty_tpl
* used in evaluated code
*/
$_smarty_tpl = $compiler->template;
eval("\$tpl_name = @$include_file;");
if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash])) {
if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash])) {
$compiler->smarty->allow_ambiguous_resources = true;
$tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template,
$compiler->template->cache_id, $c_id, $_caching);
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['uid'] = $tpl->source->uid;
/* @var Smarty_Internal_Template $tpl */
$tpl = new $compiler->smarty->template_class (trim($fullResourceName, "'"), $compiler->smarty,
$compiler->template, $compiler->template->cache_id, $c_id,
$_caching);
$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid'] =
$tpl->source->uid;
if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) {
$tpl->compiled = new Smarty_Template_Compiled();
$tpl->compiled->nocache_hash = $compiler->parent_compiler->template->compiled->nocache_hash;
$tpl->loadCompiler();
$tpl->isChild = $parameter['isChild'];
// save unique function name
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['func'] =
$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func'] =
$tpl->compiled->unifunc = 'content_' . str_replace(array('.', ','), '_', uniqid('', true));
// make sure whole chain gets compiled
$tpl->mustCompile = true;
$tpl->compiler->suppressTemplatePropertyHeader = true;
$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['nocache_hash'] =
$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['nocache_hash'] =
$tpl->compiled->nocache_hash;
// get compiled code
$compiled_code = Smarty_Internal_Extension_CodeFrame::createFunctionFrame($tpl,
@@ -259,12 +277,10 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
} else {
$_vars = 'array()';
}
$this->logInclude($compiler, $include_file, $variable_template);
$_isChild = var_export($parameter['isChild'], true);
$update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache &&
$_compile_id != '$_smarty_tpl->compile_id';
if ($has_compiled_template && !$call_nocache) {
$_output = "<?php /* Call merged included template \"" . $tpl_name . "\" */\n";
$_output = "<?php\n";
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n");
}
@@ -275,15 +291,15 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
}
if (isset($_assign)) {
$_output .= "ob_start();\n";
$_output .= "\$_smarty_tpl->_Inline->renderInline(\$_smarty_tpl, {$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, {$_isChild}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['func']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['uid']}');\n";
}
$_output .= "\$_smarty_tpl->renderInline(\$_smarty_tpl->setupSubTemplate({$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";
} else {
$_output .= "\$_smarty_tpl->_Inline->renderInline(\$_smarty_tpl, {$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, {$_isChild}, '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['func']}', '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$t_hash]['uid']}');\n";
}
if ($update_compile_id) {
$_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n");
}
$_output .= "/* End of included template \"" . $tpl_name . "\" */?>\n";
$_output .= "?>\n";
return $_output;
}
@@ -298,10 +314,10 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
// was there an assign attribute
if (isset($_assign)) {
$_output .= "ob_start();\n";
$_output .= "\$_smarty_tpl->_Subtemplate->renderSubtemplate(\$_smarty_tpl, $include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl}, {$_isChild});\n";
}
$_output .= "\$_smarty_tpl->setupSubTemplate({$fullResourceName}, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl})->render();\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(ob_get_clean());\n";
} else {
$_output .= "\$_smarty_tpl->_Subtemplate->renderSubtemplate(\$_smarty_tpl, $include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope, {$_cache_tpl}, {$_cache_tpl}, {$_isChild});\n";
}
if ($update_compile_id) {
$_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n";
@@ -309,27 +325,4 @@ class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase
$_output .= "?>\n";
return $_output;
}
/**
* log include count
*
* @param \Smarty_Internal_SmartyTemplateCompiler $compiler
* @param string $include_file
* @param bool $variable_template
*/
private function logInclude(Smarty_Internal_SmartyTemplateCompiler $compiler, $include_file, $variable_template)
{
if ($variable_template) {
return;
}
list($name, $type) = Smarty_Resource::parseResourceName(trim($include_file, '\'"'),
$compiler->template->smarty->default_resource_type);
if (in_array($type, array('eval', 'string'))) {
return;
}
$include_name = $type . ':' . $name;
$compiled = $compiler->parent_compiler->template->compiled;
$compiled->includes[$include_name] =
isset($compiled->includes[$include_name]) ? $compiled->includes[$include_name] + 1 : 1;
}
}

View File

@@ -1,59 +0,0 @@
<?php
/**
* Runtime Method renderInline
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*/
class Smarty_Internal_Runtime_Inline
{
/**
* Template code runtime function to render inline subtemplate
*
* @param Smarty_Internal_Template $callerTpl
* @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 $parent_scope scope in which {include} should execute
* @param bool $cache_tpl_obj cache template object
* @param bool $isChild flag if subtemplate is an inheritance child
* @param string $content_func name of content function
* @param string $uid source uid
*
* @throws \Exception
*/
public function renderInline(Smarty_Internal_Template $callerTpl, $template, $cache_id, $compile_id,
$caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj,
$isChild, $content_func, $uid)
{
// call runtime extension
/* @var Smarty_Internal_Template $tpl */
$tpl = $callerTpl->_Subtemplate->setupSubtemplate($callerTpl, $template, $cache_id, $compile_id,
$caching, $cache_lifetime, $data,
$parent_scope, $cache_tpl_obj, $uid);
$tpl->isChild = $isChild;
if ($callerTpl->smarty->debugging) {
$callerTpl->smarty->_debug->start_template($tpl);
$callerTpl->smarty->_debug->start_render($tpl);
}
$tpl->compiled->getRenderedTemplateCode($tpl, $content_func);
if ($callerTpl->smarty->debugging) {
$callerTpl->smarty->_debug->end_template($tpl);
$callerTpl->smarty->_debug->end_render($tpl);
}
if ($caching == 9999 && $tpl->compiled->has_nocache_code) {
$callerTpl->cached->hashes[$tpl->compiled->nocache_hash] = true;
}
if (!isset($callerTpl->_Block) && $isChild && isset($tpl->_Block) &&
($callerTpl->isChild || !empty($callerTpl->source->components))
) {
$callerTpl->_Block = $tpl->_Block;
}
}
}

View File

@@ -1,165 +0,0 @@
<?php
/**
* Runtime Method _getSubTemplate
*
* @package Smarty
* @subpackage PluginsInternal
* @author Uwe Tews
*
**/
class Smarty_Internal_Runtime_Subtemplate
{
/**
* Template code runtime function to get subtemplate content
*
* @param \Smarty_Internal_Template $callerTpl template object of caller
* @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 $parent_scope scope in which {include} should execute
* @param bool $cache_tpl_obj cache template object
* @param bool $isChild flag if subtemplate is an inheritance child
*
* @throws \SmartyException
*/
public function renderSubtemplate(Smarty_Internal_Template $callerTpl, $template, $cache_id, $compile_id, $caching,
$cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $isChild)
{
$tpl = $this->setupSubtemplate($callerTpl, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data,
$parent_scope, $cache_tpl_obj);
$tpl->isChild = $isChild;
$tpl->render();
if ($tpl->isChild && !isset($callerTpl->_Block) && isset($tpl->_Block) &&
($callerTpl->isChild || !empty($callerTpl->source->components))
) {
$callerTpl->_Block = $tpl->_Block;
}
}
/**
* Template code runtime function to set up an inline subtemplate
*
* @param \Smarty_Internal_Template $callerTpl
* @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 $parent_scope scope in which {include} should execute
* @param bool $cache_tpl_obj cache template object
* @param string|null $uid source uid
*
* @return \Smarty_Internal_Template template object
* @throws \SmartyException
*/
public function setupSubtemplate(Smarty_Internal_Template $callerTpl, $template, $cache_id, $compile_id, $caching,
$cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $uid = null)
{
$_templateId = isset($callerTpl->smarty->_cache['template_objects']) ?
$callerTpl->smarty->_getTemplateId($template, $cache_id, $compile_id) : null;
// already in template cache?
/* @var Smarty_Internal_Template $tpl */
if (isset($callerTpl->smarty->_cache['template_objects'][$_templateId])) {
// clone cached template object because of possible recursive call
$tpl = clone $callerTpl->smarty->_cache['template_objects'][$_templateId];
$tpl->parent = $callerTpl;
if ((bool) $tpl->caching !== (bool) $caching) {
unset($tpl->compiled);
}
// get variables from calling scope
if ($parent_scope == Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars = $callerTpl->tpl_vars;
$tpl->config_vars = $callerTpl->config_vars;
}
$tpl->tpl_function = $callerTpl->tpl_function;
//if (isset($callerTpl->_cache['inheritanceBlocks'])) {
// $tpl->_cache['inheritanceBlocks'] = $callerTpl->_cache['inheritanceBlocks'];
//}
} else {
$tpl = clone $callerTpl;
$tpl->parent = $callerTpl;
$tpl->isChild = false;
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)) {
$tpl->compiled = $callerTpl->compiled;
if (isset($tpl->compiled->includes["{$tpl->source->type}:{$tpl->source->name}"]) &&
$tpl->compiled->includes["{$tpl->source->type}:{$tpl->source->name}"] > 1
) {
$cache_tpl_obj = true;
}
if (isset($tpl->compiled->file_dependency[$uid])) {
$info = $tpl->compiled->file_dependency[$uid];
$tpl->source =
new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$info[2]]) ?
$tpl->smarty->_cache['resource_handlers'][$info[2]] :
Smarty_Resource::load($tpl->smarty, $info[2]), $tpl->smarty,
$info[0], $info[2], $info[0]);
$tpl->source->filepath = $info[0];
$tpl->source->timestamp = $info[1];
$tpl->source->exist = 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);
}
unset($tpl->cached);
// check if template object should be cached
if (!$tpl->source->handler->recompiled && (isset($tpl->parent->templateId) &&
isset($tpl->smarty->_cache['template_objects'][$tpl->parent->templateId]) ||
($cache_tpl_obj && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) ||
$tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON)
) {
$tpl->smarty->_cache['template_objects'][$tpl->_getTemplateId()] = $tpl;
}
}
}
$tpl->caching = $caching;
$tpl->cache_lifetime = $cache_lifetime;
if ($caching == 9999) {
$tpl->cached = $callerTpl->cached;
}
// get variables from calling scope
if ($parent_scope != Smarty::SCOPE_LOCAL) {
if ($parent_scope == Smarty::SCOPE_PARENT) {
$tpl->tpl_vars = &$callerTpl->tpl_vars;
$tpl->config_vars = &$callerTpl->config_vars;
} elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
$tpl->tpl_vars = &Smarty::$global_tpl_vars;
$tpl->config_vars = $callerTpl->config_vars;
} elseif ($parent_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 = $callerTpl->tpl_vars;
$tpl->config_vars = $callerTpl->config_vars;
}
}
if (!empty($data)) {
// set up variable values
foreach ($data as $_key => $_val) {
$tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
}
}
return $tpl;
}
}