- 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
This commit is contained in:
uwe.tews@googlemail.com
2010-10-01 13:19:53 +00:00
parent dde2219004
commit 415d2f43e2
10 changed files with 294 additions and 27 deletions

View File

@@ -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 25/09/2010
- bugfix on some compiling modifiers - bugfix on some compiling modifiers

View File

@@ -74,13 +74,18 @@ class Smarty_Internal_CacheResource_File {
* @param object $_template current template * @param object $_template current template
* @return string |booelan the template content or false if the file does not exist * @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(); ob_start();
$_smarty_tpl = $_template; $_smarty_tpl = $_template;
include $_template->getCachedFilepath(); include $_template->getCachedFilepath();
if ($no_render) {
ob_clean();
return null;
} else {
return ob_get_clean(); return ob_get_clean();
} }
}
/** /**
* Writes the rendered template output to cache file * Writes the rendered template output to cache file

View File

@@ -71,7 +71,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase {
} }
$_name = trim($saved_data[0]['name'], "\"'"); $_name = trim($saved_data[0]['name'], "\"'");
if (isset($compiler->template->block_data[$_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->properties['nocache_hash'] = $compiler->template->properties['nocache_hash'];
$_tpl->template_filepath = $compiler->template->block_data[$_name]['file']; $_tpl->template_filepath = $compiler->template->block_data[$_name]['file'];
if ($compiler->nocache) { if ($compiler->nocache) {

View File

@@ -0,0 +1,56 @@
<?php
/**
* Smarty Internal Plugin Compile Break
*
* Compiles the {break} tag
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile Break Class
*/
class Smarty_Internal_Compile_Break extends Smarty_Internal_CompileBase {
/**
* Compiles code for the {break} tag
*
* @param array $args array with attributes from parser
* @param object $compiler compiler object
* @return string compiled code
*/
public function compile($args, $compiler)
{
$this->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 "<?php break {$_levels}?>";
}
}
?>

View File

@@ -0,0 +1,56 @@
<?php
/**
* Smarty Internal Plugin Compile Continue
*
* Compiles the {continue} tag
*
* @package Smarty
* @subpackage Compiler
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Compile Continue Class
*/
class Smarty_Internal_Compile_Continue extends Smarty_Internal_CompileBase {
/**
* Compiles code for the {continue} tag
*
* @param array $args array with attributes from parser
* @param object $compiler compiler object
* @return string compiled code
*/
public function compile($args, $compiler)
{
$this->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 "<?php continue {$_levels}?>";
}
}
?>

View File

