- optimize rendering

This commit is contained in:
uwetews
2015-08-23 01:25:57 +02:00
parent 329cd6ec4d
commit 6a26393099
14 changed files with 401 additions and 358 deletions

View File

@@ -7,6 +7,7 @@
- use output buffers for better performance and less memory usage - use output buffers for better performance and less memory usage
- optimize nocache hash processing - optimize nocache hash processing
- remove not really needed properties - remove not really needed properties
- optimize rendering
06.08.2015 06.08.2015
- avoid possible circular object references caused by parser/lexer objects - avoid possible circular object references caused by parser/lexer objects

View File

@@ -756,67 +756,6 @@ class Smarty extends Smarty_Internal_TemplateBase
} }
} }
/**
* fetches a rendered Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @param bool $display true: display, false: fetch
* @param bool $merge_tpl_vars not used - left for BC
* @param bool $no_output_filter not used - left for BC
*
* @throws Exception
* @throws SmartyException
* @return string rendered template output
*/
public function fetch($template, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
{
if ($cache_id !== null && is_object($cache_id)) {
$parent = $cache_id;
$cache_id = null;
}
if ($parent === null) {
$parent = $this;
}
// get template object
$_template = is_object($template) ? $template : $this->createTemplate($template, $cache_id, $compile_id, $parent, false);
// set caching in template object
$_template->caching = $this->caching;
// fetch template content
$level = ob_get_level();
try {
$_smarty_old_error_level = isset($this->error_reporting) ? error_reporting($this->error_reporting) : null;
ob_start();
$result = $_template->render(true, false, $display);
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
}
return $result === null ? ob_get_clean() : $result;
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
/**
* displays a Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
*/
public function display($template, $cache_id = null, $compile_id = null, $parent = null)
{
// display template
$this->fetch($template, $cache_id, $compile_id, $parent, true);
}
/** /**
* Check if a template resource exists * Check if a template resource exists
* *
@@ -1180,10 +1119,20 @@ class Smarty extends Smarty_Internal_TemplateBase
} else { } else {
$data = null; $data = null;
} }
/* var Smarty $tpl */ $_templateId = $this->_getTemplateId($template, $cache_id, $compile_id);
$tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); if (isset($this->_cache['isCached'][$_templateId])) {
$tpl = $do_clone ? clone $this->_cache['isCached'][$_templateId] : $this->_cache['isCached'][$_templateId];
$tpl->parent = $parent;
$tpl->tpl_vars = array();
$tpl->config_vars = array();
} else {
/* @var Smarty_Internal_Template $tpl */
$tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id, null, null, $_templateId);
}
if ($do_clone) { if ($do_clone) {
$tpl->smarty = clone $tpl->smarty; $tpl->smarty = clone $tpl->smarty;
} elseif ($parent === null) {
$tpl->parent = $this;
} }
// fill data if present // fill data if present
if (!empty($data) && is_array($data)) { if (!empty($data) && is_array($data)) {
@@ -1214,6 +1163,31 @@ class Smarty extends Smarty_Internal_TemplateBase
return Smarty_Internal_Extension_LoadPlugin::loadPlugin($this, $plugin_name, $check); return Smarty_Internal_Extension_LoadPlugin::loadPlugin($this, $plugin_name, $check);
} }
/**
* Get unique template id
*
* @param string $template_name
* @param null|mixed $cache_id
* @param null|mixed $compile_id
*
* @return string
*/
public function _getTemplateId($template_name, $cache_id = null, $compile_id = null)
{
$cache_id = $cache_id === null ? $this->cache_id : $cache_id;
$compile_id = $compile_id === null ? $this->compile_id : $compile_id;
if ($this->allow_ambiguous_resources) {
$_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}";
} else {
$_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}";
}
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
}
return $_templateId;
}
/** /**
* Normalize path * Normalize path
* - remove /./ and /../ * - remove /./ and /../

View File

@@ -45,14 +45,8 @@ class Smarty_Internal_Method_ConfigLoad
$confObj->source->config_sections = $sections; $confObj->source->config_sections = $sections;
$confObj->source->scope = $scope; $confObj->source->scope = $scope;
$confObj->compiled = Smarty_Template_Compiled::load($confObj); $confObj->compiled = Smarty_Template_Compiled::load($confObj);
if ($confObj->smarty->debugging) {
$confObj->smarty->_debug->start_render($confObj);
}
$confObj->compiled->render($confObj); $confObj->compiled->render($confObj);
if ($confObj->smarty->debugging) { if ($data->_objType == 2) {
$confObj->smarty->_debug->end_render($confObj);
}
if ($data instanceof Smarty_Internal_Template) {
$data->compiled->file_dependency[$confObj->source->uid] = array($confObj->source->filepath, $data->compiled->file_dependency[$confObj->source->uid] = array($confObj->source->filepath,
$confObj->source->getTimeStamp(), $confObj->source->getTimeStamp(),
$confObj->source->type); $confObj->source->type);

View File

@@ -24,6 +24,14 @@ class Smarty_Internal_Resource_Php extends Smarty_Internal_Resource_File
*/ */
protected $short_open_tag; protected $short_open_tag;
/**
* Resource does implement populateCompiledFilepath() method
*
* @var bool
*/
public $hasCompiledHandler = true;
/** /**
* Create a new PHP Resource * Create a new PHP Resource
@@ -64,7 +72,7 @@ class Smarty_Internal_Resource_Php extends Smarty_Internal_Resource_File
throw new SmartyException("PHP templates are disabled"); throw new SmartyException("PHP templates are disabled");
} }
if (!$source->exists) { if (!$source->exists) {
if ($_template->parent instanceof Smarty_Internal_Template) { if ($_template->parent->_objType == 2) {
$parent_resource = " in '{$_template->parent->template_resource}'"; $parent_resource = " in '{$_template->parent->template_resource}'";
} else { } else {
$parent_resource = ''; $parent_resource = '';

View File

@@ -137,65 +137,14 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
// Template resource // Template resource
$this->template_resource = $template_resource; $this->template_resource = $template_resource;
$this->source = Smarty_Template_Source::load($this); $this->source = Smarty_Template_Source::load($this);
$this->templateId = isset($_templateId) ? $_templateId : $this->getTemplateId($template_resource, $this->cache_id, $this->compile_id); $this->templateId = isset($_templateId) ? $_templateId : $this->smarty->_getTemplateId($template_resource, $this->cache_id, $this->compile_id);
// copy block data of template inheritance // copy block data of template inheritance
if ($this->parent instanceof Smarty_Internal_Template) { if (isset($this->parent) && $this->parent->_objType == 2) {
$this->block_data = $this->parent->block_data; $this->block_data = $this->parent->block_data;
} }
} }
/**
* fetches rendered template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @param bool $_display true: display, false: fetch
*
* @return string
* @throws \Exception
*/
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $_display = false)
{
if (isset($template)) {
return $this->smarty->fetch($template, $cache_id, $compile_id, $parent, $_display);
} else {
// fetch template content
$level = ob_get_level();
try {
$_smarty_old_error_level = isset($this->smarty->error_reporting) ? error_reporting($this->smarty->error_reporting) : null;
ob_start();
$result = $this->render(true, false, $_display);
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
}
return $result === null ? ob_get_clean() : $result;
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
}
/**
* displays a Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
*
* @return string
*/
public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
{
$this->fetch($template, $cache_id, $compile_id, $parent, true);
}
/** /**
* render template * render template
* *
@@ -209,7 +158,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/ */
public function render($merge_tpl_vars = false, $no_output_filter = true, $display = null) public function render($merge_tpl_vars = false, $no_output_filter = true, $display = null)
{ {
$parentIsTpl = $this->parent instanceof Smarty_Internal_Template; $parentIsTpl = isset($this->parent) && $this->parent->_objType == 2;
if ($this->smarty->debugging) { if ($this->smarty->debugging) {
$this->smarty->_debug->start_template($this, $display); $this->smarty->_debug->start_template($this, $display);
} }
@@ -252,70 +201,30 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
$this->tpl_vars = $tpl_vars; $this->tpl_vars = $tpl_vars;
$this->config_vars = $config_vars; $this->config_vars = $config_vars;
} }
// check URL debugging control // check URL debugging control
if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') { if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') {
$this->smarty->_debug->debugUrl($this); $this->smarty->_debug->debugUrl($this);
} }
// disable caching for evaluated code if ($this->source->uncompiled) {
if ($this->source->recompiled) { $this->source->render($this);
$this->caching = false; } else {
} // disable caching for evaluated code
// read from cache or render if ($this->source->recompiled) {
$isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching = false;
$this->caching == Smarty::CACHING_LIFETIME_SAVED;
if ($isCacheTpl) {
if (!isset($this->cached)) {
$this->loadCached();
} }
$this->cached->isCached($this); // read from cache or render
} $isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT ||
if (!($isCacheTpl) || !$this->cached->valid) { $this->caching == Smarty::CACHING_LIFETIME_SAVED;
// render template (not loaded and not in cache) if ($isCacheTpl) {
if ($this->smarty->debugging) { if (!isset($this->cached)) {
$this->smarty->_debug->start_render($this); $this->loadCached();
} }
if (!$this->source->uncompiled) { $this->cached->render($this, $no_output_filter);
// render compiled code } else {
if (!isset($this->compiled)) { if (!isset($this->compiled)) {
$this->loadCompiled(); $this->loadCompiled();
} }
$this->compiled->render($this); $this->compiled->render($this);
} else {
$this->source->renderUncompiled($this);
}
if ($parentIsTpl && !empty($this->tpl_function)) {
$this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function);
}
if ($this->smarty->debugging) {
$this->smarty->_debug->end_render($this);
}
// write to cache when necessary
if (!$this->source->recompiled && $isCacheTpl) {
if ($this->smarty->debugging) {
$this->smarty->_debug->start_cache($this);
}
$this->cached->updateCache($this, $no_output_filter);
$compile_check = $this->smarty->compile_check;
$this->smarty->compile_check = false;
if ($parentIsTpl) {
$this->compiled->unifunc = $this->parent->compiled->unifunc;
}
if (!$this->cached->processed) {
$this->cached->process($this, true);
}
$this->smarty->compile_check = $compile_check;
$this->getRenderedTemplateCode($this->cached->unifunc);
if ($this->smarty->debugging) {
$this->smarty->_debug->end_cache($this);
}
}
} else {
if ($this->smarty->debugging) {
$this->smarty->_debug->start_cache($this);
}
$this->cached->render($this);
if ($this->smarty->debugging) {
$this->smarty->_debug->end_cache($this);
} }
} }
$content = null; $content = null;
@@ -359,7 +268,9 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
} }
} }
if ($parentIsTpl) { if ($parentIsTpl) {
$this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function); if (!empty($this->tpl_function)) {
$this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function);
}
foreach ($this->compiled->required_plugins as $code => $tmp1) { foreach ($this->compiled->required_plugins as $code => $tmp1) {
foreach ($tmp1 as $name => $tmp) { foreach ($tmp1 as $name => $tmp) {
foreach ($tmp as $type => $data) { foreach ($tmp as $type => $data) {
@@ -369,7 +280,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
} }
} }
// return cache content // return cache content
return $content === null ? null: $content; return $content === null ? null : $content;
} }
} }
@@ -439,30 +350,6 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
return $this->cached->writeCachedContent($this, $content); return $this->cached->writeCachedContent($this, $content);
} }
/**
* Get unique template id
*
* @param string $template_name
* @param null|mixed $cache_id
* @param null|mixed $compile_id
*
* @return string
*/
public function getTemplateId($template_name, $cache_id = null, $compile_id = null)
{
$cache_id = isset($cache_id) ? $cache_id : $this->cache_id;
$compile_id = isset($compile_id) ? $compile_id : $this->compile_id;
if ($this->smarty->allow_ambiguous_resources) {
$_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}";
} else {
$_templateId = $this->smarty->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}";
}
if (isset($_templateId[150])) {
$_templateId = sha1($_templateId);
}
return $_templateId;
}
/** /**
* Template code runtime function to get subtemplate content * Template code runtime function to get subtemplate content
* *
@@ -500,7 +387,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
*/ */
public function setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj) public function setupSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj)
{ {
$_templateId = $this->getTemplateId($template, $cache_id, $compile_id); $_templateId = $this->smarty->_getTemplateId($template, $cache_id, $compile_id);
// already in template cache? // already in template cache?
/* @var Smarty_Internal_Template $tpl */ /* @var Smarty_Internal_Template $tpl */
if (isset($this->smarty->template_objects[$_templateId])) { if (isset($this->smarty->template_objects[$_templateId])) {
@@ -510,41 +397,51 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if ((bool) $tpl->caching !== (bool) $caching) { if ((bool) $tpl->caching !== (bool) $caching) {
unset($tpl->compiled); unset($tpl->compiled);
} }
$tpl->caching = $caching; if ($parent_scope = Smarty::SCOPE_LOCAL) {
$tpl->cache_lifetime = $cache_lifetime; $tpl->tpl_vars = $this->tpl_vars;
$tpl->config_vars = $this->config_vars;
}
$tpl->tpl_function = $this->tpl_function;
} else { } else {
$tpl = new $this->smarty->template_class($template, $this->smarty, $this, $cache_id, $compile_id, $caching, $cache_lifetime, $_templateId); $tpl = clone $this;
} $tpl->parent = $this;
if (!$tpl->source->recompiled && !isset($this->smarty->template_objects[$_templateId]) && if ($tpl->templateId !== $_templateId) {
(isset($this->smarty->template_objects[$this->templateId]) || $tpl->templateId = $_templateId;
($cache_tpl_obj && $this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) || $tpl->template_resource = $template;
$this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) $tpl->cache_id = $cache_id;
) { $tpl->compile_id = $compile_id;
$this->smarty->template_objects[$_templateId] = $tpl; $tpl->source = Smarty_Template_Source::load($tpl);
unset($tpl->compiled, $tpl->cached);
$tpl->cacheTpl($cache_tpl_obj);
}
} }
$tpl->caching = $caching;
$tpl->cache_lifetime = $cache_lifetime;
if ($caching == 9999) { if ($caching == 9999) {
$tpl->cached = $this->cached; $tpl->cached = $this->cached;
} }
// get variables from calling scope // get variables from calling scope
if ($parent_scope == Smarty::SCOPE_LOCAL) { if ($parent_scope != Smarty::SCOPE_LOCAL) {
$tpl->tpl_vars = $this->tpl_vars; if ($parent_scope == Smarty::SCOPE_PARENT) {
} elseif ($parent_scope == Smarty::SCOPE_PARENT) { $tpl->tpl_vars = &$this->tpl_vars;
$tpl->tpl_vars = &$this->tpl_vars; $tpl->config_vars = &$this->config_vars;
} elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) {
$tpl->tpl_vars = &Smarty::$global_tpl_vars; $tpl->tpl_vars = &Smarty::$global_tpl_vars;
} elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) { $tpl->config_vars = $this->config_vars;
$tpl->tpl_vars = &$this->tpl_vars; } elseif (($scope_ptr = $this->getScopePointer($parent_scope)) == null) {
} else { $tpl->tpl_vars = &$this->tpl_vars;
$tpl->tpl_vars = &$scope_ptr->tpl_vars; $tpl->config_vars = &$this->config_vars;
} else {
$tpl->tpl_vars = &$scope_ptr->tpl_vars;
$tpl->config_vars = &$scope_ptr->$this->config_vars;
}
} }
$tpl->config_vars = $this->config_vars;
if (!empty($data)) { if (!empty($data)) {
// set up variable values // set up variable values
foreach ($data as $_key => $_val) { foreach ($data as $_key => $_val) {
$tpl->tpl_vars[$_key] = new Smarty_Variable($_val); $tpl->tpl_vars[$_key] = new Smarty_Variable($_val);
} }
} }
$tpl->tpl_function = $this->tpl_function;
return $tpl; return $tpl;
} }
@@ -570,7 +467,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
if (!isset($tpl->compiled)) { if (!isset($tpl->compiled)) {
$tpl->compiled = $this->compiled; $tpl->compiled = $this->compiled;
if ($tpl->compiled->includes[$tpl->source->type . ':' . $tpl->source->name] > 1) { if ($tpl->compiled->includes[$tpl->source->type . ':' . $tpl->source->name] > 1) {
$tpl->smarty->template_objects[$tpl->templateId] = $tpl; $tpl->cacheTpl(true);
} }
} }
if ($this->smarty->debugging) { if ($this->smarty->debugging) {
@@ -587,6 +484,21 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
} }
} }
/**
* Cache resources for current template
*
* @param bool $cache_tpl_obj force caching
*/
public function cacheTpl($cache_tpl_obj)
{
if (!$this->source->handler->recompiled && (isset($this->smarty->template_objects[$this->parent->templateId]) ||
($cache_tpl_obj && $this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC) ||
$this->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON)
) {
$this->smarty->->template_objects[$tpl->templateId] = $this;
}
}
/** /**
* Call template function * Call template function
* *

View File

@@ -74,6 +74,128 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
*/ */
public $cache_lifetime = 3600; public $cache_lifetime = 3600;
/**
* fetches a rendered Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @param bool $display not used - left for BC
* @param bool $merge_tpl_vars not used - left for BC
* @param bool $no_output_filter not used - left for BC
*
* @throws Exception
* @throws SmartyException
* @return string rendered template output
*/
public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $merge_tpl_vars = true, $no_output_filter = false)
{
$result = $this->_execute($template, $cache_id, $compile_id, $parent, 'fetch');
return $result === null ? ob_get_clean() : $result;
}
/**
* displays a Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
*/
public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
{
// display template
$this->_execute($template, $cache_id, $compile_id, $parent, 'display');
}
/**
* test if cache is valid
*
* @api Smarty::isCached()
* @link http://www.smarty.net/docs/en/api.is.cached.tpl
*
* @param null|string|\Smarty_Internal_Template $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
*
* @return boolean cache status
*/
public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)
{
return $this->_execute($template, $cache_id, $compile_id, $parent, 'isCached');
}
/**
* fetches a rendered Smarty template
*
* @param string $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
* @param string $function function name
*
* @return mixed
* @throws \Exception
* @throws \SmartyException
*/
private function _execute($template, $cache_id, $compile_id, $parent, $function)
{
/* @var Smarty $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;
}
} elseif (is_object($template)) {
if (!isset($template->_objType) || $template->_objType != 2) {
throw new SmartyException($function . '():Template object expected');
}
} else {
// get template object
/* @var Smarty_Internal_Template $template */
$template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
if ($this->_objType == 1) {
// set caching in template object
$template->caching = $this->caching;
}
}
// fetch template content
$level = ob_get_level();
try {
$_smarty_old_error_level = ($this->_objType == 1 &&
isset($smarty->error_reporting)) ? error_reporting($smarty->error_reporting) : null;
if ($function == 'isCached') {
if ($template->caching) {
// return cache status of template
if (!isset($template->cached)) {
$template->loadCached();
}
$result = $template->cached->isCached($template);
$template->smarty->_cache['isCached'][$template->templateId] = $template;
} else {
return false;
}
} else {
ob_start();
$result = $template->render(true, false, $function == 'display');
}
if (isset($_smarty_old_error_level)) {
error_reporting($_smarty_old_error_level);
}
return $result;
}
catch (Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
/** /**
* Registers plugin to be used in templates * Registers plugin to be used in templates
* NOTE: this method can be safely removed for dynamic loading * NOTE: this method can be safely removed for dynamic loading
@@ -233,40 +355,6 @@ abstract class Smarty_Internal_TemplateBase extends Smarty_Internal_Data
return $this; return $this;
} }
/**
* test if cache is valid
*
* @api Smarty::isCached()
* @link http://www.smarty.net/docs/en/api.is.cached.tpl
*
* @param string|\Smarty_Internal_Template $template the resource handle of the template file or template object
* @param mixed $cache_id cache id to be used with this template
* @param mixed $compile_id compile id to be used with this template
* @param object $parent next higher level of Smarty variables
*
* @return boolean cache status
*/
public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)
{
if ($template === null && $this instanceof $this->template_class) {
$template = $this;
} else {
if (!($template instanceof $this->template_class)) {
if ($parent === null) {
$parent = $this;
}
/* @var Smarty $smarty */
$smarty = isset($this->smarty) ? $this->smarty : $this;
$template = $smarty->createTemplate($template, $cache_id, $compile_id, $parent, false);
}
}
// return cache status of template
if (!isset($template->cached)) {
$template->loadCached();
}
return $template->cached->isCached($template);
}
/** /**
* @param boolean $caching * @param boolean $caching
*/ */

