From 4331452b8e8786a3ae6ca3a59f92f080051eb97f Mon Sep 17 00:00:00 2001 From: "Uwe.Tews" Date: Thu, 27 Aug 2009 14:59:28 +0000 Subject: [PATCH] - implemented registered resources as in Smarty2. NOTE: caching does not work yet - new property 'force_cache'. if true it forces the creation of a new cache file - fixed modifiers on arrays - some speed optimization on loading internal classes --- change_log.txt | 7 + libs/Smarty.class.php | 15 ++- libs/sysplugins/internal.plugin_handler.php | 32 ++++- .../internal.resource_registered.php | 125 ++++++++++++++++++ libs/sysplugins/internal.template.php | 57 ++++---- .../internal.templatecompilerbase.php | 5 - libs/sysplugins/internal.templateparser.php | 22 +-- 7 files changed, 216 insertions(+), 47 deletions(-) create mode 100644 libs/sysplugins/internal.resource_registered.php diff --git a/change_log.txt b/change_log.txt index 66238a64..e6eb1444 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,3 +1,10 @@ +08/24/2009 +- implemented registered resources as in Smarty2. NOTE: caching does not work yet +- new property 'force_cache'. if true it forces the creation of a new cache file +- fixed modifiers on arrays +- some speed optimization on loading internal classes + + 08/24/2009 - fixed typo in lexer definition for '!==' operator - bugfix - the ouput of plugins was not cached diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 29955b34..7db4e1fb 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -102,6 +102,8 @@ class Smarty extends Smarty_Internal_TemplateBase { public $caching = false; // caching lifetime public $caching_lifetime = 0; + // force cache file creation + public $force_cache = false; // cache_id public $cache_id = null; // compile_id @@ -209,13 +211,14 @@ class Smarty extends Smarty_Internal_TemplateBase { $this->config_dir = '.' . DIRECTORY_SEPARATOR . 'configs' . DIRECTORY_SEPARATOR; $this->sysplugins_dir = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sysplugins' . DIRECTORY_SEPARATOR; $this->debug_tpl = SMARTY_DIR . 'debug.tpl'; - // load base plugins - $this->loadPlugin('Smarty_Internal_Base'); - $this->loadPlugin('Smarty_Internal_PluginBase'); - $this->loadPlugin($this->template_class); - $this->loadPlugin('Smarty_Internal_Plugin_Handler'); + // load basic plugins +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sysplugins' . DIRECTORY_SEPARATOR . 'internal.template.php'); +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sysplugins' . DIRECTORY_SEPARATOR . 'internal.Plugin_Handler.php'); +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'sysplugins' . DIRECTORY_SEPARATOR . 'internal.Run_Filter.php'); +// $this->loadPlugin($this->template_class); +// $this->loadPlugin('Smarty_Internal_Plugin_Handler'); +// $this->loadPlugin('Smarty_Internal_Run_Filter'); $this->plugin_handler = new Smarty_Internal_Plugin_Handler($this); - $this->loadPlugin('Smarty_Internal_Run_Filter'); $this->filter_handler = new Smarty_Internal_Run_Filter($this); if (!$this->debugging && $this->debugging_ctrl == 'URL') { if (isset($_SERVER['QUERY_STRING'])) { diff --git a/libs/sysplugins/internal.plugin_handler.php b/libs/sysplugins/internal.plugin_handler.php index 4698f511..367382c0 100644 --- a/libs/sysplugins/internal.plugin_handler.php +++ b/libs/sysplugins/internal.plugin_handler.php @@ -24,13 +24,43 @@ class Smarty_Internal_Plugin_Handler { public function __call($name, $args) { if ($this->loadSmartyPlugin($name, $args[1])) { - // call plugin + // call plugin return call_user_func_array($this->smarty->registered_plugins[$name][1], $args[0]); } else { // plugin not found throw new Exception("Unable to load plugin {$name}"); } } + public function executeModifier($name, $args, $check_array) + { + if ($this->loadSmartyPlugin($name, 'modifier')) { + // call plugin + if (!$check_array || !is_array($args[0])) { + return call_user_func_array($this->smarty->registered_plugins[$name][1], $args); + } else { + $args0 = $args[0]; + foreach ($args0 as $key => $arg0) { + $args[0] = $arg0; + $result[$key] = call_user_func_array($this->smarty->registered_plugins[$name][1], $args); + } + return $result; + } + } elseif (is_callable($name)) { + if (!$check_array || !is_array($args[0])) { + return call_user_func_array($name, $args); + } else { + $args0 = $args[0]; + foreach ($args0 as $key => $arg0) { + $args[0] = $arg0; + $result[$key] = call_user_func_array($name, $args); + } + return $result; + } + } else { + // plugin not found + throw new Exception("Unable to load plugin {$name}"); + } + } /** * Lazy loads plugin files * class name format: Smarty_PluginType_FuncName diff --git a/libs/sysplugins/internal.resource_registered.php b/libs/sysplugins/internal.resource_registered.php new file mode 100644 index 00000000..fc9e5499 --- /dev/null +++ b/libs/sysplugins/internal.resource_registered.php @@ -0,0 +1,125 @@ +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'; + + /** + * 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 strings + // return "string" for compiler error messages + $_filepath = $_template->resource_type .':'.$_template->resource_name; + + return $_filepath; + } + + /** + * Get timestamp to template source + * + * @param object $_template template object + * @return boolean false as string resources have no timestamp + */ + public function getTemplateTimestamp($_template) + { + // return timestamp + $time_stamp = false; + call_user_func_array($this->smarty->_plugins['resource'][$_template->resource_type][0][1], + array($_template->resource_name, &$time_stamp, $this->smarty)); + return $time_stamp; + } + + /** + * Retuen template source from resource name + * + * @param object $_template template object + * @return string content of template source + */ + public function getTemplateSource($_template) + { + // return template string + return call_user_func_array($this->smarty->_plugins['resource'][$_template->resource_type][0][0], + array($_template->resource_name, &$_template->template_source, $this->smarty)); + } + + /** + * Return flag that this resource uses the compiler + * + * @return boolean true + */ + public function usesCompiler() + { + // resource string is template, needs compiler + return true; + } + + /** + * Return flag that this resource is evaluated + * + * @return boolean true + */ + public function isEvaluated() + { + // compiled template is evaluated instead of saved to disk + return false; + } + + /** + * Get filepath to compiled template + * + * @param object $_template template object + * @return boolean return false as compiled template is not stored + */ + public function getCompiledFilepath($_template) + { + // $_filepath = md5($_template->resource_name); + $_filepath = (string)abs(crc32($_template->resource_name)); + // if use_sub_dirs, break file into directories + if ($_template->smarty->use_sub_dirs) { + $_filepath = substr($_filepath, 0, 3) . DIRECTORY_SEPARATOR + . substr($_filepath, 0, 2) . DIRECTORY_SEPARATOR + . substr($_filepath, 0, 1) . DIRECTORY_SEPARATOR + . $_filepath; + } + $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DIRECTORY_SEPARATOR : '^'; + if (isset($_template->compile_id)) { + $_filepath = $_template->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 .= DIRECTORY_SEPARATOR; + } + return $_compile_dir . $_filepath . '.' . basename($_template->resource_name) . $_cache . '.' . $_template->resource_type . $_template->smarty->php_ext; + } +} + +?> diff --git a/libs/sysplugins/internal.template.php b/libs/sysplugins/internal.template.php index 9f610d1c..80e89758 100644 --- a/libs/sysplugins/internal.template.php +++ b/libs/sysplugins/internal.template.php @@ -85,6 +85,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { $this->force_compile = $this->smarty->force_compile; $this->caching = $this->smarty->caching; $this->caching_lifetime = $this->smarty->caching_lifetime; + $this->force_cache = $this->smarty->force_cache; $this->cacher_class = $this->smarty->cacher_class; $this->caching_type = $this->smarty->default_caching_type; $this->security = $this->smarty->security; @@ -154,7 +155,9 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { public function getTemplateSource () { if ($this->template_source === null) { - $this->resource_objects[$this->resource_type]->getTemplateSource($this); + if (!$this->resource_objects[$this->resource_type]->getTemplateSource($this)) { + throw new Exception("Unable to read template '{$this->resource_name}'"); + } } return $this->template_source; } @@ -384,7 +387,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { { if ($this->isCached === null) { $this->isCached = false; - if ($this->caching && !$this->isEvaluated() && !$this->force_compile) { + if ($this->caching && !$this->isEvaluated() && !$this->force_compile && !$this->force_cache) { if ($this->getCachedTimestamp() === false) { return $this->isCached; } @@ -545,31 +548,37 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { } // load resource handler if required if (!isset($this->resource_objects[$this->resource_type])) { - // try sysplugins dir first - $_resource_class = "Smarty_Internal_Resource_{$this->resource_type}"; - if ($this->smarty->loadPlugin($_resource_class)) { - $this->resource_objects[$this->resource_type] = new $_resource_class($this->smarty); + // try registered resource + if (isset($this->smarty->_plugins['resource'][$this->resource_type])) { + $this->smarty->loadPlugin('Smarty_Internal_Resource_Registered'); + $this->resource_objects[$this->resource_type] = new Smarty_Internal_Resource_Registered($this->smarty); } else { - // try plugins dir - $_resource_class = "Smarty_Resource_{$this->resource_type}"; + // try sysplugins dir + $_resource_class = "Smarty_Internal_Resource_{$this->resource_type}"; if ($this->smarty->loadPlugin($_resource_class)) { $this->resource_objects[$this->resource_type] = new $_resource_class($this->smarty); } else { - // try streams - $_known_stream = stream_get_wrappers(); - if (in_array($this->resource_type, $_known_stream)) { - // is known stream - if ($this->smarty->security) { - $this->smarty->security_handler->isTrustedStream($this->resource_type); - } - if (!isset($this->resource_objects['stream'])) { - $this->smarty->loadPlugin('Smarty_Internal_Resource_Stream'); - $this->resource_objects['stream'] = new Smarty_Internal_Resource_Stream($this->smarty); - } - $this->resource_type = 'stream'; - $this->resource_name = str_replace(':', '://', $template_resource); + // try plugins dir + $_resource_class = "Smarty_Resource_{$this->resource_type}"; + if ($this->smarty->loadPlugin($_resource_class)) { + $this->resource_objects[$this->resource_type] = new $_resource_class($this->smarty); } else { - throw new Exception('Unkown resource type \'' . $this->resource_type . '\''); + // try streams + $_known_stream = stream_get_wrappers(); + if (in_array($this->resource_type, $_known_stream)) { + // is known stream + if ($this->smarty->security) { + $this->smarty->security_handler->isTrustedStream($this->resource_type); + } + if (!isset($this->resource_objects['stream'])) { + $this->smarty->loadPlugin('Smarty_Internal_Resource_Stream'); + $this->resource_objects['stream'] = new Smarty_Internal_Resource_Stream($this->smarty); + } + $this->resource_type = 'stream'; + $this->resource_name = str_replace(':', '://', $template_resource); + } else { + throw new Exception('Unkown resource type \'' . $this->resource_type . '\''); + } } } } @@ -577,7 +586,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { // cache template object under a unique ID // do not cache string resources if ($this->resource_type != 'string') { - $this->smarty->template_objects[$this->buildTemplateId ($this->template_resource, $this->cache_id, $this->compile_id)] = $this; + $this->smarty->template_objects[$this->buildTemplateId ($this->template_resource, $this->cache_id, $this->compile_id)] = $this; } return true; } @@ -591,7 +600,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { $file = $this->resource_name; } foreach((array)$this->smarty->template_dir as $_template_dir) { - if (strpos('/\\',substr($_template_dir, -1)) === false) { + if (strpos('/\\', substr($_template_dir, -1)) === false) { $_template_dir .= DIRECTORY_SEPARATOR; } diff --git a/libs/sysplugins/internal.templatecompilerbase.php b/libs/sysplugins/internal.templatecompilerbase.php index 0ee4d005..bc1fb8dd 100644 --- a/libs/sysplugins/internal.templatecompilerbase.php +++ b/libs/sysplugins/internal.templatecompilerbase.php @@ -24,11 +24,6 @@ class Smarty_Internal_TemplateCompilerBase { */ public function __construct() { - // get required plugins - if (!is_object($this->smarty->filter_handler) && (isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre']) || isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post']))) { - $this->smarty->loadPlugin('Smarty_Internal_Run_Filter'); - $this->smarty->filter_handler = new Smarty_Internal_Run_Filter; - } } // abstract function doCompile($_content); /** diff --git a/libs/sysplugins/internal.templateparser.php b/libs/sysplugins/internal.templateparser.php index 920b53ee..a62ce279 100644 --- a/libs/sysplugins/internal.templateparser.php +++ b/libs/sysplugins/internal.templateparser.php @@ -1970,18 +1970,18 @@ static public $yy_action = array( #line 1975 "internal.templateparser.php" #line 151 "internal.templateparser.y" function yy_r18(){ preg_match('/\s*/',$this->yystack[$this->yyidx + -5]->minor,$s); $this->_retvalue = $s[0].''.$this->compiler->compileTag($this->yystack[$this->yyidx + -4]->minor,$this->yystack[$this->yyidx + -1]->minor).'smarty->plugin_handler->loadSmartyPlugin($this->yystack[$this->yyidx + -3]->minor[0],'modifier')) { - $this->_retvalue .= "\$_smarty_tpl->smarty->plugin_handler->".$this->yystack[$this->yyidx + -3]->minor[0] . "(array(ob_get_clean()". $this->yystack[$this->yyidx + -2]->minor ."),'modifier');?>"; + if ($this->smarty->plugin_handler->loadSmartyPlugin($this->yystack[$this->yyidx + -3]->minor[0],'modifier')) { + $this->_retvalue .= "\$_smarty_tpl->smarty->plugin_handler->executeModifier('".$this->yystack[$this->yyidx + -3]->minor[0] . "',array(ob_get_clean()" . $this->yystack[$this->yyidx + -2]->minor. "),".$this->yystack[$this->yyidx + -3]->minor[1].");?>"; } else { - if ($this->yystack[$this->yyidx + -3]->minor[0] == 'isset' || $this->yystack[$this->yyidx + -3]->minor[0] == 'empty' || is_callable($this->yystack[$this->yyidx + -3]->minor[0])) { + if (is_callable($this->yystack[$this->yyidx + -3]->minor[0])) { if (!$this->template->security || $this->smarty->security_handler->isTrustedModifier($this->yystack[$this->yyidx + -3]->minor[0], $this->compiler)) { - $this->_retvalue .= $this->yystack[$this->yyidx + -3]->minor[0] . "(ob_get_clean()". $this->yystack[$this->yyidx + -2]->minor .");?>"; + $this->_retvalue .= "\$_smarty_tpl->smarty->plugin_handler->executeModifier('".$this->yystack[$this->yyidx + -3]->minor[0] . "',array(ob_get_clean()" . $this->yystack[$this->yyidx + -2]->minor. "),".$this->yystack[$this->yyidx + -3]->minor[1].");?>"; } } else { $this->compiler->trigger_template_error ("unknown modifier \"" . $this->yystack[$this->yyidx + -3]->minor[0] . "\""); } } - } + } #line 1990 "internal.templateparser.php" #line 165 "internal.templateparser.y" function yy_r19(){ preg_match('/\s*/',$this->yystack[$this->yyidx + -3]->minor,$s); $this->_retvalue = $s[0].$this->compiler->compileTag($this->yystack[$this->yyidx + -2]->minor.'close',$this->yystack[$this->yyidx + -1]->minor); } @@ -2053,13 +2053,13 @@ static public $yy_action = array( function yy_r37(){$this->_retvalue = '$_smarty_tpl->getStreamVariable(\''. $this->yystack[$this->yyidx + -2]->minor .'://'. $this->yystack[$this->yyidx + 0]->minor . '\')'; } #line 2059 "internal.templateparser.php" #line 227 "internal.templateparser.y" - function yy_r38(){ + function yy_r38(){ if ($this->smarty->plugin_handler->loadSmartyPlugin($this->yystack[$this->yyidx + -1]->minor[0],'modifier')) { - $this->_retvalue = "\$_smarty_tpl->smarty->plugin_handler->".$this->yystack[$this->yyidx + -1]->minor[0] . "(array(". $this->yystack[$this->yyidx + -2]->minor . $this->yystack[$this->yyidx + 0]->minor ."),'modifier')"; + $this->_retvalue = "\$_smarty_tpl->smarty->plugin_handler->executeModifier('".$this->yystack[$this->yyidx + -1]->minor[0] . "',array(". $this->yystack[$this->yyidx + -2]->minor . $this->yystack[$this->yyidx + 0]->minor. "),".$this->yystack[$this->yyidx + -1]->minor[1].")"; } else { - if ($this->yystack[$this->yyidx + -1]->minor[0] == 'isset' || $this->yystack[$this->yyidx + -1]->minor[0] == 'empty' || is_callable($this->yystack[$this->yyidx + -1]->minor[0])) { + if (is_callable($this->yystack[$this->yyidx + -1]->minor[0])) { if (!$this->template->security || $this->smarty->security_handler->isTrustedModifier($this->yystack[$this->yyidx + -1]->minor[0], $this->compiler)) { - $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor[0] . "(". $this->yystack[$this->yyidx + -2]->minor . $this->yystack[$this->yyidx + 0]->minor .")"; + $this->_retvalue = "\$_smarty_tpl->smarty->plugin_handler->executeModifier('".$this->yystack[$this->yyidx + -1]->minor[0] . "',array(". $this->yystack[$this->yyidx + -2]->minor . $this->yystack[$this->yyidx + 0]->minor. "),".$this->yystack[$this->yyidx + -1]->minor[1].")"; } } else { $this->compiler->trigger_template_error ("unknown modifier \"" . $this->yystack[$this->yyidx + -1]->minor[0] . "\""); @@ -2205,10 +2205,10 @@ static public $yy_action = array( function yy_r96(){ return; } #line 2211 "internal.templateparser.php" #line 393 "internal.templateparser.y" - function yy_r97(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor,true); } + function yy_r97(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor,'false'); } #line 2214 "internal.templateparser.php" #line 394 "internal.templateparser.y" - function yy_r98(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor,false); } + function yy_r98(){ $this->_retvalue = array($this->yystack[$this->yyidx + 0]->minor,'true'); } #line 2217 "internal.templateparser.php" #line 401 "internal.templateparser.y" function yy_r99(){ $this->_retvalue = $this->yystack[$this->yyidx + -1]->minor.$this->yystack[$this->yyidx + 0]->minor; }