mirror of
https://github.com/smarty-php/smarty.git
synced 2025-08-03 09:54:27 +02:00
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:
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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?>"
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
{
|
||||
|
@@ -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 = [];
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
140
src/Template.php
140
src/Template.php
@@ -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
|
||||
*/
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user