diff --git a/NEWS b/NEWS index 6b5c4422..e244e0a0 100644 --- a/NEWS +++ b/NEWS @@ -1,10 +1,10 @@ - - fixed bug that would not respect nested template directories and would - put all compiled files into top-level one. (Andrei) Version 1.2.2 ------------- - - fixed bug using $PHP_VERSION instead of environment var PHP_VERSION. - - couple small warning fixes + - fixed bug that would not respect nested template directories and would + put all compiled files into top-level one. (Andrei) + - fixed bug using $PHP_VERSION instead of environment var PHP_VERSION. + - couple small warning fixes Version 1.2.1 ------------- diff --git a/Smarty.class.php b/Smarty.class.php index 7f18f987..f7c46b1e 100644 --- a/Smarty.class.php +++ b/Smarty.class.php @@ -47,17 +47,32 @@ class Smarty // This is generally set to false once the // application is entered into production and // initially compiled. Leave set to true - // during development. + // during development. true/false + + var $compile_force = false; // force templates to compile every time. + // overrides compile_check. true/false + var $allow_url_compile = true; // allow forced recompile from URL ?compile_force=1 + + // NOTE: all cache directives override + // compiling directives. If a cached version + // is available, that will be used regardless + // of compile settings. + var $cache_engine = true; // whether to use caching or not. true/false + var $cache_expire = 5; // number of seconds cached content will expire. + // 0 = never expires. default is one hour (3600) + var $cache_force = false; // force caches to expire every time. true/false + var $allow_url_cache = true; // allow forced cache expire from URL ?cache_force=1 var $template_dir = "./templates"; // name of directory for templates var $compile_dir = "./templates_c"; // name of directory for compiled templates + var $cache_dir = "./cache"; // name of directory for template cache var $tpl_file_ext = ".tpl"; // template file extentions var $allow_php = false; // whether or not to allow embedded php // in the templates. By default, php tags - // are escaped. + // are escaped. true/false var $left_delimiter = "{"; // template tag delimiters. var $right_delimiter = "}"; @@ -83,7 +98,7 @@ class Smarty ); // internal vars - var $_error_msg = false; // error messages + var $_error_msg = false; // error messages. true/false var $_tpl_vars = array(); var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part var $_literal_blocks = array(); // keeps literal template blocks @@ -183,13 +198,7 @@ class Smarty function display($tpl_file) { - // compile files - $this->_compile($this->template_dir); - //assemble compile directory path to file - $_compile_file = $this->compile_dir.'/'.$tpl_file.'.php'; - - extract($this->_tpl_vars); - include($_compile_file); + print $this->fetch($tpl_file); } /*======================================================================*\ @@ -199,10 +208,49 @@ class Smarty function fetch($tpl_file) { + global $HTTP_GET_VARS,$PHP_SELF; + + if($this->cache_engine) + { + if($this->allow_url_cache && $HTTP_GET_VARS["cache_force"]) + $this->cache_force = true; + + // cache id = template path + the invoked script + $cache_file = $this->cache_dir."/".urlencode($tpl_file."@".$PHP_SELF).".che"; + if(!$this->cache_force && + (file_exists($cache_file) && + ($this->cache_expire == 0 || + (mktime() - filectime($cache_file) <= $this->cache_expire) + ))) + { + echo "DEBUG: using cache
\n"; + $results = $this->_read_file($cache_file); + $results = $this->_process_cached_inserts($results); + return $results; + } + } + + echo "DEBUG: not using cache
\n"; + if($this->allow_url_compile && $HTTP_GET_VARS["compile_force"]) + $this->compile_force = true; + ob_start(); - $this->display($tpl_file); - $results = ob_get_contents(); + // compile files + $this->_compile($this->template_dir); + //assemble compile directory path to file + $_compile_file = $this->compile_dir."/".$tpl_file.".php"; + + extract($this->_tpl_vars); + include($_compile_file); + $results = ob_get_contents(); ob_end_clean(); + + if($this->cache_engine) + { + $this->_write_file($cache_file,$results); + $results = $this->_process_cached_inserts($results); + } + return $results; } @@ -213,7 +261,7 @@ class Smarty function _compile($tpl_dir) { - if($this->compile_check) + if($this->compile_check || $this->compile_force) { if($this->_traverse_files($tpl_dir, 0)) return true; @@ -222,8 +270,8 @@ class Smarty } else return false; - } - + } + /*======================================================================*\ Function: _traverse_files() Purpose: traverse the template files & process each one @@ -241,7 +289,8 @@ class Smarty $filepath = $tpl_dir."/".$curr_file; if(is_readable($filepath)) { - if(is_file($filepath) && preg_match('!' . preg_quote($this->tpl_file_ext, '!') . '$!', $curr_file)) { + + if(is_file($filepath) && substr($curr_file,-strlen($this->tpl_file_ext)) == $this->tpl_file_ext) { if(!$this->_process_file($filepath)) return false; } else if(is_dir($filepath)) { @@ -291,8 +340,8 @@ class Smarty } } - // compile the template file if none exists or has been modified - if (!file_exists($compile_dir."/".$tpl_file_name) || + // compile the template file if none exists or has been modified or compile_force + if (!file_exists($compile_dir."/".$tpl_file_name) || $this->compile_force || ($this->_modified_file($filepath, $compile_dir."/".$tpl_file_name))) { if (!$this->_compile_file($filepath, $compile_dir."/".$tpl_file_name)) return false; @@ -383,6 +432,44 @@ class Smarty return true; } + function _process_cached_inserts($results) + { + + preg_match_all("/\{\{\{insert_cache name=([^ ]+) (.*)\}\}\}/Uis",$results,$match); + + $fulltags = $match[0]; + $names = $match[1]; + $args = $match[2]; + + for($curr_tag = 0; $curr_tag < count($fulltags); $curr_tag++) + { + $attrs = $this->_parse_attrs($args[$curr_tag]); + $name = substr($attrs['name'], 1, -1); + + if (empty($names[$curr_tag])) { + $this->_syntax_error("missing insert name"); + } + + foreach ($attrs as $arg_name => $arg_value) { + if ($arg_name == 'name') continue; + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $evalcode = "print insert_".$names[$curr_tag]."(array(".implode(',', (array)$arg_list)."));"; + + ob_start(); + eval($evalcode); + $replace = ob_get_contents(); + ob_end_clean(); + + $results = str_replace($fulltags[$curr_tag],$replace,$results); + } + + return $results; + } + function _compile_tag($template_tag) { /* Matched comment. */ @@ -468,7 +555,6 @@ class Smarty } } - function _compile_custom_tag($tag_command, $tag_args) { $attrs = $this->_parse_attrs($tag_args); @@ -482,12 +568,14 @@ class Smarty return ""; } - function _compile_insert_tag($tag_args) { $attrs = $this->_parse_attrs($tag_args); $name = substr($attrs['name'], 1, -1); + if($this->cache_engine) + return ""; + if (empty($name)) { $this->_syntax_error("missing insert name"); } @@ -500,9 +588,8 @@ class Smarty } return ""; - } - - + } + function _compile_config_load_tag($tag_args) { $attrs = $this->_parse_attrs($tag_args); diff --git a/docs.sgml b/docs.sgml index cb68588c..0f452fcc 100644 --- a/docs.sgml +++ b/docs.sgml @@ -14,7 +14,7 @@
andrei@ispi.net
- Version 1.2.1 + Version 1.2.2 2001ispi of Lincoln, Inc. @@ -1129,26 +1129,26 @@ e-mail: jane@mydomain.com {* This is an example of printing an associative array of data within a section *} {section name=customer loop=$contacts} - {$customer/contacts.name}<br> - {$customer/contacts.home}<br> - {$customer/contacts.cell}<br> - {$customer/contacts.email}<br> + name: {$customer/contacts.name}<br> + home: {$customer/contacts.home}<br> + cell: {$customer/contacts.cell}<br> + e-mail: {$customer/contacts.email}<p> {/section} OUTPUT: name: John Smith<br> -home: 555-555-5555<p> -cell: 555-555-5555<p> +home: 555-555-5555<br> +cell: 555-555-5555<br> e-mail: john@mydomain.com<p> name: Jack Jones<br> -home phone: 555-555-5555<p> -cell phone: 555-555-5555<p> +home phone: 555-555-5555<br> +cell phone: 555-555-5555<br> e-mail: jack@mydomain.com<p> -name: Jane Munson<p> -home phone: 555-555-5555<p> -cell phone: 555-555-5555<p> +name: Jane Munson<br> +home phone: 555-555-5555<br> +cell phone: 555-555-5555<br> e-mail: jane@mydomain.com<p> @@ -1934,6 +1934,15 @@ function makeTimeStamp($year="",$month="",$day="") + + Resources + + Smarty's homepage is located at http://www.phpinsider.com/php/code/Smarty/. + You can join the mailing list by sending an e-mail to + subscribe-smarty@lists.ispi.net. An archive of the mailing list can be + viewed at http://marc.theaimsgroup.com/ under www/smarty. + + BUGS diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 7f18f987..f7c46b1e 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -47,17 +47,32 @@ class Smarty // This is generally set to false once the // application is entered into production and // initially compiled. Leave set to true - // during development. + // during development. true/false + + var $compile_force = false; // force templates to compile every time. + // overrides compile_check. true/false + var $allow_url_compile = true; // allow forced recompile from URL ?compile_force=1 + + // NOTE: all cache directives override + // compiling directives. If a cached version + // is available, that will be used regardless + // of compile settings. + var $cache_engine = true; // whether to use caching or not. true/false + var $cache_expire = 5; // number of seconds cached content will expire. + // 0 = never expires. default is one hour (3600) + var $cache_force = false; // force caches to expire every time. true/false + var $allow_url_cache = true; // allow forced cache expire from URL ?cache_force=1 var $template_dir = "./templates"; // name of directory for templates var $compile_dir = "./templates_c"; // name of directory for compiled templates + var $cache_dir = "./cache"; // name of directory for template cache var $tpl_file_ext = ".tpl"; // template file extentions var $allow_php = false; // whether or not to allow embedded php // in the templates. By default, php tags - // are escaped. + // are escaped. true/false var $left_delimiter = "{"; // template tag delimiters. var $right_delimiter = "}"; @@ -83,7 +98,7 @@ class Smarty ); // internal vars - var $_error_msg = false; // error messages + var $_error_msg = false; // error messages. true/false var $_tpl_vars = array(); var $_sectionelse_stack = array(); // keeps track of whether section had 'else' part var $_literal_blocks = array(); // keeps literal template blocks @@ -183,13 +198,7 @@ class Smarty function display($tpl_file) { - // compile files - $this->_compile($this->template_dir); - //assemble compile directory path to file - $_compile_file = $this->compile_dir.'/'.$tpl_file.'.php'; - - extract($this->_tpl_vars); - include($_compile_file); + print $this->fetch($tpl_file); } /*======================================================================*\ @@ -199,10 +208,49 @@ class Smarty function fetch($tpl_file) { + global $HTTP_GET_VARS,$PHP_SELF; + + if($this->cache_engine) + { + if($this->allow_url_cache && $HTTP_GET_VARS["cache_force"]) + $this->cache_force = true; + + // cache id = template path + the invoked script + $cache_file = $this->cache_dir."/".urlencode($tpl_file."@".$PHP_SELF).".che"; + if(!$this->cache_force && + (file_exists($cache_file) && + ($this->cache_expire == 0 || + (mktime() - filectime($cache_file) <= $this->cache_expire) + ))) + { + echo "DEBUG: using cache
\n"; + $results = $this->_read_file($cache_file); + $results = $this->_process_cached_inserts($results); + return $results; + } + } + + echo "DEBUG: not using cache
\n"; + if($this->allow_url_compile && $HTTP_GET_VARS["compile_force"]) + $this->compile_force = true; + ob_start(); - $this->display($tpl_file); - $results = ob_get_contents(); + // compile files + $this->_compile($this->template_dir); + //assemble compile directory path to file + $_compile_file = $this->compile_dir."/".$tpl_file.".php"; + + extract($this->_tpl_vars); + include($_compile_file); + $results = ob_get_contents(); ob_end_clean(); + + if($this->cache_engine) + { + $this->_write_file($cache_file,$results); + $results = $this->_process_cached_inserts($results); + } + return $results; } @@ -213,7 +261,7 @@ class Smarty function _compile($tpl_dir) { - if($this->compile_check) + if($this->compile_check || $this->compile_force) { if($this->_traverse_files($tpl_dir, 0)) return true; @@ -222,8 +270,8 @@ class Smarty } else return false; - } - + } + /*======================================================================*\ Function: _traverse_files() Purpose: traverse the template files & process each one @@ -241,7 +289,8 @@ class Smarty $filepath = $tpl_dir."/".$curr_file; if(is_readable($filepath)) { - if(is_file($filepath) && preg_match('!' . preg_quote($this->tpl_file_ext, '!') . '$!', $curr_file)) { + + if(is_file($filepath) && substr($curr_file,-strlen($this->tpl_file_ext)) == $this->tpl_file_ext) { if(!$this->_process_file($filepath)) return false; } else if(is_dir($filepath)) { @@ -291,8 +340,8 @@ class Smarty } } - // compile the template file if none exists or has been modified - if (!file_exists($compile_dir."/".$tpl_file_name) || + // compile the template file if none exists or has been modified or compile_force + if (!file_exists($compile_dir."/".$tpl_file_name) || $this->compile_force || ($this->_modified_file($filepath, $compile_dir."/".$tpl_file_name))) { if (!$this->_compile_file($filepath, $compile_dir."/".$tpl_file_name)) return false; @@ -383,6 +432,44 @@ class Smarty return true; } + function _process_cached_inserts($results) + { + + preg_match_all("/\{\{\{insert_cache name=([^ ]+) (.*)\}\}\}/Uis",$results,$match); + + $fulltags = $match[0]; + $names = $match[1]; + $args = $match[2]; + + for($curr_tag = 0; $curr_tag < count($fulltags); $curr_tag++) + { + $attrs = $this->_parse_attrs($args[$curr_tag]); + $name = substr($attrs['name'], 1, -1); + + if (empty($names[$curr_tag])) { + $this->_syntax_error("missing insert name"); + } + + foreach ($attrs as $arg_name => $arg_value) { + if ($arg_name == 'name') continue; + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + + $evalcode = "print insert_".$names[$curr_tag]."(array(".implode(',', (array)$arg_list)."));"; + + ob_start(); + eval($evalcode); + $replace = ob_get_contents(); + ob_end_clean(); + + $results = str_replace($fulltags[$curr_tag],$replace,$results); + } + + return $results; + } + function _compile_tag($template_tag) { /* Matched comment. */ @@ -468,7 +555,6 @@ class Smarty } } - function _compile_custom_tag($tag_command, $tag_args) { $attrs = $this->_parse_attrs($tag_args); @@ -482,12 +568,14 @@ class Smarty return ""; } - function _compile_insert_tag($tag_args) { $attrs = $this->_parse_attrs($tag_args); $name = substr($attrs['name'], 1, -1); + if($this->cache_engine) + return ""; + if (empty($name)) { $this->_syntax_error("missing insert name"); } @@ -500,9 +588,8 @@ class Smarty } return ""; - } - - + } + function _compile_config_load_tag($tag_args) { $attrs = $this->_parse_attrs($tag_args);