Re-organized rendering (read source / compile / cache) process to avoid circular dependencies.

Deactivated merge_compiled_includes and the {include inline} attribute. They don't seem to do much in terms of performance, but we'll
have to check back.
This commit is contained in:
Simon Wisselink
2023-01-25 16:59:10 +01:00
parent 46dfed3837
commit 169cd924df
18 changed files with 213 additions and 374 deletions

View File

@@ -7,18 +7,8 @@ use Smarty\Smarty;
use Smarty\Template;
use Smarty\Template\Cached;
/**
* Smarty Internal Plugin
*
*/
/**
* Cache Handler API
*
* @author Rodney Rehm
*/
abstract class Base

View File

@@ -62,7 +62,7 @@ class File extends Base
$_filepath[ 4 ] . $_filepath[ 5 ] . DIRECTORY_SEPARATOR;
}
$cached->filepath .= $_filepath;
$basename = $source->handler->getBasename($source);
$basename = $source->getBasename();
if (!empty($basename)) {
$cached->filepath .= '.' . $basename;
}
@@ -105,7 +105,7 @@ class File extends Base
Cached $cached = null,
$update = false
) {
$_smarty_tpl->getCached()->valid = false;
$_smarty_tpl->getCached()->setValid(false);
if ($update && defined('HHVM_VERSION')) {
eval('?>' . file_get_contents($_smarty_tpl->getCached()->filepath));
return true;

View File

@@ -100,21 +100,10 @@ class ExtendsTag extends Inheritance {
* @throws \Smarty\Exception
*/
private function compileEndChild(\Smarty\Compiler\Template $compiler, $template = null) {
$inlineUids = '';
if (isset($template) && $compiler->getSmarty()->merge_compiled_includes) {
$code = $compiler->compileTag('include', [$template, ['scope' => 'parent']]);
// @TODO this relies on the generated code to have a certain format and is sure to break someday
if (preg_match('/(,\s*\'[a-z0-9]+\',\s*\'content.*\')/', $code, $match)) {
$inlineUids = $match[1];
}
}
$compiler->getParser()->template_postfix[] = new \Smarty\ParseTree\Tag(
$compiler->getParser(),
'<?php $_smarty_tpl->getInheritance()->endChild($_smarty_tpl' .
(isset($template) ?
", {$template}{$inlineUids}" :
'') . ");\n?>"
(isset($template) ? ", {$template}" : '') . ");\n?>"
);
}

View File

@@ -100,11 +100,6 @@ class IncludeTag extends Base {
$fullResourceName = $match[1] . $fullResourceName . $match[1];
}
}
if (empty($match[5])) {
$variable_template = true;
}
} else {
$variable_template = true;
}
// scope setup
$_scope = isset($_attr['scope']) ? $this->convertScope($_attr['scope']) : 0;
@@ -118,16 +113,6 @@ class IncludeTag extends Base {
$_caching = \Smarty\Template::CACHING_NOCACHE_CODE;
}
// flag if included template code should be merged into caller
$merge_compiled_includes = ($compiler->getSmarty()->merge_compiled_includes || $_attr['inline'] === true) &&
!$compiler->getTemplate()->getSource()->handler->recompiled;
if ($merge_compiled_includes) {
// variable template name ?
if ($variable_template) {
$merge_compiled_includes = false;
}
}
/*
* if the {include} tag provides individual parameter for caching or compile_id
* the subtemplate must not be included into the common cache file and is treated like
@@ -157,10 +142,6 @@ class IncludeTag extends Base {
$_cache_id = '$_smarty_tpl->cache_id';
}
// if subtemplate will be called in nocache mode do not merge
if ($compiler->getTemplate()->caching && $call_nocache) {
$merge_compiled_includes = false;
}
// assign attribute
if (isset($_attr['assign'])) {
// output will be stored in a smarty variable instead of being displayed
@@ -175,30 +156,7 @@ class IncludeTag extends Base {
}
}
$has_compiled_template = false;
if ($merge_compiled_includes) {
$c_id = $compiler->getTemplate()->compile_id;
// we must observe different compile_id and caching
$t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching'));
$compiler->getSmarty()->setAllowAmbiguousResources(true);
$tpl = $compiler->getSmarty()->createTemplate(
trim($fullResourceName, '"\''),
$compiler->getTemplate()->cache_id,
$c_id,
$compiler->getTemplate(),
$_caching
);
$uid = $tpl->getSource()->type . $tpl->getSource()->uid;
if (!isset($compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash])) {
$has_compiled_template = $this->compileInlineTemplate($compiler, $tpl, $t_hash);
} else {
$has_compiled_template = true;
}
$compiler->getSmarty()->setAllowAmbiguousResources(false);
}
// delete {include} standard attributes
unset($_attr['file'], $_attr['assign'], $_attr['cache_id'], $_attr['cache_lifetime'], $_attr['nocache'], $_attr['caching'], $_attr['scope'], $_attr['inline']);
// remaining attributes must be assigned as smarty variable
@@ -211,27 +169,6 @@ class IncludeTag extends Base {
}
$_vars = 'array(' . join(',', $_pairs) . ')';
}
if ($has_compiled_template && !$call_nocache) {
$_output = "<?php\n";
if (!empty($_attr) && $_caching === \Smarty\Template::CACHING_NOCACHE_CODE && $compiler->getTemplate()->caching) {
$_vars_nc = "foreach ($_vars as \$ik => \$iv) {\n";
$_vars_nc .= "\$_smarty_tpl->assign(\$ik, \$iv);\n";
$_vars_nc .= "}\n";
$_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n"), 6, -3);
}
if (isset($_assign)) {
$_output .= "ob_start();\n";
}
$_output .= "\$_smarty_tpl->renderSubTemplate({$fullResourceName}, {$_cache_id}, \$_smarty_tpl->compile_id, " .
"{$_caching}, {$_cache_lifetime}, {$_vars}, " .
"'{$compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash]['uid']}', " .
"'{$compiler->getParentCompiler()->mergedSubTemplatesData[$uid][$t_hash]['func']}', (int) {$_scope});\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean(), false, {$_scope});\n";
}
$_output .= "?>";
return $_output;
}
if ($call_nocache) {
$compiler->tag_nocache = true;
}
@@ -241,7 +178,7 @@ class IncludeTag extends Base {
$_output .= "ob_start();\n";
}
$_output .= "\$_smarty_tpl->renderSubTemplate({$fullResourceName}, $_cache_id, \$_smarty_tpl->compile_id, " .
"$_caching, $_cache_lifetime, $_vars, null, null, (int) {$_scope});\n";
"$_caching, $_cache_lifetime, $_vars, (int) {$_scope});\n";
if (isset($_assign)) {
$_output .= "\$_smarty_tpl->assign({$_assign}, ob_get_clean(), false, {$_scope});\n";
}
@@ -280,7 +217,7 @@ class IncludeTag extends Base {
if ($tplSource->type === 'file') {
$sourceInfo = $tplSource->filepath;
} else {
$basename = $tplSource->handler->getBasename($tplSource);
$basename = $tplSource->getBasename();
$sourceInfo = $tplSource->type . ':' .
($basename ? $basename : $tplSource->name);
}

View File

@@ -400,7 +400,7 @@ class Template extends BaseCompiler {
$this->has_variable_string = false;
$this->prefix_code = [];
// add file dependency
if ($this->smarty->merge_compiled_includes || $this->template->getSource()->handler->checkTimestamps()) {
if ($this->template->getSource()->handler->checkTimestamps()) {
$this->parent_compiler->getTemplate()->getCompiled()->file_dependency[$this->template->getSource()->uid] =
[
$this->template->getSource()->filepath,

View File

@@ -2,12 +2,14 @@
namespace Smarty\Resource;
use Smarty\Exception;
use Smarty\Smarty;
use Smarty\Template;
use Smarty\Template\Source;
/**
* Smarty Resource Plugin
* Base implementation for resource plugins
* @method process(\Smarty\Template $_smarty_tpl)
* @author Rodney Rehm
*/
abstract class BasePlugin
@@ -41,15 +43,25 @@ abstract class BasePlugin
return true;
}
/**
* Load Resource Handler
*
* @param \Smarty $smarty smarty object
* @param string $type name of the resource
*
* @return BasePlugin Resource Handler
*@throws \Smarty\Exception
*/
/**
* Check if resource must check time stamps when loading compiled or cached templates.
* Resources like 'extends' which use source components my disable timestamp checks on own resource.
* @return bool
*/
public function checkTimestamps()
{
return true;
}
/**
* Load Resource Handler
*
* @param Smarty $smarty smarty object
* @param string $type name of the resource
*
* @return BasePlugin Resource Handler
* @throws Exception
*/
public static function load(Smarty $smarty, $type)
{
// try smarty's cache
@@ -108,77 +120,50 @@ abstract class BasePlugin
return array($name, $type);
}
/**
* initialize Source Object for given resource
* wrapper for backward compatibility to versions < 3.1.22
* Either [$_template] or [$smarty, $template_resource] must be specified
*
* @param \Smarty\Template $_template template object
* @param \Smarty $smarty smarty object
* @param string $template_resource resource identifier
*
* @return \Smarty\Template\Source Source Object
* @throws \Smarty\Exception
*/
public static function source(
\Smarty\Template $_template = null,
\Smarty\Smarty $smarty = null,
$template_resource = null
) {
return \Smarty\Template\Source::load($_template, $smarty, $template_resource);
}
/**
* Load template's source into current template object
*
* @param \Smarty\Template\Source $source source object
* @param Source $source source object
*
* @return string template source
* @throws \Smarty\Exception if source cannot be loaded
*/
abstract public function getContent(\Smarty\Template\Source $source);
abstract public function getContent(Source $source);
/**
* populate Source Object with meta data from Resource
*
* @param \Smarty\Template\Source $source source object
* @param \Smarty\Template $_template template object
*/
abstract public function populate(\Smarty\Template\Source $source, \Smarty\Template $_template = null);
/**
* populate Source Object with metadata from Resource
*
* @param Source $source source object
* @param Template|null $_template template object
*/
abstract public function populate(Source $source, \Smarty\Template $_template = null);
/**
* populate Source Object with timestamp and exists from Resource
*
* @param \Smarty\Template\Source $source source object
* @param Source $source source object
*/
public function populateTimestamp(\Smarty\Template\Source $source)
public function populateTimestamp(Source $source)
{
// intentionally left blank
}
/*
* Check if resource must check time stamps when when loading complied or cached templates.
* Resources like 'extends' which use source components my disable timestamp checks on own resource.
*
* @return bool
*/
/**
* Determine basename for compiled filename
*
* @param \Smarty\Template\Source $source source object
*
* @return string resource's basename
*/
public function getBasename(\Smarty\Template\Source $source)
{
return basename(preg_replace('![^\w]+!', '_', $source->name));
}
/*
* Check if resource must check time stamps when when loading complied or cached templates.
* Resources like 'extends' which use source components my disable timestamp checks on own resource.
*
* @return bool
*/
/**
* Determine basename for compiled filename
*
* @param \Smarty\Template\Source $source source object
*
* @return string resource's basename
*/
public function getBasename(\Smarty\Template\Source $source)
{
return basename(preg_replace('![^\w]+!', '_', $source->name));
}
/**
* @return bool
*/
public function checkTimestamps()
{
return true;
}
}

