- 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
- bugfix on some compiling modifiers

View File

@@ -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();
}
}
/**

View File

@@ -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) {

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
$_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());";

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)
{
// 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)
{

View File

@@ -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';
}
}

View File

@@ -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('<?php if (!$no_render) {?>'. $output. '<?php } ?>');
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 {