View File

@@ -997,7 +997,7 @@ abstract class Smarty_Internal_TemplateCompilerBase
// If the template is not evaluated and we have a nocache section and or a nocache tag // If the template is not evaluated and we have a nocache section and or a nocache tag
if ($is_code && !empty($content)) { if ($is_code && !empty($content)) {
// generate replacement code // generate replacement code
if ((!($this->template->source->recompiled) || $this->forceNocache) && $this->template->caching && if ((!($this->template->source->handler->recompiled) || $this->forceNocache) && $this->template->caching &&
!$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache) !$this->suppressNocacheProcessing && ($this->nocache || $this->tag_nocache)
) { ) {
$this->template->compiled->has_nocache_code = true; $this->template->compiled->has_nocache_code = true;

View File

@@ -42,6 +42,13 @@ abstract class Smarty_Resource
'eval' => 'smarty_internal_resource_eval.php', 'eval' => 'smarty_internal_resource_eval.php',
'php' => 'smarty_internal_resource_php.php'); 'php' => 'smarty_internal_resource_php.php');
/**
* Flag if resource does implement populateCompiledFilepath() method
*
* @var bool
*/
public $hasCompiledHandler = false;
/** /**
* Name of the Class to compile this resource's contents with * Name of the Class to compile this resource's contents with
* *
@@ -139,19 +146,14 @@ abstract class Smarty_Resource
public static function load(Smarty $smarty, $type) public static function load(Smarty $smarty, $type)
{ {
// try smarty's cache // try smarty's cache
if (isset($smarty->_resource_handlers[$type])) { if (isset($smarty->_cache['resource_handlers'][$type])) {
return $smarty->_resource_handlers[$type]; return $smarty->_cache['resource_handlers'][$type];
} }
// try registered resource // try registered resource
if (isset($smarty->registered_resources[$type])) { if (isset($smarty->registered_resources[$type])) {
if ($smarty->registered_resources[$type] instanceof Smarty_Resource) { return $smarty->_cache['resource_handlers'][$type] = $smarty->registered_resources[$type] instanceof
$smarty->_resource_handlers[$type] = $smarty->registered_resources[$type]; Smarty_Resource ? $smarty->registered_resources[$type] : new Smarty_Internal_Resource_Registered();
} else {
$smarty->_resource_handlers[$type] = new Smarty_Internal_Resource_Registered();
}
return $smarty->_resource_handlers[$type];
} }
// try sysplugins dir // try sysplugins dir
@@ -160,14 +162,14 @@ abstract class Smarty_Resource
if (!class_exists($_resource_class, false)) { if (!class_exists($_resource_class, false)) {
require SMARTY_SYSPLUGINS_DIR . self::$sysplugins[$type]; require SMARTY_SYSPLUGINS_DIR . self::$sysplugins[$type];
} }
return $smarty->_resource_handlers[$type] = new $_resource_class(); return $smarty->_cache['resource_handlers'][$type] = new $_resource_class();
} }
// try plugins dir // try plugins dir
$_resource_class = 'Smarty_Resource_' . ucfirst($type); $_resource_class = 'Smarty_Resource_' . ucfirst($type);
if ($smarty->loadPlugin($_resource_class)) { if ($smarty->loadPlugin($_resource_class)) {
if (class_exists($_resource_class, false)) { if (class_exists($_resource_class, false)) {
return $smarty->_resource_handlers[$type] = new $_resource_class(); return $smarty->_cache['resource_handlers'][$type] = new $_resource_class();
} else { } else {
$smarty->registerResource($type, array("smarty_resource_{$type}_source", $smarty->registerResource($type, array("smarty_resource_{$type}_source",
"smarty_resource_{$type}_timestamp", "smarty_resource_{$type}_timestamp",
@@ -185,7 +187,7 @@ abstract class Smarty_Resource
if (is_object($smarty->security_policy)) { if (is_object($smarty->security_policy)) {
$smarty->security_policy->isTrustedStream($type); $smarty->security_policy->isTrustedStream($type);
} }
return $smarty->_resource_handlers[$type] = new Smarty_Internal_Resource_Stream(); return $smarty->_cache['resource_handlers'][$type] = new Smarty_Internal_Resource_Stream();
} }
// TODO: try default_(template|config)_handler // TODO: try default_(template|config)_handler
@@ -229,23 +231,23 @@ abstract class Smarty_Resource
/** /**
* modify template_resource according to resource handlers specifications * modify template_resource according to resource handlers specifications
* *
* @param Smarty_Internal_template $template Smarty instance * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance
* @param string $template_resource template_resource to extract resource handler and name of * @param string $template_resource template_resource to extract resource handler and name of
* *
* @return string unique resource name * @return string unique resource name
*/ */
public static function getUniqueTemplateName($template, $template_resource) public static function getUniqueTemplateName($obj, $template_resource)
{ {
$smarty = isset($template->smarty) ? $template->smarty : $template; $smarty = $obj->_objType == 2 ? $obj->smarty : $obj;
list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type);
// TODO: optimize for Smarty's internal resource types // TODO: optimize for Smarty's internal resource types
$resource = Smarty_Resource::load($smarty, $type); $resource = Smarty_Resource::load($smarty, $type);
// go relative to a given template? // go relative to a given template?
$_file_is_dotted = $name[0] == '.' && ($name[1] == '.' || $name[1] == '/'); $_file_is_dotted = $name[0] == '.' && ($name[1] == '.' || $name[1] == '/');
if ($template instanceof Smarty_Internal_Template && $_file_is_dotted && if ($obj->_objType == 2 && $_file_is_dotted &&
($template->source->type == 'file' || $template->parent->source->type == 'extends') ($obj->source->type == 'file' || $obj->parent->source->type == 'extends')
) { ) {
$name = dirname($template->source->filepath) . DS . $name; $name = dirname($obj->source->filepath) . DS . $name;
} }
return $resource->buildUniqueResourceName($smarty, $name); return $resource->buildUniqueResourceName($smarty, $name);
} }