@@ -33,7 +33,7 @@ class Smarty_Internal_Compile_Eval extends Smarty_Internal_CompileBase {
} }
// create template object // 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? //was there an assign attribute?
if (isset($_assign)) { if (isset($_assign)) {
$_output .= "\$_smarty_tpl->assign($_assign,\$_template->getRenderedTemplate());"; $_output .= "\$_smarty_tpl->assign($_assign,\$_template->getRenderedTemplate());";

View File

@@ -0,0 +1,90 @@
<?php
/**
* Smarty Internal Plugin Resource Eval
*
* Implements the strings as resource for Smarty template
*
* @package Smarty
* @subpackage TemplateResources
* @author Uwe Tews
*/
/**
* Smarty Internal Plugin Resource Eval
*/
class Smarty_Internal_Resource_Eval {
public function __construct($smarty)
{
$this->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;
}
}
?>

View File

@@ -47,18 +47,16 @@ class Smarty_Internal_Resource_Registered {
*/ */
public function getTemplateFilepath($_template) 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); $_template->templateUid = sha1($_filepath);
return $_filepath; return $_filepath;
} }
/** /**
* Get timestamp to template source * Get timestamp of template source
* *
* @param object $_template template object * @param object $_template template object
* @return boolean false as string resources have no timestamp * @return int timestamp
*/ */
public function getTemplateTimestamp($_template) 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 * @param object $_template template object
* @return boolean false as string resources have no timestamp * @return int timestamp
*/ */
public function getTemplateTimestampTypeName($_resource_type, $_resource_name) public function getTemplateTimestampTypeName($_resource_type, $_resource_name)
{ {

View File

@@ -24,7 +24,7 @@ class Smarty_Internal_Resource_String {
public $template_parser_class = 'Smarty_Internal_Templateparser'; public $template_parser_class = 'Smarty_Internal_Templateparser';
// properties // properties
public $usesCompiler = true; public $usesCompiler = true;
public $isEvaluated = true; public $isEvaluated = false;
/** /**
* Return flag if template source is existing * Return flag if template source is existing
@@ -44,9 +44,10 @@ class Smarty_Internal_Resource_String {
*/ */
public function getTemplateFilepath($_template) public function getTemplateFilepath($_template)
{ {
$_template->templateUid = sha1($_template->resource_name);
// no filepath for strings // no filepath for strings
// return "string" for compiler error messages // return "string" for compiler error messages
return 'string'; return 'string:';
} }
/** /**
@@ -57,9 +58,26 @@ class Smarty_Internal_Resource_String {
*/ */
public function getTemplateTimestamp($_template) public function getTemplateTimestamp($_template)
{ {
// strings must always be compiled and have no timestamp if ($this->isEvaluated) {
//must always be compiled and have no timestamp
return false; 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 * Retuen template source from resource name
@@ -82,8 +100,33 @@ class Smarty_Internal_Resource_String {
*/ */
public function getCompiledFilepath($_template) public function getCompiledFilepath($_template)
{ {
// no filepath for strings $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w\|]+!', '_', $_template->compile_id) : null;
return false; // 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';
} }
} }

View File

@@ -356,7 +356,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data {
* *
* @return boolean true if cache is valid * @return boolean true if cache is valid
*/ */
public function isCached () public function isCached ($no_render = true)
{ {
if ($this->isCached === null) { if ($this->isCached === null) {
$this->isCached = false; $this->isCached = false;
@@ -372,7 +372,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data {
if ($this->smarty->debugging) { if ($this->smarty->debugging) {
Smarty_Internal_Debug::start_cache($this); 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) { if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_cache($this); Smarty_Internal_Debug::end_cache($this);
} }
@@ -519,7 +519,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data {
eval("?>" . $output); eval("?>" . $output);
$this->rendered_content = ob_get_clean(); $this->rendered_content = ob_get_clean();
// write cache file content // write cache file content
$this->writeCachedContent($output); $this->writeCachedContent('<?php if (!$no_render) {?>'. $output. '<?php } ?>');
if ($this->smarty->debugging) { if ($this->smarty->debugging) {
Smarty_Internal_Debug::end_cache($this); Smarty_Internal_Debug::end_cache($this);
} }
@@ -550,10 +550,24 @@ class Smarty_Internal_Template extends Smarty_Internal_Data {
// checks if template exists // checks if template exists
$this->isExisting(true); $this->isExisting(true);
// read from cache or render // 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) // render template (not loaded and not in cache)
$this->renderTemplate(); $this->renderTemplate();
} }
}
$this->updateParentVariables(); $this->updateParentVariables();
$this->isCached = null; $this->isCached = null;
return $this->rendered_content; return $this->rendered_content;
@@ -575,9 +589,8 @@ class Smarty_Internal_Template extends Smarty_Internal_Data {
$this->getResourceTypeName($template_resource, $resource_type, $resource_name); $this->getResourceTypeName($template_resource, $resource_type, $resource_name);
$resource_handler = $this->loadTemplateResourceHandler($resource_type); $resource_handler = $this->loadTemplateResourceHandler($resource_type);
// cache template object under a unique ID // cache template object under a unique ID
// do not cache string resources // do not cache eval resources
// ***** if ($resource_type != 'string' && $this->smarty->caching) { if ($resource_type != 'eval') {
if ($resource_type != 'string') {
$this->smarty->template_objects[crc32($this->template_resource . $this->cache_id . $this->compile_id)] = $this; $this->smarty->template_objects[crc32($this->template_resource . $this->cache_id . $this->compile_id)] = $this;
} }
return true; return true;
@@ -712,7 +725,7 @@ class Smarty_Internal_Template extends Smarty_Internal_Data {
return new Smarty_Internal_Resource_Registered($this->smarty); return new Smarty_Internal_Resource_Registered($this->smarty);
} else { } else {
// try sysplugins dir // 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); $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($resource_type);
return new $_resource_class($this->smarty); return new $_resource_class($this->smarty);
} else { } else {