View File

@@ -8,19 +8,9 @@ use Smarty\Template\Source;
/**
* Smarty Internal Plugin Resource Extends
*
* Implements the file system as resource for Smarty which {extend}s a chain of template files templates
* @author Uwe Tews
* @author Rodney Rehm
*/
/**
* Smarty Internal Plugin Resource Extends
* Implements the file system as resource for Smarty which {extend}s a chain of template files templates
*
*/
class ExtendsPlugin extends BasePlugin
{

View File

@@ -9,9 +9,7 @@
namespace Smarty\Resource;
use Smarty\Smarty;
use Smarty\Template;
use Smarty\Template\Compiled;
/**
* Smarty Resource Plugin
@@ -45,7 +43,7 @@ abstract class RecompiledPlugin extends BasePlugin {
*
* @throws Exception
*/
public function process(Template $_smarty_tpl) {
public function recompile(Template $_smarty_tpl) {
$compiled = $_smarty_tpl->getCompiled();
$compiled->file_dependency = [];
$compiled->includes = [];

View File

@@ -40,13 +40,6 @@ class CaptureRuntime {
*/
private $namedBuffer = [];
/**
* Flag if callbacks are registered
*
* @var bool
*/
private $isRegistered = false;
/**
* Open capture section
*
@@ -56,9 +49,9 @@ class CaptureRuntime {
* @param string $append variable name
*/
public function open(Template $_template, $buffer, $assign, $append) {
if (!$this->isRegistered) {
$this->register($_template);
}
$this->registerCallbacks($_template);
$this->captureStack[] = [
$buffer,
$assign,
@@ -73,7 +66,15 @@ class CaptureRuntime {
*
* @param \Smarty\Template $_template
*/
private function register(Template $_template) {
private function registerCallbacks(Template $_template) {
foreach ($_template->startRenderCallbacks as $callback) {
if (is_array($callback) && get_class($callback[0]) == self::class) {
// already registered
return;
}
}
$_template->startRenderCallbacks[] = [
$this,
'startRender',
@@ -83,7 +84,6 @@ class CaptureRuntime {
'endRender',
];
$this->startRender($_template);
$this->isRegistered = true;
}
/**

View File

@@ -85,8 +85,6 @@ class InheritanceRuntime {
ob_start();
}
++$this->inheritanceLevel;
// $tpl->startRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateStart');
// $tpl->endRenderCallbacks[ 'inheritance' ] = array($this, 'subTemplateEnd');
}
// if state was waiting for parent change state to parent
if ($this->state === 2) {
@@ -100,13 +98,11 @@ class InheritanceRuntime {
*
* @param \Smarty\Template $tpl
* @param null|string $template optional name of inheritance parent template
* @param null|string $uid uid of inline template
* @param null|string $func function call name of inline template
*
* @throws \Exception
* @throws \Smarty\Exception
*/
public function endChild(Template $tpl, $template = null, $uid = null, $func = null) {
public function endChild(Template $tpl, $template = null) {
--$this->inheritanceLevel;
if (!$this->inheritanceLevel) {
ob_end_clean();
@@ -118,10 +114,7 @@ class InheritanceRuntime {
$tpl->cache_id,
$tpl->compile_id,
$tpl->caching ? \Smarty\Template::CACHING_NOCACHE_CODE : 0,
$tpl->cache_lifetime,
[],
$uid,
$func
$tpl->cache_lifetime
);
}
}
@@ -151,7 +144,7 @@ class InheritanceRuntime {
while ($block->child && $block->child->child && $block->tplIndex <= $block->child->tplIndex) {
$block->child = $block->child->child;
}
$this->process($tpl, $block);
$this->processBlock($tpl, $block);
}
/**
@@ -163,7 +156,7 @@ class InheritanceRuntime {
*
* @throws Exception
*/
private function process(
private function processBlock(
Template $tpl,
\Smarty\Runtime\Block $block,
\Smarty\Runtime\Block $parent = null
@@ -181,7 +174,7 @@ class InheritanceRuntime {
if ($block->callsChild || !isset($block->child) || ($block->child->hide && !isset($block->child->child))) {
$this->callBlock($block, $tpl);
} else {
$this->process($tpl, $block->child, $block);
$this->processBlock($tpl, $block->child, $block);
}
if ($block->prepend && isset($parent)) {
$this->callParent($tpl, $block, '{block prepend}');
@@ -191,7 +184,7 @@ class InheritanceRuntime {
) {
$this->callBlock($block, $tpl);
} else {
$this->process($tpl, $block->child, $block);
$this->processBlock($tpl, $block->child, $block);
}
}
}
@@ -209,7 +202,7 @@ class InheritanceRuntime {
*/
public function callChild(Template $tpl, \Smarty\Runtime\Block $block) {
if (isset($block->child)) {
$this->process($tpl, $block->child, $block);
$this->processBlock($tpl, $block->child, $block);
}
}

View File

@@ -70,13 +70,6 @@ class Template extends TemplateBase {
*/
public $templateId = null;
/**
* Flag which is set while rending a cache file
*
* @var bool
*/
public $isRenderingCache = false;
/**
* Callbacks called before rendering template
*
@@ -161,7 +154,7 @@ class Template extends TemplateBase {
* @throws \Exception
* @throws \Smarty\Exception
*/
public function render($no_output_filter = true, $display = null) {
private function render($no_output_filter = true, $display = null) {
if ($this->smarty->debugging) {
$this->smarty->getDebug()->start_template($this, $display);
}
@@ -172,23 +165,38 @@ class Template extends TemplateBase {
($this->_isSubTpl() ? " in '{$this->parent->template_resource}'" : '')
);
}
// disable caching for evaluated code
if ($this->getSource()->handler->recompiled) {
$this->caching = \Smarty\Smarty::CACHING_OFF;
}
// read from cache or render
if ($this->caching === \Smarty\Smarty::CACHING_LIFETIME_CURRENT || $this->caching === \Smarty\Smarty::CACHING_LIFETIME_SAVED) {
if ($this->getCached()->cache_id !== $this->cache_id || $this->getCached()->compile_id !== $this->compile_id) {
$this->getCached(true);
}
$this->getCached()->render($this, $no_output_filter);
} else {
$compiled = $this->getCompiled();
if ($compiled->compile_id !== $this->compile_id) {
$compiled = $this->getCompiled(true);
}
$compiled->render($this);
foreach ($this->startRenderCallbacks as $callback) {
call_user_func($callback, $this);
}
try {
// read from cache or render
if ($this->caching === \Smarty\Smarty::CACHING_LIFETIME_CURRENT || $this->caching === \Smarty\Smarty::CACHING_LIFETIME_SAVED) {
if ($this->getCached()->cache_id !== $this->cache_id || $this->getCached()->compile_id !== $this->compile_id) {
$this->getCached(true);
}
$this->getCached()->render($this, $no_output_filter);
} else {
$compiled = $this->getCompiled();
if ($compiled->compile_id !== $this->compile_id) {
$compiled = $this->getCompiled(true);
}
$compiled->render($this);
}
} finally {
foreach ($this->endRenderCallbacks as $callback) {
call_user_func($callback, $this);
}
}
// display or fetch
if ($display) {
if ($this->caching && $this->smarty->cache_modified_check) {
@@ -240,8 +248,6 @@ class Template extends TemplateBase {
* @param integer $caching cache mode
* @param integer $cache_lifetime lifetime of cache data
* @param array $extra_vars passed parameter template variables
* @param null $uid file dependency uid
* @param null $content_func function name
* @param int|null $scope
*
* @throws Exception
@@ -252,9 +258,7 @@ class Template extends TemplateBase {
$compile_id,
$caching,
$cache_lifetime,
array $extra_vars,
$uid = null,
$content_func = null,
array $extra_vars = [],
int $scope = null
) {
@@ -270,22 +274,10 @@ class Template extends TemplateBase {
// recursive call ?
if ($tpl->getTemplateId() !== $this->getTemplateId()) {
if (isset($uid) && $this->getCompiled()->file_dependency) {
// for inline templates we can get all resource information from file dependency
[$filepath, $timestamp, $type] = $this->getCompiled()->file_dependency[$uid];
$source = new Source($this->getSmarty(), $filepath, $type, $filepath);
$source->filepath = $filepath;
$source->timestamp = $timestamp;
$source->exists = true;
$source->uid = $uid;
$tpl->setSource($source);
} else {
$tpl->setSource(Source::load($tpl));
$tpl->getCompiled(true); // @TODO this unset($tpl->compiled), there might be a bug here
}
$tpl->setSource(Source::load($tpl));
$tpl->getCompiled(true);
if ($caching !== \Smarty\Template::CACHING_NOCACHE_CODE) {
$tpl->getCached(true); // @TODO this unset($tpl->cached), there might be a bug here
$tpl->getCached(true);
}
}
@@ -300,20 +292,8 @@ class Template extends TemplateBase {
$this->getCached()->hashes[$tpl->getCompiled()->nocache_hash] = true;
}
}
if (isset($uid)) {
$smarty = $this->getSmarty();
if ($smarty->debugging) {
$smarty->getDebug()->start_template($tpl);
$smarty->getDebug()->start_render($tpl);
}
$tpl->getRenderedTemplateCode($content_func);
if ($smarty->debugging) {
$smarty->getDebug()->end_template($tpl);
$smarty->getDebug()->end_render($tpl);
}
} else {
$tpl->render();
}
$tpl->render();
}
/**
@@ -326,7 +306,7 @@ class Template extends TemplateBase {
}
public function assign($tpl_var, $value = null, $nocache = false, $scope = null) {
return parent::assign($tpl_var, $value, $nocache || $this->isRenderingCache, $scope);
return parent::assign($tpl_var, $value, $nocache, $scope);
}
/**
@@ -388,7 +368,7 @@ class Template extends TemplateBase {
$is_valid = false;
}
$this->getCached()->cache_lifetime = $properties['cache_lifetime'];
$this->getCached()->valid = $is_valid;
$this->getCached()->setValid($is_valid);
$generatedFile = $this->getCached();
} else {
$this->mustCompile = !$is_valid;
@@ -429,6 +409,8 @@ class Template extends TemplateBase {
* @param string $content
*
* @return bool
*
* @TODO this method is only used in unit tests that (mostly) try to test CacheResources.
*/
public function writeCachedContent($content) {
if ($this->getSource()->handler->recompiled || !$this->caching
@@ -495,7 +477,7 @@ class Template extends TemplateBase {
return $this->cached;
}
public function isCachingEnabled(): bool {
private function isCachingEnabled(): bool {
return $this->caching && !$this->getSource()->handler->recompiled;
}
@@ -523,14 +505,6 @@ class Template extends TemplateBase {
$this->inheritance = $inheritanceRuntime;
}
/**
* Unload event callbacks
*/
private function _cleanUp() {
$this->startRenderCallbacks = [];
$this->endRenderCallbacks = [];
}
/**
* Return Compiler object
*/
@@ -745,7 +719,6 @@ class Template extends TemplateBase {
$result = $this->render(false, $function);
// Restore the template to its previous state
$this->_cleanUp();
$this->tpl_vars = $savedTplVars;
$this->config_vars = $savedConfigVars;
}
@@ -773,41 +746,6 @@ class Template extends TemplateBase {
}
}
/**
* get rendered template content by calling compiled or cached template code
*
* @param string $unifunc function with template code
*
* @throws \Exception
*/
public function getRenderedTemplateCode($unifunc) {
$level = ob_get_level();
try {
if (empty($unifunc) || !function_exists($unifunc)) {
throw new \Smarty\Exception("Invalid compiled template for '{$this->template_resource}'");
}
if ($this->startRenderCallbacks) {
foreach ($this->startRenderCallbacks as $callback) {
call_user_func($callback, $this);
}
}
$unifunc($this);
foreach ($this->endRenderCallbacks as $callback) {
call_user_func($callback, $this);
}
$this->isRenderingCache = false;
} catch (\Exception $e) {
$this->isRenderingCache = false;
while (ob_get_level() > $level) {
ob_end_clean();
}
if (isset($this->getSmarty()->security_policy)) {
$this->getSmarty()->security_policy->endTemplate();
}
throw $e;
}
}
/**
* @return Config|Source|null
*/

View File

@@ -5,6 +5,7 @@ namespace Smarty\Template;
use Smarty\Exception;
use Smarty\Template;
use Smarty\Template\Cacheresource\Base;
use Smarty\Template\Compiler\CodeFrame;
/**
* Represents a cached version of a template or config file.
@@ -17,14 +18,7 @@ class Cached extends GeneratedPhpFile {
*
* @var boolean
*/
public $valid = null;
/**
* @return bool|null
*/
public function getValid(): ?bool {
return $this->valid;
}
private $valid = null;
/**
* @param bool|null $valid
@@ -89,11 +83,6 @@ class Cached extends GeneratedPhpFile {
*/
public $content = null;
private function renderTemplateCode(Template $_template) {
$_template->isRenderingCache = true;
$_template->getRenderedTemplateCode($this->unifunc);
}
/**
* create Cached Object container
*
@@ -118,21 +107,25 @@ class Cached extends GeneratedPhpFile {
* @throws \Exception
*/
public function render(Template $_template, $no_output_filter = true) {
if ($this->isCached($_template)) {
if ($_template->getSmarty()->debugging) {
$_template->getSmarty()->getDebug()->start_cache($_template);
}
if (!$this->isCached($_template)) {
$this->updateCache($_template, $no_output_filter);
} else {
if (!$this->processed) {
$this->process($_template);
}
$this->renderTemplateCode($_template);
if ($_template->getSmarty()->debugging) {
$_template->getSmarty()->getDebug()->end_cache($_template);
}
return;
} else {
$this->updateCache($_template, $no_output_filter);
}
if ($_template->getSmarty()->debugging) {
$_template->getSmarty()->getDebug()->start_cache($_template);
}
$this->getRenderedTemplateCode($_template, $this->unifunc);
if ($_template->getSmarty()->debugging) {
$_template->getSmarty()->getDebug()->end_cache($_template);
}
}
/**
@@ -283,23 +276,30 @@ class Cached extends GeneratedPhpFile {
* @throws \Smarty\Exception
*/
private function updateCache(Template $_template, $no_output_filter) {
ob_start();
$_template->getCompiled()->render($_template);
if ($_template->getSmarty()->debugging) {
$_template->getSmarty()->getDebug()->start_cache($_template);
}
$this->removeNoCacheHash($_template, $no_output_filter);
$compile_check = (int)$_template->compile_check;
$_template->compile_check = \Smarty\Smarty::COMPILECHECK_OFF;
if ($_template->_isSubTpl()) {
$_template->getCompiled()->unifunc = $_template->parent->getCompiled()->unifunc;
}
if (!$_template->getCached()->processed) {
$_template->getCached()->process($_template, true);
if (!$this->processed) {
$this->process($_template, true);
}
$_template->compile_check = $compile_check;
$this->renderTemplateCode($_template);
if ($_template->getSmarty()->debugging) {
$_template->getSmarty()->getDebug()->end_cache($_template);
}
@@ -367,8 +367,9 @@ class Cached extends GeneratedPhpFile {
) {
$content = $_template->getSmarty()->runOutputFilters($content, $_template);
}
// write cache file content
$_template->writeCachedContent($content);
$codeframe = (new \Smarty\Compiler\CodeFrame($_template))->create($content, '', true);
$this->writeCache($_template, $codeframe);
}
/**

View File

@@ -65,11 +65,10 @@ class Compiled extends GeneratedPhpFile {
$this->filepath .= (int)$smarty->config_read_hidden + (int)$smarty->config_booleanize * 2 +
(int)$smarty->config_overwrite * 4;
} else {
$this->filepath .= (int)$smarty->merge_compiled_includes + (int)$smarty->escape_html * 2 +
(($smarty->merge_compiled_includes && $source->type === 'extends') ? 4 : 0);
$this->filepath .= (int)$smarty->escape_html * 2;
}
$this->filepath .= '.' . $source->type;
$basename = $source->handler->getBasename($source);
$basename = $source->getBasename();
if (!empty($basename)) {
$this->filepath .= '.' . $basename;
}
@@ -101,13 +100,13 @@ class Compiled extends GeneratedPhpFile {
$_template->getSmarty()->getDebug()->start_render($_template);
}
if (!$this->processed) {
$this->process($_template);
$this->compileAndLoad($_template);
}
$_template->getCached()->file_dependency =
array_merge($_template->getCached()->file_dependency, $this->file_dependency);
$_template->getRenderedTemplateCode($this->unifunc);
$this->getRenderedTemplateCode($_template, $this->unifunc);
if ($_template->caching && $this->getNocacheCode()) {
$_template->getCached()->hashes[$this->nocache_hash] = true;
@@ -124,29 +123,23 @@ class Compiled extends GeneratedPhpFile {
*
* @throws Exception
*/
private function process(Template $_smarty_tpl) {
private function compileAndLoad(Template $_smarty_tpl) {
$source = $_smarty_tpl->getSource();
$smarty = $_smarty_tpl->getSmarty();
if ($source->handler->recompiled) {
$source->handler->process($_smarty_tpl);
$source->handler->recompile($_smarty_tpl); // @TODO who is compiling here?
} else {
if (!$this->exists || $smarty->force_compile
|| ($_smarty_tpl->compile_check && $source->getTimeStamp() > $this->getTimeStamp())
) {
$this->compileTemplateSource($_smarty_tpl);
$compileCheck = $_smarty_tpl->compile_check;
$_smarty_tpl->compile_check = \Smarty\Smarty::COMPILECHECK_OFF;
$this->loadCompiledTemplate($_smarty_tpl);
$_smarty_tpl->compile_check = $compileCheck;
} else {
$_smarty_tpl->mustCompile = true;
@include $this->filepath;
if ($_smarty_tpl->mustCompile) {
$this->compileTemplateSource($_smarty_tpl);
$compileCheck = $_smarty_tpl->compile_check;
$_smarty_tpl->compile_check = \Smarty\Smarty::COMPILECHECK_OFF;
$this->loadCompiledTemplate($_smarty_tpl);
$_smarty_tpl->compile_check = $compileCheck;
}
}
$this->processed = true;
@@ -192,7 +185,7 @@ class Compiled extends GeneratedPhpFile {
* @return bool success
* @throws \Smarty\Exception
*/
public function write(Template $_template, $code) {
private function write(Template $_template, $code) {
if (!$_template->getSource()->handler->recompiled) {
if ($_template->getSmarty()->writeFile($this->filepath, $code) === true) {
$this->timestamp = $this->exists = is_file($this->filepath);
@@ -206,20 +199,6 @@ class Compiled extends GeneratedPhpFile {
return true;
}
/**
* Read compiled content from handler
*
* @param Template $_template template object
*
* @return string content
*/
public function read(Template $_template) {
if (!$_template->getSource()->handler->recompiled) {
return file_get_contents($this->filepath);
}
return false;
}
/**
* Load fresh compiled template by including the PHP file
* HHVM requires a workaround because of a PHP incompatibility
@@ -227,6 +206,8 @@ class Compiled extends GeneratedPhpFile {
* @param \Smarty\Template $_smarty_tpl do not change variable name, is used by compiled template
*/
private function loadCompiledTemplate(Template $_smarty_tpl) {
$compileCheck = $_smarty_tpl->compile_check;
$_smarty_tpl->compile_check = \Smarty\Smarty::COMPILECHECK_OFF;
if (function_exists('opcache_invalidate')
&& (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1)
) {
@@ -239,6 +220,7 @@ class Compiled extends GeneratedPhpFile {
} else {
include $this->filepath;
}
$_smarty_tpl->compile_check = $compileCheck;
}
}

View File

@@ -41,7 +41,7 @@ abstract class GeneratedPhpFile {
*
* @var boolean
*/
public $processed = false;
protected $processed = false;
/**
* unique function name for compiled template code
@@ -90,4 +90,27 @@ abstract class GeneratedPhpFile {
$this->has_nocache_code = $has_nocache_code;
}
/**
* get rendered template content by calling compiled or cached template code
*
* @param string $unifunc function with template code
*
* @throws \Exception
*/
protected function getRenderedTemplateCode(\Smarty\Template $_template, $unifunc) {
$level = ob_get_level();
try {
if (empty($unifunc) || !function_exists($unifunc)) {
throw new \Smarty\Exception("Invalid compiled template for '{$this->filepath}'");
}
$unifunc($_template);
} catch (\Exception $e) {
while (ob_get_level() > $level) {
ob_end_clean();
}
throw $e;
}
}
}

View File

@@ -234,4 +234,14 @@ class Source {
return $this->smarty;
}
/**
* Determine basename for compiled filename
*
* @return string resource's basename
*/
public function getBasename()
{
return $this->handler->getBasename($this);
}
}

View File

@@ -7,7 +7,7 @@ use Smarty\Template\Source;
class Smarty_Resource_FiletestPlugin extends FilePlugin
{
/**
* populate Source Object with meta data from Resource
* populate Source Object with metadata from Resource
*
* @param Source $source source object
* @param Template $_template template object

View File

@@ -17,20 +17,22 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
*
* @var Memcache
*/
protected $memcache = null;
private $memcache = null;
/**
* Smarty_CacheResource_Memcache constructor.
*/
public function __construct()
{
if (class_exists('Memcached')) {
$this->memcache = new Memcached();
} else {
$this->memcache = new Memcache();
}
$this->memcache->addServer('127.0.0.1', 11211);
}
/**
* @return Memcache|Memcached
*/
public function getMemcache() {
if ($this->memcache === null) {
if (class_exists('Memcached')) {
$this->memcache = new Memcached();
} else {
$this->memcache = new Memcache();
}
$this->memcache->addServer('127.0.0.1', 11211);
}
return $this->memcache;
}
/**
* Read values for a set of keys from cache
@@ -45,7 +47,7 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
$res = array();
foreach ($keys as $key) {
$k = sha1($key);
$res[$key] = $this->memcache->get($k);
$res[$key] = $this->getMemcache()->get($k);
}
return $res;
}
@@ -63,9 +65,9 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
foreach ($keys as $k => $v) {
$k = sha1($k);
if (class_exists('Memcached')) {
$this->memcache->set($k, $v, $expire);
$this->getMemcache()->set($k, $v, $expire);
} else {
$this->memcache->set($k, $v, 0, $expire);
$this->getMemcache()->set($k, $v, 0, $expire);
}
}
return true;
@@ -82,7 +84,7 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
{
foreach ($keys as $k) {
$k = sha1($k);
$this->memcache->delete($k);
$this->getMemcache()->delete($k);
}
return true;
}
@@ -94,6 +96,6 @@ class Smarty_CacheResource_Memcache extends \Smarty\Cacheresource\KeyValueStore
*/
protected function purge()
{
return $this->memcache->flush();
return $this->getMemcache()->flush();
}
}

View File

@@ -29,7 +29,8 @@ class My_Resource_Extendsall extends \Smarty\Resource\ExtendsPlugin
$timestamp = 0;
foreach ($source->getSmarty()->getTemplateDir() as $key => $directory) {
try {
$s = Smarty\Resource\BasePlugin::source(null, $source->getSmarty(), 'file:' . '[' . $key . ']' . $source->name);
$s = \Smarty\Template\Source::load(null, $source->getSmarty(),
'file:' . '[' . $key . ']' . $source->name);
if (!$s->exists) {
continue;
}