From 494993de3857357a2750b901d538aeb8dea64dbd Mon Sep 17 00:00:00 2001 From: mohrt Date: Thu, 23 Jan 2003 23:33:29 +0000 Subject: [PATCH] add support for object registration --- NEWS | 6 +-- Smarty.class.php | 33 +++++++++++++-- Smarty_Compiler.class.php | 75 +++++++++++++++++++++++++++++----- libs/Smarty.class.php | 33 +++++++++++++-- libs/Smarty_Compiler.class.php | 75 +++++++++++++++++++++++++++++----- 5 files changed, 191 insertions(+), 31 deletions(-) diff --git a/NEWS b/NEWS index 543e617c..260d3032 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,6 @@ - - add debug template to secure dir (Ferdinand Beyer, Monte) - - add template_dir to secure_dir by default (Ferdinand - Beyer, Monte) + - add support for object registration (Monte) + - add debug template to secure dir, add template_dir + to secure_dir by default (Ferdinand Beyer, Monte) - added support for object method access (Monte) - fixed bug with directories named '0' (Frank Bauer, Monte) - add javascript parameter to escape modifier (Monte) diff --git a/Smarty.class.php b/Smarty.class.php index 21a45af0..ccd9258f 100644 --- a/Smarty.class.php +++ b/Smarty.class.php @@ -334,6 +334,26 @@ class Smarty unset($this->_plugins['function'][$function]); } +/*======================================================================*\ + Function: register_object + Purpose: Registers object to be used in templates +\*======================================================================*/ + function register_object($object, &$object_impl) + { + $this->_plugins['object'][$object] = + array(&$object_impl, null, null, false); + } + +/*======================================================================*\ + function: unregister_object + Purpose: Unregisters object +\*======================================================================*/ + function unregister_object($object) + { + unset($this->_plugins['object'][$object]); + } + + /*======================================================================*\ Function: register_block Purpose: Registers block function to be used in templates @@ -614,10 +634,12 @@ class Smarty function fetch($_smarty_tpl_file, $_smarty_cache_id = null, $_smarty_compile_id = null, $_smarty_display = false) { $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(error_reporting() & ~E_NOTICE); + if($this->security && !in_array($this->template_dir, $this->secure_dir)) { // add template_dir to secure_dir array array_unshift($this->secure_dir, $this->template_dir); } + if (!$this->debugging && $this->debugging_ctrl == 'URL' && strstr($GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'], $this->_smarty_debug_id)) { // enable debugging from URL @@ -1868,10 +1890,10 @@ function _run_insert_handler($args) function _load_plugins($plugins) { - foreach ($plugins as $plugin_info) { + foreach ($plugins as $plugin_info) { list($type, $name, $tpl_file, $tpl_line, $delayed_loading) = $plugin_info; $plugin = &$this->_plugins[$type][$name]; - + /* * We do not load plugin more than once for each instance of Smarty. * The following code checks for that. The plugin can also be @@ -1882,10 +1904,13 @@ function _run_insert_handler($args) * whether the dynamically registered plugin function has been * checked for existence yet or not. */ - if (isset($plugin)) { + if (isset($plugin)) { if (!$plugin[3]) { - if (!function_exists($plugin[0])) { + // no line number, see if it is valid + if ($type == 'function' && !function_exists($plugin[0])) { $this->_trigger_plugin_error("$type '$name' is not implemented", $tpl_file, $tpl_line, __FILE__, __LINE__); + } elseif ($type == 'object' && !is_object($plugin[0])) { + $this->_trigger_plugin_error("$type '$name' is not an object", $tpl_file, $tpl_line, __FILE__, __LINE__); } else { $plugin[1] = $tpl_file; $plugin[2] = $tpl_line; diff --git a/Smarty_Compiler.class.php b/Smarty_Compiler.class.php index 0e513f1a..49d2cd65 100644 --- a/Smarty_Compiler.class.php +++ b/Smarty_Compiler.class.php @@ -144,7 +144,11 @@ class Smarty_Compiler extends Smarty { // foo123 // _foo_bar $this->_func_regexp = '[a-zA-Z_]\w*'; - + + // matches valid registered object: + // foo.bar + $this->_reg_obj_regexp = '[a-zA-Z_]\w*\.[a-zA-Z_]\w*'; + // matches valid parameter values: // true // $foo @@ -342,13 +346,14 @@ class Smarty_Compiler extends Smarty { \*======================================================================*/ function _compile_tag($template_tag) { - + /* Matched comment. */ if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*') return ''; /* Split tag into two three parts: command, command modifiers and the arguments. */ - if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) + if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp + . '|' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) (?:\s+(.*))?$ /xs', $template_tag, $match)) { $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__); @@ -357,17 +362,22 @@ class Smarty_Compiler extends Smarty { $tag_command = $match[1]; $tag_modifier = isset($match[2]) ? $match[2] : null; $tag_args = isset($match[3]) ? $match[3] : null; - - /* If the tag name is not a function, we process it. */ - if (!preg_match('!^\/?' . $this->_func_regexp . '$!', $tag_command)) { - $_tag_attrs = $this->_parse_attrs($tag_args); - $return = $this->_parse_var_props($tag_command . $tag_modifier, $_tag_attrs); + + + /* If the tag name is a variable or object, we process it. */ + if (preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$!', $tag_command)) { + $return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args)); if(isset($_tag_attrs['assign'])) { return "assign('" . $this->_dequote($_tag_attrs['assign']) . "', $return ); ?>\n"; } else { return "\n"; } } + + /* If the tag name is a registered object, we process it. */ + if (preg_match('!^' . $this->_reg_obj_regexp . '$!', $tag_command)) { + return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier); + } switch ($tag_command) { case 'include': @@ -453,7 +463,7 @@ class Smarty_Compiler extends Smarty { case 'insert': return $this->_compile_insert_tag($tag_args); - default: + default: if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) { return $output; } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) { @@ -631,6 +641,51 @@ class Smarty_Compiler extends Smarty { return '\n"; } +/*======================================================================*\ + Function: _compile_registered_object_tag + Purpose: compile a registered object tag +\*======================================================================*/ + function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier) + { + list($object, $obj_comp) = explode('.', $tag_command); + $this->_add_plugin('object', $object); + + $arg_list = array(); + if(count($attrs)) { + $_assign_var = false; + foreach ($attrs as $arg_name => $arg_value) { + if($arg_name == 'assign') { + $_assign_var = $arg_value; + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + if(!$this->_plugins['object'][$object][0]) { + $this->_trigger_plugin_error("Smarty error: Registered '$object' is not an object"); + } elseif(method_exists($this->_plugins['object'][$object][0], $obj_comp)) { + // method + $return = "\$this->_plugins['object']['$object'][0]->$obj_comp(array(".implode(',', (array)$arg_list)."), \$this)"; + } else { + // property + $return = "\$this->_plugins['object']['$object'][0]->$obj_comp"; + } + + if($tag_modifier != '') { + $this->_parse_modifiers($return, $tag_modifier); + } + + if($_assign_var) { + return "assign('" . $this->_dequote($_assign_var) ."', $return); ?>\n"; + } else { + return '\n"; + } + } + + /*======================================================================*\ Function: _compile_insert_tag @@ -1186,7 +1241,7 @@ class Smarty_Compiler extends Smarty { 1 - expecting '=' 2 - expecting attribute value (not '=') */ $state = 0; - + foreach ($tokens as $token) { switch ($state) { case 0: diff --git a/libs/Smarty.class.php b/libs/Smarty.class.php index 21a45af0..ccd9258f 100644 --- a/libs/Smarty.class.php +++ b/libs/Smarty.class.php @@ -334,6 +334,26 @@ class Smarty unset($this->_plugins['function'][$function]); } +/*======================================================================*\ + Function: register_object + Purpose: Registers object to be used in templates +\*======================================================================*/ + function register_object($object, &$object_impl) + { + $this->_plugins['object'][$object] = + array(&$object_impl, null, null, false); + } + +/*======================================================================*\ + function: unregister_object + Purpose: Unregisters object +\*======================================================================*/ + function unregister_object($object) + { + unset($this->_plugins['object'][$object]); + } + + /*======================================================================*\ Function: register_block Purpose: Registers block function to be used in templates @@ -614,10 +634,12 @@ class Smarty function fetch($_smarty_tpl_file, $_smarty_cache_id = null, $_smarty_compile_id = null, $_smarty_display = false) { $_smarty_old_error_level = $this->debugging ? error_reporting() : error_reporting(error_reporting() & ~E_NOTICE); + if($this->security && !in_array($this->template_dir, $this->secure_dir)) { // add template_dir to secure_dir array array_unshift($this->secure_dir, $this->template_dir); } + if (!$this->debugging && $this->debugging_ctrl == 'URL' && strstr($GLOBALS['HTTP_SERVER_VARS']['QUERY_STRING'], $this->_smarty_debug_id)) { // enable debugging from URL @@ -1868,10 +1890,10 @@ function _run_insert_handler($args) function _load_plugins($plugins) { - foreach ($plugins as $plugin_info) { + foreach ($plugins as $plugin_info) { list($type, $name, $tpl_file, $tpl_line, $delayed_loading) = $plugin_info; $plugin = &$this->_plugins[$type][$name]; - + /* * We do not load plugin more than once for each instance of Smarty. * The following code checks for that. The plugin can also be @@ -1882,10 +1904,13 @@ function _run_insert_handler($args) * whether the dynamically registered plugin function has been * checked for existence yet or not. */ - if (isset($plugin)) { + if (isset($plugin)) { if (!$plugin[3]) { - if (!function_exists($plugin[0])) { + // no line number, see if it is valid + if ($type == 'function' && !function_exists($plugin[0])) { $this->_trigger_plugin_error("$type '$name' is not implemented", $tpl_file, $tpl_line, __FILE__, __LINE__); + } elseif ($type == 'object' && !is_object($plugin[0])) { + $this->_trigger_plugin_error("$type '$name' is not an object", $tpl_file, $tpl_line, __FILE__, __LINE__); } else { $plugin[1] = $tpl_file; $plugin[2] = $tpl_line; diff --git a/libs/Smarty_Compiler.class.php b/libs/Smarty_Compiler.class.php index 0e513f1a..49d2cd65 100644 --- a/libs/Smarty_Compiler.class.php +++ b/libs/Smarty_Compiler.class.php @@ -144,7 +144,11 @@ class Smarty_Compiler extends Smarty { // foo123 // _foo_bar $this->_func_regexp = '[a-zA-Z_]\w*'; - + + // matches valid registered object: + // foo.bar + $this->_reg_obj_regexp = '[a-zA-Z_]\w*\.[a-zA-Z_]\w*'; + // matches valid parameter values: // true // $foo @@ -342,13 +346,14 @@ class Smarty_Compiler extends Smarty { \*======================================================================*/ function _compile_tag($template_tag) { - + /* Matched comment. */ if ($template_tag{0} == '*' && $template_tag{strlen($template_tag) - 1} == '*') return ''; /* Split tag into two three parts: command, command modifiers and the arguments. */ - if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) + if(! preg_match('/^(?:(' . $this->_obj_call_regexp . '|' . $this->_var_regexp + . '|' . $this->_reg_obj_regexp . '|\/?' . $this->_func_regexp . ')(' . $this->_mod_regexp . '*)) (?:\s+(.*))?$ /xs', $template_tag, $match)) { $this->_syntax_error("unrecognized tag: $template_tag", E_USER_ERROR, __FILE__, __LINE__); @@ -357,17 +362,22 @@ class Smarty_Compiler extends Smarty { $tag_command = $match[1]; $tag_modifier = isset($match[2]) ? $match[2] : null; $tag_args = isset($match[3]) ? $match[3] : null; - - /* If the tag name is not a function, we process it. */ - if (!preg_match('!^\/?' . $this->_func_regexp . '$!', $tag_command)) { - $_tag_attrs = $this->_parse_attrs($tag_args); - $return = $this->_parse_var_props($tag_command . $tag_modifier, $_tag_attrs); + + + /* If the tag name is a variable or object, we process it. */ + if (preg_match('!^' . $this->_obj_call_regexp . '|' . $this->_var_regexp . '$!', $tag_command)) { + $return = $this->_parse_var_props($tag_command . $tag_modifier, $this->_parse_attrs($tag_args)); if(isset($_tag_attrs['assign'])) { return "assign('" . $this->_dequote($_tag_attrs['assign']) . "', $return ); ?>\n"; } else { return "\n"; } } + + /* If the tag name is a registered object, we process it. */ + if (preg_match('!^' . $this->_reg_obj_regexp . '$!', $tag_command)) { + return $this->_compile_registered_object_tag($tag_command, $this->_parse_attrs($tag_args), $tag_modifier); + } switch ($tag_command) { case 'include': @@ -453,7 +463,7 @@ class Smarty_Compiler extends Smarty { case 'insert': return $this->_compile_insert_tag($tag_args); - default: + default: if ($this->_compile_compiler_tag($tag_command, $tag_args, $output)) { return $output; } else if ($this->_compile_block_tag($tag_command, $tag_args, $tag_modifier, $output)) { @@ -631,6 +641,51 @@ class Smarty_Compiler extends Smarty { return '\n"; } +/*======================================================================*\ + Function: _compile_registered_object_tag + Purpose: compile a registered object tag +\*======================================================================*/ + function _compile_registered_object_tag($tag_command, $attrs, $tag_modifier) + { + list($object, $obj_comp) = explode('.', $tag_command); + $this->_add_plugin('object', $object); + + $arg_list = array(); + if(count($attrs)) { + $_assign_var = false; + foreach ($attrs as $arg_name => $arg_value) { + if($arg_name == 'assign') { + $_assign_var = $arg_value; + continue; + } + if (is_bool($arg_value)) + $arg_value = $arg_value ? 'true' : 'false'; + $arg_list[] = "'$arg_name' => $arg_value"; + } + } + + if(!$this->_plugins['object'][$object][0]) { + $this->_trigger_plugin_error("Smarty error: Registered '$object' is not an object"); + } elseif(method_exists($this->_plugins['object'][$object][0], $obj_comp)) { + // method + $return = "\$this->_plugins['object']['$object'][0]->$obj_comp(array(".implode(',', (array)$arg_list)."), \$this)"; + } else { + // property + $return = "\$this->_plugins['object']['$object'][0]->$obj_comp"; + } + + if($tag_modifier != '') { + $this->_parse_modifiers($return, $tag_modifier); + } + + if($_assign_var) { + return "assign('" . $this->_dequote($_assign_var) ."', $return); ?>\n"; + } else { + return '\n"; + } + } + + /*======================================================================*\ Function: _compile_insert_tag @@ -1186,7 +1241,7 @@ class Smarty_Compiler extends Smarty { 1 - expecting '=' 2 - expecting attribute value (not '=') */ $state = 0; - + foreach ($tokens as $token) { switch ($state) { case 0: