From 415d2f43e2f6f476cb7063c055a0a79893ca96f2 Mon Sep 17 00:00:00 2001 From: "uwe.tews@googlemail.com" Date: Fri, 1 Oct 2010 13:19:53 +0000 Subject: [PATCH] - added {break} and {continue} tags for flow control of {foreach},{section},{for} and {while} loops - change of 'string' resource. It's no longer evaluated and compiled files are now stored - new 'eval' resource which evaluates a template without saving the compiled file - change in isCached() method to allow multiple calls for the same template --- change_log.txt | 6 ++ .../smarty_internal_cacheresource_file.php | 9 +- .../smarty_internal_compile_block.php | 2 +- .../smarty_internal_compile_break.php | 56 ++++++++++++ .../smarty_internal_compile_continue.php | 56 ++++++++++++ .../smarty_internal_compile_eval.php | 2 +- .../smarty_internal_resource_eval.php | 90 +++++++++++++++++++ .../smarty_internal_resource_registered.php | 12 ++- .../smarty_internal_resource_string.php | 57 ++++++++++-- libs/sysplugins/smarty_internal_template.php | 31 +++++-- 10 files changed, 294 insertions(+), 27 deletions(-) create mode 100644 libs/sysplugins/smarty_internal_compile_break.php create mode 100644 libs/sysplugins/smarty_internal_compile_continue.php create mode 100644 libs/sysplugins/smarty_internal_resource_eval.php diff --git a/change_log.txt b/change_log.txt index e2b107b5..5e485f36 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,3 +1,9 @@ +01/10/2010 +- added {break} and {continue} tags for flow control of {foreach},{section},{for} and {while} loops +- change of 'string' resource. It's no longer evaluated and compiled files are now stored +- new 'eval' resource which evaluates a template without saving the compiled file +- change in isCached() method to allow multiple calls for the same template + 25/09/2010 - bugfix on some compiling modifiers diff --git a/libs/sysplugins/smarty_internal_cacheresource_file.php b/libs/sysplugins/smarty_internal_cacheresource_file.php index 9ca579db..3ce4e8fc 100644 --- a/libs/sysplugins/smarty_internal_cacheresource_file.php +++ b/libs/sysplugins/smarty_internal_cacheresource_file.php @@ -74,12 +74,17 @@ class Smarty_Internal_CacheResource_File { * @param object $_template current template * @return string |booelan the template content or false if the file does not exist */ - public function getCachedContents($_template) + public function getCachedContents($_template, $no_render = false) { ob_start(); $_smarty_tpl = $_template; include $_template->getCachedFilepath(); - return ob_get_clean(); + if ($no_render) { + ob_clean(); + return null; + } else { + return ob_get_clean(); + } } /** diff --git a/libs/sysplugins/smarty_internal_compile_block.php b/libs/sysplugins/smarty_internal_compile_block.php index 77bd0873..7e651e43 100644 --- a/libs/sysplugins/smarty_internal_compile_block.php +++ b/libs/sysplugins/smarty_internal_compile_block.php @@ -71,7 +71,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase { } $_name = trim($saved_data[0]['name'], "\"'"); if (isset($compiler->template->block_data[$_name])) { - $_tpl = $this->smarty->createTemplate('string:' . $compiler->template->block_data[$_name]['source'], null, null, $compiler->template); + $_tpl = $this->smarty->createTemplate('eval:' . $compiler->template->block_data[$_name]['source'], null, null, $compiler->template); $_tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash']; $_tpl->template_filepath = $compiler->template->block_data[$_name]['file']; if ($compiler->nocache) { diff --git a/libs/sysplugins/smarty_internal_compile_break.php b/libs/sysplugins/smarty_internal_compile_break.php new file mode 100644 index 00000000..60e856df --- /dev/null +++ b/libs/sysplugins/smarty_internal_compile_break.php @@ -0,0 +1,56 @@ +compiler = $compiler; + $this->smarty = $compiler->smarty; + $this->optional_attributes = array('levels'); + // check and get attributes + $_attr = $this->_get_attributes($args); + + if (isset($_attr['levels'])) { + if (!is_numeric($_attr['levels'])) { + $this->compiler->trigger_template_error('level attribute must be a numeric constant', $this->compiler->lex->taglineno); + } + $_levels = $_attr['levels']; + } else { + $_levels = 1; + } + $level_count = $_levels; + $stack_count = count($compiler->_tag_stack) - 1; + while ($level_count > 0 && $stack_count >= 0) { + if (in_array($compiler->_tag_stack[$stack_count][0], array('for', 'foreach', 'while', 'section'))) { + $level_count--; + } + $stack_count--; + } + if ($level_count != 0) { + $this->compiler->trigger_template_error("cannot break {$_levels} level(s)", $this->compiler->lex->taglineno); + } + // this tag does not return compiled code + $this->compiler->has_code = true; + return ""; + } +} + +?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_compile_continue.php b/libs/sysplugins/smarty_internal_compile_continue.php new file mode 100644 index 00000000..3c15e8f1 --- /dev/null +++ b/libs/sysplugins/smarty_internal_compile_continue.php @@ -0,0 +1,56 @@ +compiler = $compiler; + $this->smarty = $compiler->smarty; + $this->optional_attributes = array('levels'); + // check and get attributes + $_attr = $this->_get_attributes($args); + + if (isset($_attr['levels'])) { + if (!is_numeric($_attr['levels'])) { + $this->compiler->trigger_template_error('level attribute must be a numeric constant', $this->compiler->lex->taglineno); + } + $_levels = $_attr['levels']; + } else { + $_levels = 1; + } + $level_count = $_levels; + $stack_count = count($compiler->_tag_stack) - 1; + while ($level_count > 0 && $stack_count >= 0) { + if (in_array($compiler->_tag_stack[$stack_count][0], array('for', 'foreach', 'while', 'section'))) { + $level_count--; + } + $stack_count--; + } + if ($level_count != 0) { + $this->compiler->trigger_template_error("cannot continue {$_levels} level(s)", $this->compiler->lex->taglineno); + } + // this tag does not return compiled code + $this->compiler->has_code = true; + return ""; + } +} + +?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_compile_eval.php b/libs/sysplugins/smarty_internal_compile_eval.php index 747f8e73..17be1f80 100644 --- a/libs/sysplugins/smarty_internal_compile_eval.php +++ b/libs/sysplugins/smarty_internal_compile_eval.php @@ -33,7 +33,7 @@ class Smarty_Internal_Compile_Eval extends Smarty_Internal_CompileBase { } // create template object - $_output = "\$_template = new {$compiler->smarty->template_class}('string:'.".$_attr['var'].", \$_smarty_tpl->smarty, \$_smarty_tpl);"; + $_output = "\$_template = new {$compiler->smarty->template_class}('eval:'.".$_attr['var'].", \$_smarty_tpl->smarty, \$_smarty_tpl);"; //was there an assign attribute? if (isset($_assign)) { $_output .= "\$_smarty_tpl->assign($_assign,\$_template->getRenderedTemplate());"; diff --git a/libs/sysplugins/smarty_internal_resource_eval.php b/libs/sysplugins/smarty_internal_resource_eval.php new file mode 100644 index 00000000..2eb20857 --- /dev/null +++ b/libs/sysplugins/smarty_internal_resource_eval.php @@ -0,0 +1,90 @@ +smarty = $smarty; + } + // classes used for compiling Smarty templates from file resource + public $compiler_class = 'Smarty_Internal_SmartyTemplateCompiler'; + public $template_lexer_class = 'Smarty_Internal_Templatelexer'; + public $template_parser_class = 'Smarty_Internal_Templateparser'; + // properties + public $usesCompiler = true; + public $isEvaluated = true; + + /** + * Return flag if template source is existing + * + * @return boolean true + */ + public function isExisting($template) + { + return true; + } + + /** + * Get filepath to template source + * + * @param object $_template template object + * @return string return 'string' as template source is not a file + */ + public function getTemplateFilepath($_template) + { + // no filepath for evaluated strings + // return "string" for compiler error messages + return 'eval:'; + } + + /** + * Get timestamp to template source + * + * @param object $_template template object + * @return boolean false as string resources have no timestamp + */ + public function getTemplateTimestamp($_template) + { + // evaluated strings must always be compiled and have no timestamp + return false; + } + + /** + * Retuen template source from resource name + * + * @param object $_template template object + * @return string content of template source + */ + public function getTemplateSource($_template) + { + // return template string + $_template->template_source = $_template->resource_name; + return true; + } + + /** + * Get filepath to compiled template + * + * @param object $_template template object + * @return boolean return false as compiled template is not stored + */ + public function getCompiledFilepath($_template) + { + // no filepath for strings + return false; + } +} + +?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_resource_registered.php b/libs/sysplugins/smarty_internal_resource_registered.php index a56236e4..d120d179 100644 --- a/libs/sysplugins/smarty_internal_resource_registered.php +++ b/libs/sysplugins/smarty_internal_resource_registered.php @@ -47,18 +47,16 @@ class Smarty_Internal_Resource_Registered { */ public function getTemplateFilepath($_template) { - // no filepath for strings - // return "string" for compiler error messages - $_filepath = $_template->resource_type .':'.$_template->resource_name; + $_filepath = $_template->resource_type .':'.$_template->resource_name; $_template->templateUid = sha1($_filepath); return $_filepath; } /** - * Get timestamp to template source + * Get timestamp of template source * * @param object $_template template object - * @return boolean false as string resources have no timestamp + * @return int timestamp */ public function getTemplateTimestamp($_template) { @@ -70,10 +68,10 @@ class Smarty_Internal_Resource_Registered { } /** - * Get timestamp to template source by type and name + * Get timestamp of template source by type and name * * @param object $_template template object - * @return boolean false as string resources have no timestamp + * @return int timestamp */ public function getTemplateTimestampTypeName($_resource_type, $_resource_name) { diff --git a/libs/sysplugins/smarty_internal_resource_string.php b/libs/sysplugins/smarty_internal_resource_string.php index f5e28e3c..9368f040 100644 --- a/libs/sysplugins/smarty_internal_resource_string.php +++ b/libs/sysplugins/smarty_internal_resource_string.php @@ -24,7 +24,7 @@ class Smarty_Internal_Resource_String { public $template_parser_class = 'Smarty_Internal_Templateparser'; // properties public $usesCompiler = true; - public $isEvaluated = true; + public $isEvaluated = false; /** * Return flag if template source is existing @@ -44,9 +44,10 @@ class Smarty_Internal_Resource_String { */ public function getTemplateFilepath($_template) { + $_template->templateUid = sha1($_template->resource_name); // no filepath for strings // return "string" for compiler error messages - return 'string'; + return 'string:'; } /** @@ -57,10 +58,27 @@ class Smarty_Internal_Resource_String { */ public function getTemplateTimestamp($_template) { - // strings must always be compiled and have no timestamp - return false; + if ($this->isEvaluated) { + //must always be compiled and have no timestamp + return false; + } else { + return 0; + } } + /** + * Get timestamp of template source by type and name + * + * @param object $_template template object + * @return int timestamp (always 0) + */ + public function getTemplateTimestampTypeName($_resource_type, $_resource_name) + { + // return timestamp 0 + return 0; + } + + /** * Retuen template source from resource name * @@ -81,9 +99,34 @@ class Smarty_Internal_Resource_String { * @return boolean return false as compiled template is not stored */ public function getCompiledFilepath($_template) - { - // no filepath for strings - return false; + { + $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null; + // calculate Uid if not already done + if ($_template->templateUid == '') { + $_template->getTemplateFilepath(); + } + $_filepath = $_template->templateUid; + // if use_sub_dirs, break file into directories + if ($_template->smarty->use_sub_dirs) { + $_filepath = substr($_filepath, 0, 2) . DS + . substr($_filepath, 2, 2) . DS + . substr($_filepath, 4, 2) . DS + . $_filepath; + } + $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^'; + if (isset($_compile_id)) { + $_filepath = $_compile_id . $_compile_dir_sep . $_filepath; + } + if ($_template->caching) { + $_cache = '.cache'; + } else { + $_cache = ''; + } + $_compile_dir = $_template->smarty->compile_dir; + if (strpos('/\\', substr($_compile_dir, -1)) === false) { + $_compile_dir .= DS; + } + return $_compile_dir . $_filepath . '.' . $_template->resource_type . $_cache . '.php'; } } diff --git a/libs/sysplugins/smarty_internal_template.php b/libs/sysplugins/smarty_internal_template.php index 41b3a462..e8a4e7f8 100644 --- a/libs/sysplugins/smarty_internal_template.php +++ b/libs/sysplugins/smarty_internal_template.php @@ -346,7 +346,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { return false; } $this->properties['cache_lifetime'] = $this->cache_lifetime; - return $this->cache_resource_object->writeCachedContent($this, $this->createPropertyHeader(true) . $content); + return $this->cache_resource_object->writeCachedContent($this, $this->createPropertyHeader(true) .$content); } /** @@ -356,7 +356,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { * * @return boolean true if cache is valid */ - public function isCached () + public function isCached ($no_render = true) { if ($this->isCached === null) { $this->isCached = false; @@ -372,7 +372,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { if ($this->smarty->debugging) { Smarty_Internal_Debug::start_cache($this); } - $this->rendered_content = $this->cache_resource_object->getCachedContents($this); + $this->rendered_content = $this->cache_resource_object->getCachedContents($this, $no_render); if ($this->smarty->debugging) { Smarty_Internal_Debug::end_cache($this); } @@ -519,7 +519,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { eval("?>" . $output); $this->rendered_content = ob_get_clean(); // write cache file content - $this->writeCachedContent($output); + $this->writeCachedContent(''. $output. ''); if ($this->smarty->debugging) { Smarty_Internal_Debug::end_cache($this); } @@ -550,9 +550,23 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { // checks if template exists $this->isExisting(true); // read from cache or render - if ($this->rendered_content === null && !$this->isCached()) { + if ($this->rendered_content === null) { + if ($this->isCached) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_cache($this); + } + $this->rendered_content = $this->cache_resource_object->getCachedContents($this, false); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_cache($this); + } + } + if ($this->isCached === null) { + $this->isCached(false); + } + if (!$this->isCached) { // render template (not loaded and not in cache) $this->renderTemplate(); + } } $this->updateParentVariables(); $this->isCached = null; @@ -575,9 +589,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { $this->getResourceTypeName($template_resource, $resource_type, $resource_name); $resource_handler = $this->loadTemplateResourceHandler($resource_type); // cache template object under a unique ID - // do not cache string resources - // ***** if ($resource_type != 'string' && $this->smarty->caching) { - if ($resource_type != 'string') { + // do not cache eval resources + if ($resource_type != 'eval') { $this->smarty->template_objects[crc32($this->template_resource . $this->cache_id . $this->compile_id)] = $this; } return true; @@ -712,7 +725,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data { return new Smarty_Internal_Resource_Registered($this->smarty); } else { // try sysplugins dir - if (in_array($resource_type, array('file', 'string', 'extends', 'php', 'registered', 'stream'))) { + if (in_array($resource_type, array('file', 'string', 'extends', 'php', 'registered', 'stream', 'eval'))) { $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($resource_type); return new $_resource_class($this->smarty); } else {