diff --git a/src/Cacheresource/Base.php b/src/Cacheresource/Base.php index 984ea827..8ec8f232 100644 --- a/src/Cacheresource/Base.php +++ b/src/Cacheresource/Base.php @@ -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 diff --git a/src/Cacheresource/File.php b/src/Cacheresource/File.php index 63430a2a..54070013 100644 --- a/src/Cacheresource/File.php +++ b/src/Cacheresource/File.php @@ -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; diff --git a/src/Compile/Tag/ExtendsTag.php b/src/Compile/Tag/ExtendsTag.php index f49efaac..f295339b 100644 --- a/src/Compile/Tag/ExtendsTag.php +++ b/src/Compile/Tag/ExtendsTag.php @@ -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(), 'getInheritance()->endChild($_smarty_tpl' . - (isset($template) ? - ", {$template}{$inlineUids}" : - '') . ");\n?>" + (isset($template) ? ", {$template}" : '') . ");\n?>" ); } diff --git a/src/Compile/Tag/IncludeTag.php b/src/Compile/Tag/IncludeTag.php index 8f100795..c2da994b 100644 --- a/src/Compile/Tag/IncludeTag.php +++ b/src/Compile/Tag/IncludeTag.php @@ -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 = "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('\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); } diff --git a/src/Compiler/Template.php b/src/Compiler/Template.php index c69f8185..4318c7fa 100644 --- a/src/Compiler/Template.php +++ b/src/Compiler/Template.php @@ -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, diff --git a/src/Resource/BasePlugin.php b/src/Resource/BasePlugin.php index 30f8cff8..bad56cbf 100644 --- a/src/Resource/BasePlugin.php +++ b/src/Resource/BasePlugin.php @@ -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; - } } diff --git a/src/Resource/ExtendsPlugin.php b/src/Resource/ExtendsPlugin.php index 808a6a12..b8aeab2c 100644 --- a/src/Resource/ExtendsPlugin.php +++ b/src/Resource/ExtendsPlugin.php @@ -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 { diff --git a/src/Resource/RecompiledPlugin.php b/src/Resource/RecompiledPlugin.php index 7800f065..f87664b3 100644 --- a/src/Resource/RecompiledPlugin.php +++ b/src/Resource/RecompiledPlugin.php @@ -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 = []; diff --git a/src/Runtime/CaptureRuntime.php b/src/Runtime/CaptureRuntime.php index fd84c3d4..3f37c59f 100644 --- a/src/Runtime/CaptureRuntime.php +++ b/src/Runtime/CaptureRuntime.php @@ -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; } /** diff --git a/src/Runtime/InheritanceRuntime.php b/src/Runtime/InheritanceRuntime.php index c1070a85..5a023d03 100644 --- a/src/Runtime/InheritanceRuntime.php +++ b/src/Runtime/InheritanceRuntime.php @@ -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); } } diff --git a/src/Template.php b/src/Template.php index 1e0122a2..991c7c92 100644 --- a/src/Template.php +++ b/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 */ diff --git a/src/Template/Cached.php b/src/Template/Cached.php index bf175bb7..89df7b0f 100644 --- a/src/Template/Cached.php +++ b/src/Template/Cached.php @@ -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); } /** diff --git a/src/Template/Compiled.php b/src/Template/Compiled.php index 4e1d51aa..660b672f 100644 --- a/src/Template/Compiled.php +++ b/src/Template/Compiled.php @@ -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; } } diff --git a/src/Template/GeneratedPhpFile.php b/src/Template/GeneratedPhpFile.php index e42948d9..c8aa0f02 100644 --- a/src/Template/GeneratedPhpFile.php +++ b/src/Template/GeneratedPhpFile.php @@ -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; + } + } + } diff --git a/src/Template/Source.php b/src/Template/Source.php index 2431bf17..4d5621ff 100644 --- a/src/Template/Source.php +++ b/src/Template/Source.php @@ -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); + } + } diff --git a/tests/UnitTests/CacheResourceTests/_shared/PHPunitplugins/resource.filetest.php b/tests/UnitTests/CacheResourceTests/_shared/PHPunitplugins/resource.filetest.php index add9b8a0..8d5b4271 100644 --- a/tests/UnitTests/CacheResourceTests/_shared/PHPunitplugins/resource.filetest.php +++ b/tests/UnitTests/CacheResourceTests/_shared/PHPunitplugins/resource.filetest.php @@ -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 diff --git a/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php b/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php index 2fed1948..bc212a82 100644 --- a/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php +++ b/tests/UnitTests/__shared/cacheresources/cacheresource.memcache.php @@ -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(); } } diff --git a/tests/UnitTests/__shared/resources/resource.extendsall.php b/tests/UnitTests/__shared/resources/resource.extendsall.php index 10f7d437..55b7985b 100644 --- a/tests/UnitTests/__shared/resources/resource.extendsall.php +++ b/tests/UnitTests/__shared/resources/resource.extendsall.php @@ -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; }