diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33224fcb..3cfcba74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,6 @@ jobs: - ubuntu-latest php-version: - - "7.1" - "7.2" - "7.3" - "7.4" diff --git a/src/Compile/Tag/IncludeTag.php b/src/Compile/Tag/IncludeTag.php index eee6bc5b..7e6232cb 100644 --- a/src/Compile/Tag/IncludeTag.php +++ b/src/Compile/Tag/IncludeTag.php @@ -84,7 +84,7 @@ class IncludeTag extends Base { $type = !empty($match[3]) ? $match[3] : $compiler->template->smarty->default_resource_type; $name = !empty($match[5]) ? $match[5] : $match[6]; $handler = \Smarty\Resource\BasePlugin::load($compiler->smarty, $type); - if ($handler->recompiled || $handler->uncompiled) { + if ($handler->recompiled) { $variable_template = true; } if (!$variable_template) { @@ -285,7 +285,7 @@ class IncludeTag extends Base { $t_hash ) { $uid = $tpl->source->type . $tpl->source->uid; - if (!($tpl->source->handler->uncompiled) && $tpl->source->exists) { + if ($tpl->source->exists) { $compiler->parent_compiler->mergedSubTemplatesData[$uid][$t_hash]['uid'] = $tpl->source->uid; if (isset($compiler->template->inheritance)) { $tpl->inheritance = clone $compiler->template->inheritance; diff --git a/src/Compiler/CodeFrame.php b/src/Compiler/CodeFrame.php index 4d9ae81a..2f5904dd 100644 --- a/src/Compiler/CodeFrame.php +++ b/src/Compiler/CodeFrame.php @@ -2,9 +2,12 @@ namespace Smarty\Compiler; +use Smarty\Exception; + /** * Smarty Internal Extension * This file contains the Smarty template extension to create a code frame + * * @author Uwe Tews */ @@ -24,15 +27,16 @@ class CodeFrame } /** - * Create code frame for compiled and cached templates - * - * @param string $content optional template content - * @param string $functions compiled template function and block code - * @param bool $cache flag for cache file - * @param \Smarty\Compiler\Template $compiler - * - * @return string - */ + * Create code frame for compiled and cached templates + * + * @param string $content optional template content + * @param string $functions compiled template function and block code + * @param bool $cache flag for cache file + * @param Template|null $compiler + * + * @return string + * @throws Exception +*/ public function create( $content = '', $functions = '', diff --git a/src/Resource/BasePlugin.php b/src/Resource/BasePlugin.php index 2212ead0..e5aecc31 100644 --- a/src/Resource/BasePlugin.php +++ b/src/Resource/BasePlugin.php @@ -36,16 +36,8 @@ abstract class BasePlugin 'extends' => ExtendsPlugin::class, 'stream' => StreamPlugin::class, 'eval' => StringEval::class, - 'php' => PhpPlugin::class, ]; - /** - * Source is bypassing compiler - * - * @var boolean - */ - public $uncompiled = false; - /** * Source must be recompiled on every occasion * diff --git a/src/Resource/PhpPlugin.php b/src/Resource/PhpPlugin.php deleted file mode 100644 index 1b146a60..00000000 --- a/src/Resource/PhpPlugin.php +++ /dev/null @@ -1,119 +0,0 @@ -short_open_tag = function_exists('ini_get') ? ini_get('short_open_tag') : 1; - } - - /** - * Load template's source from file into current template object - * - * @param Source $source source object - * - * @return string template source - * @throws Exception if source cannot be loaded - */ - public function getContent(Source $source) { - if ($source->exists) { - return ''; - } - throw new Exception("Unable to read template {$source->type} '{$source->name}'"); - } - - /** - * populate compiled object with compiled filepath - * - * @param Compiled $compiled compiled object - * @param Template $_template template object (is ignored) - */ - public function populateCompiledFilepath(Compiled $compiled, Template $_template) { - $compiled->filepath = $_template->source->filepath; - $compiled->timestamp = $_template->source->timestamp; - $compiled->exists = $_template->source->exists; - $compiled->file_dependency[$_template->source->uid] = - [ - $compiled->filepath, - $compiled->timestamp, - $_template->source->type, - ]; - } - - /** - * Render and output the template (without using the compiler) - * - * @param Source $source source object - * @param Template $_template template object - * - * @return void - * @throws Exception if template cannot be loaded or allow_php_templates is disabled - */ - public function renderUncompiled(Source $source, Template $_template) { - if (!$source->smarty->allow_php_templates) { - throw new Exception('PHP templates are disabled'); - } - if (!$source->exists) { - throw new Exception( - "Unable to load template '{$source->type}:{$source->name}'" . - ($_template->_isSubTpl() ? " in '{$_template->parent->template_resource}'" : '') - ); - } - // prepare variables - extract($_template->getTemplateVars()); - // include PHP template with short open tags enabled - if (function_exists('ini_set')) { - ini_set('short_open_tag', '1'); - } - /** - * - * - * @var Template $_smarty_template - * used in included file - */ - $_smarty_template = $_template; - include $source->filepath; - if (function_exists('ini_set')) { - ini_set('short_open_tag', $this->short_open_tag); - } - } -} diff --git a/src/Resource/UncompiledPlugin.php b/src/Resource/UncompiledPlugin.php deleted file mode 100644 index fe955b27..00000000 --- a/src/Resource/UncompiledPlugin.php +++ /dev/null @@ -1,54 +0,0 @@ -filepath = $_template->source->filepath; - $compiled->timestamp = $_template->source->timestamp; - $compiled->exists = $_template->source->exists; - if ($_template->smarty->merge_compiled_includes || $_template->source->handler->checkTimestamps()) { - $compiled->file_dependency[$_template->source->uid] = - [$compiled->filepath, $compiled->timestamp, $_template->source->type,]; - } - } -} diff --git a/src/Runtime/InheritanceRuntime.php b/src/Runtime/InheritanceRuntime.php index bdec8290..a5b8a107 100644 --- a/src/Runtime/InheritanceRuntime.php +++ b/src/Runtime/InheritanceRuntime.php @@ -120,7 +120,6 @@ class InheritanceRuntime { $tpl->caching ? 9999 : 0, $tpl->cache_lifetime, [], - false, $uid, $func ); diff --git a/src/Smarty.php b/src/Smarty.php index 8a2f7f55..7272bd1e 100644 --- a/src/Smarty.php +++ b/src/Smarty.php @@ -1386,7 +1386,7 @@ class Smarty extends \Smarty\TemplateBase /* @var Template $tpl */ $tpl = $this->createTemplate($resource_name); $this->caching = $_save_stat; - if (!$tpl->source->handler->uncompiled && !$tpl->source->handler->recompiled && $tpl->source->exists) { + if (!$tpl->source->handler->recompiled && $tpl->source->exists) { $_resource_part_1 = basename(str_replace('^', DIRECTORY_SEPARATOR, $tpl->compiled->filepath)); $_resource_part_1_length = strlen($_resource_part_1); } else { diff --git a/src/Template.php b/src/Template.php index 272eab17..bd4fb61c 100644 --- a/src/Template.php +++ b/src/Template.php @@ -10,7 +10,6 @@ namespace Smarty; -use Smarty\Smarty; use Smarty\Runtime\InheritanceRuntime; use Smarty\Template\Source; use Smarty\Template\Cached; @@ -298,7 +297,7 @@ class Template extends TemplateBase { $smarty->getDebug()->start_template($tpl); $smarty->getDebug()->start_render($tpl); } - $tpl->compiled->getRenderedTemplateCode($tpl, $content_func); + $tpl->getRenderedTemplateCode($content_func); if ($smarty->debugging) { $smarty->getDebug()->end_template($tpl); $smarty->getDebug()->end_render($tpl); @@ -386,16 +385,16 @@ class Template extends TemplateBase { } $tpl->cached->cache_lifetime = $properties['cache_lifetime']; $tpl->cached->valid = $is_valid; - $resource = $tpl->cached; + $generatedFile = $tpl->cached; } else { $tpl->mustCompile = !$is_valid; - $resource = $tpl->compiled; - $resource->includes = isset($properties['includes']) ? $properties['includes'] : []; + $generatedFile = $tpl->compiled; + $generatedFile->includes = $properties['includes'] ?? []; } if ($is_valid) { - $resource->unifunc = $properties['unifunc']; - $resource->has_nocache_code = $properties['has_nocache_code']; - $resource->file_dependency = $properties['file_dependency']; + $generatedFile->unifunc = $properties['unifunc']; + $generatedFile->has_nocache_code = $properties['has_nocache_code']; + $generatedFile->file_dependency = $properties['file_dependency']; } return $is_valid && !function_exists($properties['unifunc']); } @@ -465,10 +464,17 @@ class Template extends TemplateBase { * Load cached object * * @param bool $force force new cached object + * + * @throws Exception */ public function loadCached($force = false) { if ($force || !isset($this->cached)) { - $this->cached = Cached::create($this); + $this->cached = new Cached($this); + $this->cached->handler->populate($this->cached, $this); + // caching enabled ? + if (!$this->caching || $this->source->handler->recompiled) { + $this->cached->valid = false; + } } } @@ -484,7 +490,7 @@ class Template extends TemplateBase { /** * Unload inheritance object */ - public function _cleanUp() { + private function _cleanUp() { $this->startRenderCallbacks = []; $this->endRenderCallbacks = []; $this->inheritance = null; @@ -496,7 +502,9 @@ class Template extends TemplateBase { * @throws \Smarty\Exception */ public function loadCompiler() { - $this->compiler = $this->source->createCompiler(); + if (!isset($this->compiler)) { + $this->compiler = $this->source->createCompiler(); + } } /** @@ -510,7 +518,7 @@ class Template extends TemplateBase { * @return string */ public function createCodeFrame($content = '', $functions = '', $cache = false, \Smarty\Compiler\Template $compiler = null) { - return $this->getFrameCompiler()->create($content, $functions, $cache, $compiler); + return $this->getCodeFrameCompiler()->create($content, $functions, $cache, $compiler); } /** @@ -537,6 +545,9 @@ class Template extends TemplateBase { * * @return mixed|Cached * @throws Exception + * + * @deprecated + * @TODO remove */ public function __get($property_name) { switch ($property_name) { @@ -565,6 +576,10 @@ class Template extends TemplateBase { * @param mixed $value value * * @throws Exception + * + * + * @deprecated + * @TODO remove */ public function __set($property_name, $value) { switch ($property_name) { @@ -612,16 +627,15 @@ class Template extends TemplateBase { throw new Exception("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}"); } if ($this->mustCompile === null) { - $this->mustCompile = (!$this->source->handler->uncompiled && - ($this->smarty->force_compile || $this->source->handler->recompiled || - !$this->compiled->exists || ($this->compile_check && - $this->compiled->getTimeStamp() < - $this->source->getTimeStamp()))); + $this->mustCompile = $this->smarty->force_compile + || $this->source->handler->recompiled + || !$this->compiled->exists + || ($this->compile_check && $this->compiled->getTimeStamp() < $this->source->getTimeStamp()); } return $this->mustCompile; } - private function getFrameCompiler(): Compiler\CodeFrame { + private function getCodeFrameCompiler(): Compiler\CodeFrame { return new \Smarty\Compiler\CodeFrame($this); } @@ -800,5 +814,39 @@ 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->_getSmartyObj()->security_policy)) { + $this->_getSmartyObj()->security_policy->endTemplate(); + } + throw $e; + } + } } diff --git a/src/Template/Cached.php b/src/Template/Cached.php index 55083adc..c26102a1 100644 --- a/src/Template/Cached.php +++ b/src/Template/Cached.php @@ -3,18 +3,12 @@ namespace Smarty\Template; use Smarty\Template; -use Smarty\Template\ResourceBase; -use Smarty\Template\Source; /** - * Smarty Resource Data Object - * Cache Data Container for Template Files - * - - + * Represents a cached version of a template or config file. * @author Rodney Rehm */ -class Cached extends ResourceBase { +class Cached extends GeneratedPhpFile { /** * Cache Is Valid @@ -73,11 +67,16 @@ class Cached extends ResourceBase { public $hashes = []; /** - * Flag if this is a cache resource + * Content buffer * - * @var bool + * @var string */ - public $isCache = true; + public $content = null; + + private function renderTemplateCode(Template $_template) { + $_template->isRenderingCache = true; + $_template->getRenderedTemplateCode($this->unifunc); + } /** * create Cached Object container @@ -93,22 +92,6 @@ class Cached extends ResourceBase { $this->handler = $_template->smarty->getCacheResource(); } - /** - * @param Template $_template - * - * @return Cached - */ - public static function create(Template $_template) { - $_template->cached = new self($_template); - $_template->cached->handler->populate($_template->cached, $_template); - // caching enabled ? - if (!$_template->caching || $_template->source->handler->recompiled - ) { - $_template->cached->valid = false; - } - return $_template->cached; - } - /** * Render cache template * @@ -125,7 +108,7 @@ class Cached extends ResourceBase { if (!$this->processed) { $this->process($_template); } - $this->getRenderedTemplateCode($_template); + $this->renderTemplateCode($_template); if ($_template->smarty->debugging) { $_template->smarty->getDebug()->end_cache($_template); } @@ -300,7 +283,7 @@ class Cached extends ResourceBase { $_template->cached->process($_template, true); } $_template->compile_check = $compile_check; - $this->getRenderedTemplateCode($_template); + $this->renderTemplateCode($_template); if ($_template->smarty->debugging) { $_template->smarty->getDebug()->end_cache($_template); } diff --git a/src/Template/Compiled.php b/src/Template/Compiled.php index 1e4082e1..50b70375 100644 --- a/src/Template/Compiled.php +++ b/src/Template/Compiled.php @@ -5,15 +5,10 @@ namespace Smarty\Template; use Smarty\Template; /** - * Smarty Resource Data Object - * Meta Data Container for Template Files - * - - + * Represents a compiled version of a template or config file. * @author Rodney Rehm - * @property string $content compiled content */ -class Compiled extends ResourceBase { +class Compiled extends GeneratedPhpFile { /** * nocache hash @@ -22,6 +17,15 @@ class Compiled extends ResourceBase { */ public $nocache_hash = null; + /** + * Included sub templates + * - index name + * - value use count + * + * @var int[] + */ + public $includes = []; + /** * get a Compiled Object of this source * @@ -105,11 +109,9 @@ class Compiled extends ResourceBase { $_template->cached->file_dependency = array_merge($_template->cached->file_dependency, $this->file_dependency); } - if ($_template->source->handler->uncompiled) { - $_template->source->handler->renderUncompiled($_template->source, $_template); - } else { - $this->getRenderedTemplateCode($_template); - } + + $_template->getRenderedTemplateCode($this->unifunc); + if ($_template->caching && $this->has_nocache_code) { $_template->cached->hashes[$this->nocache_hash] = true; } @@ -130,7 +132,7 @@ class Compiled extends ResourceBase { $smarty = &$_smarty_tpl->smarty; if ($source->handler->recompiled) { $source->handler->process($_smarty_tpl); - } elseif (!$source->handler->uncompiled) { + } else { if (!$this->exists || $smarty->force_compile || ($_smarty_tpl->compile_check && $source->getTimeStamp() > $this->getTimeStamp()) ) { @@ -222,12 +224,12 @@ class Compiled extends ResourceBase { if (!$_template->source->handler->recompiled) { return file_get_contents($this->filepath); } - return isset($this->content) ? $this->content : false; + return false; } /** * Load fresh compiled template by including the PHP file - * HHVM requires a work around because of a PHP incompatibility + * HHVM requires a workaround because of a PHP incompatibility * * @param \Smarty\Template $_smarty_tpl do not change variable name, is used by compiled template */ @@ -245,4 +247,5 @@ class Compiled extends ResourceBase { include $this->filepath; } } + } diff --git a/src/Template/GeneratedPhpFile.php b/src/Template/GeneratedPhpFile.php new file mode 100644 index 00000000..37b6e551 --- /dev/null +++ b/src/Template/GeneratedPhpFile.php @@ -0,0 +1,79 @@ +exists && !$this->timestamp) { + $this->timestamp = filemtime($this->filepath); + } + return $this->timestamp; + } + +} diff --git a/src/Template/ResourceBase.php b/src/Template/ResourceBase.php deleted file mode 100644 index 33e41f22..00000000 --- a/src/Template/ResourceBase.php +++ /dev/null @@ -1,147 +0,0 @@ -smarty; - $_template->isRenderingCache = $this->isCache; - $level = ob_get_level(); - try { - if (!isset($unifunc)) { - $unifunc = $this->unifunc; - } - if (empty($unifunc) || !function_exists($unifunc)) { - throw new \Smarty\Exception("Invalid compiled template for '{$_template->template_resource}'"); - } - if ($_template->startRenderCallbacks) { - foreach ($_template->startRenderCallbacks as $callback) { - call_user_func($callback, $_template); - } - } - $unifunc($_template); - foreach ($_template->endRenderCallbacks as $callback) { - call_user_func($callback, $_template); - } - $_template->isRenderingCache = false; - } catch (\Exception $e) { - $_template->isRenderingCache = false; - while (ob_get_level() > $level) { - ob_end_clean(); - } - if (isset($smarty->security_policy)) { - $smarty->security_policy->endTemplate(); - } - throw $e; - } - } - - /** - * Get compiled time stamp - * - * @return int - */ - public function getTimeStamp() { - if ($this->exists && !$this->timestamp) { - $this->timestamp = filemtime($this->filepath); - } - return $this->timestamp; - } -} diff --git a/src/Template/Source.php b/src/Template/Source.php index 75604835..918a4bde 100644 --- a/src/Template/Source.php +++ b/src/Template/Source.php @@ -7,11 +7,7 @@ use Smarty\Template; use Smarty\Exception; /** - * Smarty Resource Data Object - * Meta Data Container for Template Files - * - - + * Meta-data Container for Template source files * @author Rodney Rehm */ class Source { diff --git a/tests/UnitTests/ResourceTests/Eval/EvalResourceTest.php b/tests/UnitTests/ResourceTests/Eval/EvalResourceTest.php index adf9d79e..0c6c0c3c 100644 --- a/tests/UnitTests/ResourceTests/Eval/EvalResourceTest.php +++ b/tests/UnitTests/ResourceTests/Eval/EvalResourceTest.php @@ -81,7 +81,7 @@ class EvalResourceTest extends PHPUnit_Smarty public function testUsesCompiler() { $tpl = $this->smarty->createTemplate('eval:hello world'); - $this->assertFalse($tpl->source->handler->uncompiled); + $this->markTestIncomplete(); } /** diff --git a/tests/UnitTests/ResourceTests/File/FileResourceTest.php b/tests/UnitTests/ResourceTests/File/FileResourceTest.php index 20cca0bc..6737738f 100644 --- a/tests/UnitTests/ResourceTests/File/FileResourceTest.php +++ b/tests/UnitTests/ResourceTests/File/FileResourceTest.php @@ -93,7 +93,7 @@ class FileResourceTest extends PHPUnit_Smarty public function testUsesCompiler() { $tpl = $this->smarty->createTemplate('helloworld.tpl'); - $this->assertFalse($tpl->source->handler->uncompiled); + $this->markTestIncomplete(); } public function testIsEvaluated() diff --git a/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php b/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php index 9a2c5f53..d6b4d335 100644 --- a/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php +++ b/tests/UnitTests/ResourceTests/Stream/StreamResourceTest.php @@ -70,7 +70,7 @@ class StreamResourceTest extends PHPUnit_Smarty public function testUsesCompiler() { $tpl = $this->smarty->createTemplate('global:mytest'); - $this->assertFalse($tpl->source->handler->uncompiled); + $this->markTestIncomplete(); } /** diff --git a/tests/UnitTests/ResourceTests/String/StringResourceTest.php b/tests/UnitTests/ResourceTests/String/StringResourceTest.php index c3d54954..ee59b6e4 100644 --- a/tests/UnitTests/ResourceTests/String/StringResourceTest.php +++ b/tests/UnitTests/ResourceTests/String/StringResourceTest.php @@ -83,7 +83,7 @@ class StringResourceTest extends PHPUnit_Smarty public function testUsesCompiler() { $tpl = $this->smarty->createTemplate('string:hello world'); - $this->assertFalse($tpl->source->handler->uncompiled); + $this->markTestIncomplete(); } /**