View File

@@ -23,6 +23,13 @@ abstract class Smarty_Resource_Recompiled extends Smarty_Resource
*/ */
public $recompiled = true; public $recompiled = true;
/**
* Resource does implement populateCompiledFilepath() method
*
* @var bool
*/
public $hasCompiledHandler = true;
/** /**
* populate Compiled Object with compiled filepath * populate Compiled Object with compiled filepath
* *

View File

@@ -23,6 +23,13 @@ abstract class Smarty_Resource_Uncompiled extends Smarty_Resource
*/ */
public $uncompiled = true; public $uncompiled = true;
/**
* Resource does implement populateCompiledFilepath() method
*
* @var bool
*/
public $hasCompiledHandler = true;
/** /**
* Render and output the template (without using the compiler) * Render and output the template (without using the compiler)
* *

View File

@@ -67,7 +67,7 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base
/** /**
* Nocache hash codes of processed compiled templates * Nocache hash codes of processed compiled templates
* *
* @var array * @var array
*/ */
public $hashes = array(); public $hashes = array();
@@ -106,6 +106,59 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base
return $_template->cached; return $_template->cached;
} }
/**
* Render cache template
*
* @param \Smarty_Internal_Template $_template
* @param bool $no_output_filter
*
* @throws \Exception
*/
public function render(Smarty_Internal_Template $_template, $no_output_filter = true)
{
if ($this->isCached($_template)) {
if ($_template->smarty->debugging) {
$_template->smarty->_debug->start_cache($_template);
}
if (!$this->processed) {
$this->process($_template);
}
$this->getRenderedTemplateCode($_template);
if ($_template->smarty->debugging) {
$_template->smarty->_debug->end_cache($_template);
}
return;
} elseif ($_template->source->handler->uncompiled) {
$_template->source->render($_template);
} else {
if (!isset($_template->compiled)) {
$_template->loadCompiled();
}
$_template->compiled->render($_template);
}
// write to cache when necessary
if ($_template->source->handler->recompiled) {
return;
}
if ($_template->smarty->debugging) {
$_template->smarty->_debug->start_cache($_template);
}
$_template->cached->updateCache($_template, $no_output_filter);
$compile_check = $_template->smarty->compile_check;
$_template->smarty->compile_check = false;
if (isset($this->parent) && $this->parent->_objType == 2) {
$_template->compiled->unifunc = $_template->parent->compiled->unifunc;
}
if (!$_template->cached->processed) {
$_template->cached->process($_template, true);
}
$_template->smarty->compile_check = $compile_check;
$this->getRenderedTemplateCode($_template);
if ($_template->smarty->debugging) {
$_template->smarty->_debug->end_cache($_template);
}
}
/** /**
* Check if cache is valid, lock cache if required * Check if cache is valid, lock cache if required
* *
@@ -202,22 +255,6 @@ class Smarty_Template_Cached extends Smarty_Template_Resource_Base
} }
} }
/**
* Render cached template
*
* @param Smarty_Internal_Template $_template
*
* @return string
* @throws Exception
*/
public function render(Smarty_Internal_Template $_template)
{
if (!$this->processed) {
$this->process($_template);
}
$_template->getRenderedTemplateCode($this->unifunc);
}
/** /**
* Write this cache object to handler * Write this cache object to handler
* *

View File

@@ -19,7 +19,6 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
*/ */
public $nocache_hash = null; public $nocache_hash = null;
/** /**
* create Compiled Object container * create Compiled Object container
*/ */
@@ -48,7 +47,7 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
} }
} }
$compiled = new Smarty_Template_Compiled(); $compiled = new Smarty_Template_Compiled();
if (method_exists($_template->source->handler, 'populateCompiledFilepath')) { if ($_template->source->handler->hasCompiledHandler) {
$_template->source->handler->populateCompiledFilepath($compiled, $_template); $_template->source->handler->populateCompiledFilepath($compiled, $_template);
} else { } else {
$compiled->populateCompiledFilepath($_template); $compiled->populateCompiledFilepath($_template);
@@ -199,17 +198,25 @@ class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
*/ */
public function render(Smarty_Internal_Template $_template) public function render(Smarty_Internal_Template $_template)
{ {
if ($_template->smarty->debugging) {
$_template->smarty->_debug->start_render($_template);
}
if (!$this->processed) { if (!$this->processed) {
$this->process($_template); $this->process($_template);
} }
if (isset($_template->cached)) { if (isset($_template->cached)) {
$_template->cached->file_dependency = array_merge($_template->cached->file_dependency, $this->file_dependency); $_template->cached->file_dependency = array_merge($_template->cached->file_dependency, $this->file_dependency);
} }
$_template->getRenderedTemplateCode($this->unifunc); $this->getRenderedTemplateCode($_template);
if ($_template->caching && $this->has_nocache_code) { if ($_template->caching && $this->has_nocache_code) {
$_template->cached->hashes[$this->nocache_hash] = true; $_template->cached->hashes[$this->nocache_hash] = true;
} }
if (isset($_template->parent) && $_template->parent->_objType == 2 && !empty($_template->tpl_function)) {
$_template->parent->tpl_function = array_merge($_template->parent->tpl_function, $_template->tpl_function);
}
if ($_template->smarty->debugging) {
$_template->smarty->_debug->end_render($_template);
}
} }
/** /**

View File

@@ -2,7 +2,6 @@
/** /**
* Smarty Template Resource Base Object * Smarty Template Resource Base Object
* Meta Data Container for Template Resource Files
* *
* @package Smarty * @package Smarty
* @subpackage TemplateResources * @subpackage TemplateResources
@@ -101,64 +100,50 @@ abstract class Smarty_Template_Resource_Base
*/ */
abstract public function process(Smarty_Internal_Template $_template); abstract public function process(Smarty_Internal_Template $_template);
/** /**
* render template code * get rendered template content by calling compiled or cached template code
* *
* @param Smarty_Internal_Template $_template * @param string $unifunc function with template code
* *
* @return string * @return string
* @throws Exception * @throws \Exception
*/ */
public function render(Smarty_Internal_Template $_template) public function getRenderedTemplateCode(Smarty_Internal_Template $_template, $unifunc = null)
{ {
$unifunc = isset($unifunc) ? $unifunc : $this->unifunc;
if (!$this->processed) { $level = ob_get_level();
$this->process($_template); try {
} if (empty($unifunc) || !is_callable($unifunc)) {
return $_template->getRenderedTemplateCode($this->unifunc); throw new SmartyException("Invalid compiled template for '{$_template->template_resource}'");
}
/**
* Write compiled code by handler
*
* @param Smarty_Internal_Template $_template template object
* @param string $code compiled code
*
* @return boolean success
*/
public function write(Smarty_Internal_Template $_template, $code)
{
if (!$_template->source->recompiled) {
$obj = new Smarty_Internal_Write_File();
if ($obj->writeFile($this->filepath, $code, $_template->smarty) === true) {
$this->timestamp = $this->exists = is_file($this->filepath);
if ($this->exists) {
$this->timestamp = filemtime($this->filepath);
return true;
}
} }
return false; if (isset($_template->smarty->security_policy)) {
} else { $_template->smarty->security_policy->startTemplate($_template);
$this->content = $code; }
array_unshift($_template->_capture_stack, array());
//
// render compiled or saved template code
//
$unifunc($_template);
// any unclosed {capture} tags ?
if (isset($_template->_capture_stack[0][0])) {
$_template->capture_error();
}
array_shift($_template->_capture_stack);
if (isset($_template->smarty->security_policy)) {
$_template->smarty->security_policy->exitTemplate();
}
return null;
} }
$this->timestamp = time(); catch (Exception $e) {
$this->exists = true; while (ob_get_level() > $level) {
return true; ob_end_clean();
} }
array_shift($_template->_capture_stack);
/** if (isset($_template->smarty->security_policy)) {
* Read compiled content from handler $_template->smarty->security_policy->exitTemplate();
* }
* @param Smarty_Internal_Template $_template template object throw $e;
*
* @return string content
*/
public function read(Smarty_Internal_Template $_template)
{
if (!$_template->source->recompiled) {
return file_get_contents($this->filepath);
} }
return isset($this->content) ? $this->content : false;
} }
/** /**

View File

@@ -251,6 +251,27 @@ class Smarty_Template_Source
$this->handler->renderUncompiled($_template->source, $_template); $this->handler->renderUncompiled($_template->source, $_template);
} }
/**
* Render uncompiled source
*
* @param \Smarty_Internal_Template $_template
*/
public function render(Smarty_Internal_Template $_template)
{
if ($_template->source->handler->uncompiled) {
if ($_template->smarty->debugging) {
$_template->smarty->_debug->start_render($_template);
}
$this->handler->renderUncompiled($_template->source, $_template);
if (isset($_template->parent) && $_template->parent->_objType == 2 && !empty($_template->tpl_function)) {
$_template->parent->tpl_function = array_merge($_template->parent->tpl_function, $_template->tpl_function);
}
if ($_template->smarty->debugging) {
$_template->smarty->_debug->end_render($_template);
}
}
}
/** /**
* Get source time stamp * Get source time stamp
* *