From 1757b274d630d8d1f9af2c405c3da1f83f0d530f Mon Sep 17 00:00:00 2001 From: "uwe.tews@googlemail.com" Date: Mon, 28 Mar 2011 22:18:39 +0000 Subject: [PATCH] - bugfix on error message in smarty_internal_compile_block.php - bugfix mb handling in strip modifier - bugfix for Smarty2 style registered compiler function on unnamed attribute passing like {tag $foo $bar} --- change_log.txt | 5 + libs/plugins/modifiercompiler.strip.php | 4 +- .../smarty_internal_compile_block.php | 36 +-- .../smarty_internal_templatecompilerbase.php | 210 +++++++++--------- 4 files changed, 132 insertions(+), 123 deletions(-) diff --git a/change_log.txt b/change_log.txt index 10cfd9b8..147da3aa 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,9 @@ ===== SVN trunk ===== +29/03/2011 +- bugfix on error message in smarty_internal_compile_block.php +- bugfix mb handling in strip modifier +- bugfix for Smarty2 style registered compiler function on unnamed attribute passing like {tag $foo $bar} + 17/03/2011 - bugfix on default {function} parameters when {function} was used in nocache sections - bugfix on compiler object destruction. compiler_object property was by mistake unset. diff --git a/libs/plugins/modifiercompiler.strip.php b/libs/plugins/modifiercompiler.strip.php index ab5b7688..55b98e0e 100644 --- a/libs/plugins/modifiercompiler.strip.php +++ b/libs/plugins/modifiercompiler.strip.php @@ -26,8 +26,8 @@ function smarty_modifiercompiler_strip($params, $compiler) { if (!isset($params[1])) { $params[1] = "' '"; - } - return "preg_replace('!\s+!', {$params[1]},{$params[0]})"; + } + return "preg_replace('!\s+!u', {$params[1]},{$params[0]})"; } ?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_compile_block.php b/libs/sysplugins/smarty_internal_compile_block.php index cd1ca281..fc003dd7 100644 --- a/libs/sysplugins/smarty_internal_compile_block.php +++ b/libs/sysplugins/smarty_internal_compile_block.php @@ -1,12 +1,12 @@ smarty->inheritance = true; // must merge includes - $this->compiler->smarty->merge_compiled_includes = true; + $this->compiler->smarty->merge_compiled_includes = true; $compiler->parser->current_buffer = new _smarty_template_buffer($compiler->parser); $compiler->has_code = false; return true; - } + } static function saveBlockData($block_content, $block_tag, $template, $filepath) @@ -53,7 +53,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { $error_text = 'Syntax Error in template "' . $template->getTemplateFilepath() . '" "' . htmlspecialchars($block_tag) . '" illegal options'; throw new SmartyCompilerException($error_text); } else { - $_name = trim($_match[3], '\'"'); + $_name = trim($_match[3], '\'"'); // replace {$smarty.block.child} if (strpos($block_content, $template->smarty->left_delimiter . '$smarty.block.child' . $template->smarty->right_delimiter) !== false) { if (isset($template->block_data[$_name])) { @@ -63,8 +63,8 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { } else { $block_content = str_replace($template->smarty->left_delimiter . '$smarty.block.child' . $template->smarty->right_delimiter, '', $block_content); - } - } + } + } if (isset($template->block_data[$_name])) { if (strpos($template->block_data[$_name]['source'], '%%%%SMARTY_PARENT%%%%') !== false) { $template->block_data[$_name]['source'] = @@ -73,17 +73,17 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { $template->block_data[$_name]['source'] .= $block_content; } elseif ($template->block_data[$_name]['mode'] == 'append') { $template->block_data[$_name]['source'] = $block_content . $template->block_data[$_name]['source']; - } + } } else { $template->block_data[$_name]['source'] = $block_content; - } + } if ($_match[6] == 'append') { $template->block_data[$_name]['mode'] = 'append'; } elseif ($_match[6] == 'prepend') { $template->block_data[$_name]['mode'] = 'prepend'; } else { $template->block_data[$_name]['mode'] = 'replace'; - } + } $template->block_data[$_name]['file'] = $filepath; } } @@ -104,13 +104,13 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { $compiler->template->block_data[$_name]['compiled'] = true; } if ($_name == null) { - $compiler->trigger_template_error('{$smarty.block.child} used out of context', $this->compiler->lex->taglineno); + $compiler->trigger_template_error('{$smarty.block.child} used out of context', $compiler->lex->taglineno); } // undefined child? if (!isset($compiler->template->block_data[$_name])) { return ''; } - $_tpl = new Smarty_Internal_template ('eval:' . $compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id, + $_tpl = new Smarty_Internal_template ('eval:' . $compiler->template->block_data[$_name]['source'], $compiler->smarty, $compiler->template, $compiler->template->cache_id, $compiler->template->compile_id = null, $compiler->template->caching, $compiler->template->cache_lifetime); $_tpl->properties['nocache_hash'] = $compiler->template->properties['nocache_hash']; $_tpl->template_filepath = $compiler->template->block_data[$_name]['file']; @@ -154,7 +154,7 @@ class Smarty_Internal_Compile_Block extends Smarty_Internal_CompileBase { class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase { /** * Compiles code for the {/block} tag - * + * * @param array $args array with attributes from parser * @param object $compiler compiler object * @return string compiled code @@ -163,7 +163,7 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase { { $this->compiler = $compiler; $this->smarty = $compiler->smarty; - $this->compiler->has_code = true; + $this->compiler->has_code = true; // check and get attributes $_attr = $this->_get_attributes($args); $saved_data = $this->_close_tag(array('block')); @@ -182,6 +182,6 @@ class Smarty_Internal_Compile_Blockclose extends Smarty_Internal_CompileBase { // $_output content has already nocache code processed $compiler->suppressNocacheProcessing = true; return $_output; - } -} + } +} ?> \ No newline at end of file diff --git a/libs/sysplugins/smarty_internal_templatecompilerbase.php b/libs/sysplugins/smarty_internal_templatecompilerbase.php index 8372a3db..b8b341e7 100644 --- a/libs/sysplugins/smarty_internal_templatecompilerbase.php +++ b/libs/sysplugins/smarty_internal_templatecompilerbase.php @@ -1,12 +1,12 @@ nocache_hash = str_replace('.', '-', uniqid(rand(), true)); - } + } /** * Methode to compile a Smarty template - * + * * @param $template template object to compile * @return bool true if compiling succeeded, false if it failed */ @@ -46,38 +46,38 @@ class Smarty_Internal_TemplateCompilerBase { $template->properties['nocache_hash'] = $this->nocache_hash; } else { $this->nocache_hash = $template->properties['nocache_hash']; - } + } // flag for nochache sections $this->nocache = false; - $this->tag_nocache = false; + $this->tag_nocache = false; // save template object in compiler class $this->template = $template; - $this->smarty->_current_file = $saved_filepath = $this->template->getTemplateFilepath(); + $this->smarty->_current_file = $saved_filepath = $this->template->getTemplateFilepath(); // template header code $template_header = ''; if (!$template->suppressHeader) { $template_header .= "template->getTemplateFilepath() . "\" */ ?>\n"; - } + } do { // flag for aborting current and start recompile - $this->abort_and_recompile = false; + $this->abort_and_recompile = false; // get template source - $_content = $template->getTemplateSource(); + $_content = $template->getTemplateSource(); // run prefilter if required if (isset($this->smarty->autoload_filters['pre']) || isset($this->smarty->registered_filters['pre'])) { $template->template_source = $_content = Smarty_Internal_Filter_Handler::runFilter('pre', $_content, $template); - } + } // on empty template just return header if ($_content == '') { if ($template->suppressFileDependency) { $template->compiled_template = ''; } else { $template->compiled_template = $template_header . $template->createPropertyHeader(); - } + } return true; - } + } // call compiler $_compiled_code = $this->doCompile($_content); } while ($this->abort_and_recompile); @@ -88,26 +88,26 @@ class Smarty_Internal_TemplateCompilerBase { $template->compiled_template = $_compiled_code; } else { $template->compiled_template = $template_header . $template->createPropertyHeader() . $_compiled_code; - } + } // run postfilter if required if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { $template->compiled_template = Smarty_Internal_Filter_Handler::runFilter('post', $template->compiled_template, $template); - } - } + } + } /** * Compile Tag - * + * * This is a call back from the lexer/parser * It executes the required compile plugin for the Smarty tag - * + * * @param string $tag tag name * @param array $args array with tag attributes * @param array $parameter array with compilation parameter * @return string compiled code */ public function compileTag($tag, $args, $parameter = array()) - { + { // $args contains the attributes parsed and compiled by the lexer/parser // assume that tag does compile into code, but creates no HTML output $this->has_code = true; @@ -115,7 +115,7 @@ class Smarty_Internal_TemplateCompilerBase { // log tag/attributes if (isset($this->smarty->get_used_tags) && $this->smarty->get_used_tags) { $this->used_tags[] = array($tag,$args); - } + } // check nocache option flag if (in_array("'nocache'",$args) || in_array(array('nocache'=>'true'),$args) || in_array(array('nocache'=>'"true"'),$args) || in_array(array('nocache'=>"'true'"),$args)) { @@ -127,8 +127,8 @@ class Smarty_Internal_TemplateCompilerBase { // template defined by {template} tag $args['_attr']['name'] = "'" . $tag . "'"; $_output = $this->callTagCompiler('call', $args, $parameter); - } - } + } + } if ($_output !== false) { if ($_output !== true) { // did we get compiled code @@ -136,11 +136,11 @@ class Smarty_Internal_TemplateCompilerBase { // Does it create output? if ($this->has_output) { $_output .= "\n"; - } + } // return compiled code return $_output; - } - } + } + } // tag did not produce compiled code return ''; } else { @@ -149,9 +149,9 @@ class Smarty_Internal_TemplateCompilerBase { foreach ($args['_attr'] as $key => $attribute) { if (is_array($attribute)) { $args = array_merge($args, $attribute); - } - } - } + } + } + } // not an internal compiler tag if (strlen($tag) < 6 || substr($tag, -5) != 'close') { // check if tag is a registered object @@ -164,20 +164,24 @@ class Smarty_Internal_TemplateCompilerBase { return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); } else { return $this->trigger_template_error ('unallowed methode "' . $methode . '" in registered object "' . $tag . '"', $this->lex->taglineno); - } - } + } + } // check if tag is registered foreach (array(Smarty::PLUGIN_COMPILER, Smarty::PLUGIN_FUNCTION, Smarty::PLUGIN_BLOCK) as $type) { if (isset($this->smarty->registered_plugins[$type][$tag])) { // if compiler function plugin call it now if ($type == Smarty::PLUGIN_COMPILER) { $new_args = array(); - foreach ($args as $mixed) { - $new_args = array_merge($new_args, $mixed); - } + foreach ($args as $key => $mixed) { + if (is_array($mixed)) { + $new_args = array_merge($new_args, $mixed); + } else { + $new_args[$key] = $mixed; + } + } if (!$this->smarty->registered_plugins[$type][$tag][1]) { $this->tag_nocache = true; - } + } $function = $this->smarty->registered_plugins[$type][$tag][0]; if (!is_array($function)) { return $function($new_args, $this); @@ -185,14 +189,14 @@ class Smarty_Internal_TemplateCompilerBase { return $this->smarty->registered_plugins[$type][$tag][0][0]->$function[1]($new_args, $this); } else { return call_user_func_array($this->smarty->registered_plugins[$type][$tag][0], array($new_args, $this)); - } - } + } + } // compile registered function or block function if ($type == Smarty::PLUGIN_FUNCTION || $type == Smarty::PLUGIN_BLOCK) { return $this->callTagCompiler('private_registered_' . $type, $args, $parameter, $tag); - } - } - } + } + } + } // check plugins from plugins folder foreach ($this->smarty->plugin_search_order as $plugin_type) { if ($plugin_type == Smarty::PLUGIN_BLOCK && $this->smarty->loadPlugin('smarty_compiler_' . $tag)) { @@ -206,25 +210,25 @@ class Smarty_Internal_TemplateCompilerBase { } else { $new_args[$key] = $mixed; } - } + } return $plugin($new_args, $this->smarty); - } + } if (class_exists($plugin, false)) { $plugin_object = new $plugin; if (method_exists($plugin_object, 'compile')) { return $plugin_object->compile($args, $this); - } - } + } + } throw new SmartyException("Plugin \"{$tag}\" not callable"); } else { if ($function = $this->getPlugin($tag, $plugin_type)) { return $this->callTagCompiler('private_' . $plugin_type . '_plugin', $args, $parameter, $tag, $function); - } - } - } + } + } + } } else { // compile closing tag of block function - $base_tag = substr($tag, 0, -5); + $base_tag = substr($tag, 0, -5); // check if closing tag is a registered object if (isset($this->smarty->registered_objects[$base_tag]) && isset($parameter['object_methode'])) { $methode = $parameter['object_methode']; @@ -232,41 +236,41 @@ class Smarty_Internal_TemplateCompilerBase { return $this->callTagCompiler('private_object_block_function', $args, $parameter, $tag, $methode); } else { return $this->trigger_template_error ('unallowed closing tag methode "' . $methode . '" in registered object "' . $base_tag . '"', $this->lex->taglineno); - } - } + } + } // registered block tag ? if (isset($this->smarty->registered_plugins[Smarty::PLUGIN_BLOCK][$base_tag])) { return $this->callTagCompiler('private_registered_block', $args, $parameter, $tag); - } + } // block plugin? if ($function = $this->getPlugin($base_tag, Smarty::PLUGIN_BLOCK)) { return $this->callTagCompiler('private_block_plugin', $args, $parameter, $tag, $function); - } + } if ($this->smarty->loadPlugin('smarty_compiler_' . $tag)) { $plugin = 'smarty_compiler_' . $tag; if (is_callable($plugin)) { return $plugin($args, $this->smarty); - } + } if (class_exists($plugin, false)) { $plugin_object = new $plugin; if (method_exists($plugin_object, 'compile')) { return $plugin_object->compile($args, $this); - } - } + } + } throw new SmartyException("Plugin \"{$tag}\" not callable"); - } - } + } + } $this->trigger_template_error ("unknown tag \"" . $tag . "\"", $this->lex->taglineno); - } - } + } + } /** * lazy loads internal compile plugin for tag and calls the compile methode - * + * * compile objects cached for reuse. * class name format: Smarty_Internal_Compile_TagName * plugin filename format: Smarty_Internal_Tagname.php - * + * * @param $tag string tag name * @param $args array with tag attributes * @param $param1 optional parameter @@ -275,27 +279,27 @@ class Smarty_Internal_TemplateCompilerBase { * @return string compiled code */ public function callTagCompiler($tag, $args, $param1 = null, $param2 = null, $param3 = null) - { + { // re-use object if already exists if (isset(self::$_tag_objects[$tag])) { // compile this tag return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); - } + } // lazy load internal compiler plugin $class_name = 'Smarty_Internal_Compile_' . $tag; if ($this->smarty->loadPlugin($class_name)) { // use plugin if found - self::$_tag_objects[$tag] = new $class_name; + self::$_tag_objects[$tag] = new $class_name; // compile this tag return self::$_tag_objects[$tag]->compile($args, $this, $param1, $param2, $param3); - } + } // no internal compile plugin for this tag return false; - } + } /** * Check for plugins and return function name - * + * * @param $pugin_name string name of plugin or function * @param $type string type of plugin * @return string call name of function @@ -309,21 +313,21 @@ class Smarty_Internal_TemplateCompilerBase { } else if (isset($this->template->required_plugins['compiled'][$plugin_name][$type])) { $this->template->required_plugins['nocache'][$plugin_name][$type] = $this->template->required_plugins['compiled'][$plugin_name][$type]; $function = $this->template->required_plugins['nocache'][$plugin_name][$type]['function']; - } + } } else { if (isset($this->template->required_plugins['compiled'][$plugin_name][$type])) { $function = $this->template->required_plugins['compiled'][$plugin_name][$type]['function']; } else if (isset($this->template->required_plugins['nocache'][$plugin_name][$type])) { $this->template->required_plugins['compiled'][$plugin_name][$type] = $this->template->required_plugins['nocache'][$plugin_name][$type]; $function = $this->template->required_plugins['compiled'][$plugin_name][$type]['function']; - } - } + } + } if (isset($function)) { if ($type == 'modifier') { $this->template->saved_modifier[$plugin_name] = true; - } + } return $function; - } + } // loop through plugin dirs and find the plugin $function = 'smarty_' . $type . '_' . $plugin_name; $found = false; @@ -333,8 +337,8 @@ class Smarty_Internal_TemplateCompilerBase { // require_once($file); $found = true; break; - } - } + } + } if ($found) { if ($this->template->caching && ($this->nocache || $this->tag_nocache)) { $this->template->required_plugins['nocache'][$plugin_name][$type]['file'] = $file; @@ -342,32 +346,32 @@ class Smarty_Internal_TemplateCompilerBase { } else { $this->template->required_plugins['compiled'][$plugin_name][$type]['file'] = $file; $this->template->required_plugins['compiled'][$plugin_name][$type]['function'] = $function; - } + } if ($type == 'modifier') { $this->template->saved_modifier[$plugin_name] = true; - } + } return $function; - } + } if (is_callable($function)) { // plugin function is defined in the script return $function; - } + } return false; - } + } /** * Inject inline code for nocache template sections - * + * * This method gets the content of each template element from the parser. * If the content is compiled code and it should be not cached the code is injected * into the rendered output. - * + * * @param string $content content of template element * @param boolean $tag_nocache true if the parser detected a nocache situation * @param boolean $is_code true if content is compiled code * @return string content */ public function processNocacheCode ($content, $is_code) - { + { // If the template is not evaluated and we have a nocache section and or a nocache tag if ($is_code && !empty($content)) { // generate replacement code @@ -376,42 +380,42 @@ class Smarty_Internal_TemplateCompilerBase { $this->template->has_nocache_code = true; $_output = str_replace("'", "\'", $content); $_output = str_replace("^#^", "'", $_output); - $_output = "nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>"; + $_output = "nocache_hash}%%*/" . $_output . "/*/%%SmartyNocache:{$this->nocache_hash}%%*/';?>"; // make sure we include modifer plugins for nocache code if (isset($this->template->saved_modifier)) { foreach ($this->template->saved_modifier as $plugin_name => $dummy) { if (isset($this->template->required_plugins['compiled'][$plugin_name]['modifier'])) { $this->template->required_plugins['nocache'][$plugin_name]['modifier'] = $this->template->required_plugins['compiled'][$plugin_name]['modifier']; - } - } + } + } $this->template->saved_modifier = null; - } + } } else { $_output = $content; - } + } } else { $_output = $content; - } + } $this->suppressNocacheProcessing = false; $this->tag_nocache = false; return $_output; - } + } /** * display compiler error messages without dying - * + * * If parameter $args is empty it is a parser detected syntax error. * In this case the parser is called to obtain information about expected tokens. - * + * * If parameter $args contains a string this is used as error message - * + * * @param $args string individual error message or null */ public function trigger_template_error($args = null, $line = null) - { + { // get template source line which has error if (!isset($line)) { $line = $this->lex->line; - } + } $match = preg_split("/\n/", $this->lex->data); $error_text = 'Syntax Error in template "' . $this->template->getTemplateFilepath() . '" on line ' . $line . ' "' . htmlspecialchars(trim(preg_replace('![\t\r\n]+!',' ',$match[$line-1]))) . '" '; if (isset($args)) { @@ -429,13 +433,13 @@ class Smarty_Internal_TemplateCompilerBase { } else { // otherwise internal token name $expect[] = $this->parser->yyTokenName[$token]; - } - } + } + } $error_text .= ', expected one of: ' . implode(' , ', $expect); } - } + } throw new SmartyCompilerException($error_text); - } -} + } +} ?> \ No newline at end of file