diff --git a/change_log.txt b/change_log.txt index 3cfd17ce..50572aa9 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,3 +1,8 @@ +10/11/2009 +- allow {block} tags inside included templates +- bugfix for resource plugins in Smarty2 format +- some optimizations of internal.template.php + 10/11/2009 - fixed bug when template with same name is used with different data objects - fixed bug with double quoted name attribute at {insert} tag diff --git a/libs/sysplugins/internal.compile_blockclose.php b/libs/sysplugins/internal.compile_blockclose.php index 7e96123b..a92642ce 100644 --- a/libs/sysplugins/internal.compile_blockclose.php +++ b/libs/sysplugins/internal.compile_blockclose.php @@ -22,6 +22,7 @@ class Smarty_Internal_Compile_BlockClose extends Smarty_Internal_CompileBase { public function compile($args, $compiler) { $this->compiler = $compiler; + $this->smarty = $compiler->smarty; $this->compiler->has_code = true; // turn off block code extraction $compiler->template->extract_code = false; @@ -34,15 +35,15 @@ class Smarty_Internal_Compile_BlockClose extends Smarty_Internal_CompileBase { $this->compiler->trigger_template_error('mismatching name attributes "' . $saved_data[0]['name'] . '" and "' . $_attr['name'] . '"'); } $_name = trim($saved_data[0]['name'], "\"'"); - if (isset($compiler->template->block_data[$_name])) { - if (strpos($compiler->template->block_data[$_name]['compiled'], '%%%%SMARTY_PARENT%%%%') !== false) { - $_output = str_replace('%%%%SMARTY_PARENT%%%%', $_compiled_content, $compiler->template->block_data[$_name]['compiled']); - } elseif ($compiler->template->block_data[$_name]['mode'] == 'prepend') { - $_output = $compiler->template->block_data[$_name]['compiled'] . $compiler->template->extracted_compiled_code; - } elseif ($compiler->template->block_data[$_name]['mode'] == 'append') { - $_output = $compiler->template->extracted_compiled_code . $compiler->template->block_data[$_name]['compiled']; - } elseif (!empty($compiler->template->block_data[$_name])) { - $_output = $compiler->template->block_data[$_name]['compiled']; + if (isset($this->smarty->block_data[$_name])) { + if (strpos($this->smarty->block_data[$_name]['compiled'], '%%%%SMARTY_PARENT%%%%') !== false) { + $_output = str_replace('%%%%SMARTY_PARENT%%%%', $compiler->template->extracted_compiled_code, $this->smarty->block_data[$_name]['compiled']); + } elseif ($this->smarty->block_data[$_name]['mode'] == 'prepend') { + $_output = $this->smarty->block_data[$_name]['compiled'] . $compiler->template->extracted_compiled_code; + } elseif ($this->smarty->block_data[$_name]['mode'] == 'append') { + $_output = $compiler->template->extracted_compiled_code . $this->smarty->block_data[$_name]['compiled']; + } elseif (!empty($this->smarty->block_data[$_name])) { + $_output = $this->smarty->block_data[$_name]['compiled']; } } else { $_output = $compiler->template->extracted_compiled_code; diff --git a/libs/sysplugins/internal.compile_extend.php b/libs/sysplugins/internal.compile_extend.php index cdd572f2..fd6998ec 100644 --- a/libs/sysplugins/internal.compile_extend.php +++ b/libs/sysplugins/internal.compile_extend.php @@ -23,6 +23,7 @@ class Smarty_Internal_Compile_Extend extends Smarty_Internal_CompileBase { public function compile($args, $compiler) { $this->compiler = $compiler; + $this->smarty =$compiler->smarty; $this->required_attributes = array('file'); // check and get attributes $_attr = $this->_get_attributes($args); @@ -30,17 +31,17 @@ class Smarty_Internal_Compile_Extend extends Smarty_Internal_CompileBase { // $include_file = ''; eval('$include_file = ' . $_attr['file'] . ';'); // create template object - $_template = new Smarty_Template ($include_file, $this->compiler->smarty, $compiler->template); + $_template = new Smarty_Template ($include_file, $this->smarty, $compiler->template); // save file dependency $compiler->template->properties['file_dependency']['F'.abs(crc32($_template->getTemplateFilepath()))] = array($_template->getTemplateFilepath(), $_template->getTemplateTimestamp()); $_old_source = $compiler->template->template_source; - if (preg_match_all('/(' . $this->compiler->smarty->left_delimiter . 'block(.+?)' . $this->compiler->smarty->right_delimiter . ')/', $_old_source, $s, PREG_OFFSET_CAPTURE) != - preg_match_all('/(' . $this->compiler->smarty->left_delimiter . '\/block(.*?)' . $this->compiler->smarty->right_delimiter . ')/', $_old_source, $c, PREG_OFFSET_CAPTURE)) { + if (preg_match_all('/(' . $this->smarty->left_delimiter . 'block(.+?)' . $this->smarty->right_delimiter . ')/', $_old_source, $s, PREG_OFFSET_CAPTURE) != + preg_match_all('/(' . $this->smarty->left_delimiter . '\/block(.*?)' . $this->smarty->right_delimiter . ')/', $_old_source, $c, PREG_OFFSET_CAPTURE)) { $this->compiler->trigger_template_error(" unmatched {block} {/block} pairs"); } $block_count = count($s[0]); for ($i = 0; $i < $block_count; $i++) { - $block_content = str_replace($this->compiler->smarty->left_delimiter . '$smarty.parent' . $this->compiler->smarty->right_delimiter, '%%%%SMARTY_PARENT%%%%', + $block_content = str_replace($this->smarty->left_delimiter . '$smarty.parent' . $this->smarty->right_delimiter, '%%%%SMARTY_PARENT%%%%', substr($_old_source, $s[0][$i][1] + strlen($s[0][$i][0]), $c[0][$i][1] - $s[0][$i][1] - strlen($s[0][$i][0]))); $this->saveBlockData($block_content, $s[0][$i][0]); } @@ -55,31 +56,31 @@ class Smarty_Internal_Compile_Extend extends Smarty_Internal_CompileBase { $this->compiler->trigger_template_error("\"" . $block_tag . "\" missing name attribute"); } else { // compile block content - $_tpl = $this->compiler->smarty->createTemplate('string:' . $block_content); + $_tpl = $this->smarty->createTemplate('string:' . $block_content); $_tpl->template_filepath = $this->compiler->template->getTemplateFilepath(); $_tpl->suppressHeader = true; $_compiled_content = $_tpl->getCompiledTemplate(); unset($_tpl); $_name = trim($_match[3], "\"'}"); - if (isset($this->compiler->template->block_data[$_name])) { - if (strpos($this->compiler->template->block_data[$_name]['compiled'], '%%%%SMARTY_PARENT%%%%') !== false) { - $this->compiler->template->block_data[$_name]['compiled'] = - str_replace('%%%%SMARTY_PARENT%%%%', $_compiled_content, $this->compiler->template->block_data[$_name]['compiled']); - } elseif ($this->compiler->template->block_data[$_name]['mode'] == 'prepend') { - $this->compiler->template->block_data[$_name]['compiled'] .= $_compiled_content; - } elseif ($this->compiler->template->block_data[$_name]['mode'] == 'append') { - $this->compiler->template->block_data[$_name]['compiled'] = $_compiled_content . $this->compiler->template->block_data[$_name]['compiled']; + if (isset($this->smarty->block_data[$_name])) { + if (strpos($this->smarty->block_data[$_name]['compiled'], '%%%%SMARTY_PARENT%%%%') !== false) { + $this->smarty->block_data[$_name]['compiled'] = + str_replace('%%%%SMARTY_PARENT%%%%', $_compiled_content, $this->smarty->block_data[$_name]['compiled']); + } elseif ($this->smarty->block_data[$_name]['mode'] == 'prepend') { + $this->smarty->block_data[$_name]['compiled'] .= $_compiled_content; + } elseif ($this->smarty->block_data[$_name]['mode'] == 'append') { + $this->smarty->block_data[$_name]['compiled'] = $_compiled_content . $this->smarty->block_data[$_name]['compiled']; } } else { - $this->compiler->template->block_data[$_name]['compiled'] = $_compiled_content; + $this->smarty->block_data[$_name]['compiled'] = $_compiled_content; } if (preg_match('/(.?)(append=true)(.*)/', $block_tag, $_match) != 0) { - $this->compiler->template->block_data[$_name]['mode'] = 'append'; + $this->smarty->block_data[$_name]['mode'] = 'append'; } elseif (preg_match('/(.?)(prepend=true)(.*)/', $block_tag, $_match) != 0) { - $this->compiler->template->block_data[$_name]['mode'] = 'prepend'; + $this->smarty->block_data[$_name]['mode'] = 'prepend'; } else { - $this->compiler->template->block_data[$_name]['mode'] = 'replace'; + $this->smarty->block_data[$_name]['mode'] = 'replace'; } } } diff --git a/libs/sysplugins/internal.resource_extend.php b/libs/sysplugins/internal.resource_extend.php index 6e6b2639..ab318377 100644 --- a/libs/sysplugins/internal.resource_extend.php +++ b/libs/sysplugins/internal.resource_extend.php @@ -116,24 +116,24 @@ class Smarty_Internal_Resource_Extend { unset($_tpl); $_name = trim($_match[3], "\"'}"); - if (isset($this->template->block_data[$_name])) { - if (strpos($this->template->block_data[$_name]['compiled'], '%%%%SMARTY_PARENT%%%%') !== false) { - $this->template->block_data[$_name]['compiled'] = - str_replace('%%%%SMARTY_PARENT%%%%', $_compiled_content, $this->template->block_data[$_name]['compiled']); - } elseif ($this->template->block_data[$_name]['mode'] == 'prepend') { - $this->template->block_data[$_name]['compiled'] .= $_compiled_content; - } elseif ($this->template->block_data[$_name]['mode'] == 'append') { - $this->template->block_data[$_name]['compiled'] = $_compiled_content . $this->template->block_data[$_name]['compiled']; + if (isset($this->smarty->block_data[$_name])) { + if (strpos($this->smarty->block_data[$_name]['compiled'], '%%%%SMARTY_PARENT%%%%') !== false) { + $this->smarty->block_data[$_name]['compiled'] = + str_replace('%%%%SMARTY_PARENT%%%%', $_compiled_content, $this->smarty->block_data[$_name]['compiled']); + } elseif ($this->smarty->block_data[$_name]['mode'] == 'prepend') { + $this->smarty->block_data[$_name]['compiled'] .= $_compiled_content; + } elseif ($this->smarty->block_data[$_name]['mode'] == 'append') { + $this->smarty->block_data[$_name]['compiled'] = $_compiled_content . $this->smarty->block_data[$_name]['compiled']; } } else { - $this->template->block_data[$_name]['compiled'] = $_compiled_content; + $this->smarty->block_data[$_name]['compiled'] = $_compiled_content; } if (preg_match('/(.?)(append=true)(.*)/', $block_tag, $_match) != 0) { - $this->template->block_data[$_name]['mode'] = 'append'; + $this->smarty->block_data[$_name]['mode'] = 'append'; } elseif (preg_match('/(.?)(prepend=true)(.*)/', $block_tag, $_match) != 0) { - $this->template->block_data[$_name]['mode'] = 'prepend'; + $this->smarty->block_data[$_name]['mode'] = 'prepend'; } else { - $this->template->block_data[$_name]['mode'] = 'replace'; + $this->smarty->block_data[$_name]['mode'] = 'replace'; } } } diff --git a/libs/sysplugins/internal.template.php b/libs/sysplugins/internal.template.php index bbde7f80..17606c40 100644 --- a/libs/sysplugins/internal.template.php +++ b/libs/sysplugins/internal.template.php @@ -159,10 +159,10 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { * * @return boolean true if the template exists */ - public function isExisting ($error= false) + public function isExisting ($error = false) { if ($this->isExisting === null) { - $this->isExisting = $this->smarty->resource_objects[$this->resource_type]->isExisting($this); + $this->isExisting = $this->smarty->resource_objects[$this->resource_type]->isExisting($this); } if (!$this->isExisting && $error) { throw new Exception("Unable to load template \"{$this->resource_type} : {$this->resource_name}\""); @@ -207,7 +207,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { public function mustCompile () { $this->isExisting(true); - + if ($this->mustCompile === null) { $this->mustCompile = ($this->usesCompiler() && ($this->force_compile || $this->isEvaluated() || ($this->smarty->compile_check && $this->getCompiledTimestamp () !== $this->getTemplateTimestamp ()))); } @@ -383,10 +383,11 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { } if (!empty($this->properties['file_dependency']) && $this->smarty->compile_check) { foreach ($this->properties['file_dependency'] as $_file_to_check) { - If (is_file($_file_to_check[0])) { + $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name); + If ($resource_type == 'file') { $mtime = filemtime($_file_to_check[0]); } else { - $this->parseResourceName($_file_to_check[0], $resource_type, $resource_name, $resource_handler); + $resource_handler = $this->loadTemplateResourceHandler($resource_type); $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name); } // If ($mtime > $this->getCachedTimestamp()) { @@ -429,15 +430,17 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { if (!empty($this->properties['file_dependency'])) { $this->mustCompile = false; foreach ($this->properties['file_dependency'] as $_file_to_check) { - If (is_file($_file_to_check[0])) { + $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name); + If ($resource_type == 'file') { $mtime = filemtime($_file_to_check[0]); } else { - $this->parseResourceName($_file_to_check[0], $resource_type, $resource_name, $resource_handler); + $resource_handler = $this->loadTemplateResourceHandler($resource_type); $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name); } If ($mtime != $_file_to_check[1]) { $this->properties['file_dependency'] = array(); $this->mustCompile = true; + break; } } if ($this->mustCompile) { @@ -504,71 +507,25 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { } /** - * parse a template resource in its name and type + * Parse a template resource in its name and type + * Load required resource handler * * @param string $template_resource template resource specification + * @param string $resource_type return resource type + * @param string $resource_name return resource name + * @param object $resource_handler return resource handler object */ public function parseResourceName($template_resource, &$resource_type, &$resource_name, &$resource_handler) { if (empty($template_resource)) return false; - if (strpos($template_resource, ':') === false) { - // no resource given, use default - $resource_type = $this->smarty->default_resource_type; - $resource_name = $template_resource; - } else { - // get type and name from path - list($resource_type, $resource_name) = explode(':', $template_resource, 2); - if (strlen($resource_type) == 1) { - // 1 char is not resource type, but part of filepath - $resource_type = 'file'; - $resource_name = $template_resource; - } else { - $resource_type = strtolower($resource_type); - } - } - // load resource handler if required - if (!isset($this->smarty->resource_objects[$resource_type])) { - // try registered resource - if (isset($this->smarty->_plugins['resource'][$resource_type])) { - require_once(SMARTY_SYSPLUGINS_DIR . 'internal.resource_registered.php'); - // $this->smarty->loadPlugin('Smarty_Internal_Resource_Registered'); - $resource_handler = $this->smarty->resource_objects[$resource_type] = new Smarty_Internal_Resource_Registered($this->smarty); - } else { - // try sysplugins dir - $_resource_class = "Smarty_Internal_Resource_{$resource_type}"; - if ($this->smarty->loadPlugin($_resource_class)) { - $resource_handler = $this->smarty->resource_objects[$resource_type] = new $_resource_class($this->smarty); - } else { - // try plugins dir - $_resource_class = "Smarty_Resource_{$resource_type}"; - if ($this->smarty->loadPlugin($_resource_class)) { - $resource_handler = $this->smarty->resource_objects[$resource_type] = new $_resource_class($this->smarty); - } else { - // try streams - $_known_stream = stream_get_wrappers(); - if (in_array($resource_type, $_known_stream)) { - // is known stream - if ($this->smarty->security) { - $this->smarty->security_handler->isTrustedStream($resource_type); - } - require_once(SMARTY_SYSPLUGINS_DIR . 'internal.resource_stream.php'); - // $this->smarty->loadPlugin('Smarty_Internal_Resource_Stream'); - $resource_handler = $this->smarty->resource_objects[$resource_type] = new Smarty_Internal_Resource_Stream($this->smarty); -// $resource_name = str_replace(':', '://', $template_resource); - } else { - throw new Exception('Unkown resource type \'' . $resource_type . '\''); - } - } - } - } - } else { - $resource_handler = $this->smarty->resource_objects[$resource_type]; - } + $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') { - $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; } @@ -673,6 +630,91 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { } } + /** + * Split a template resource in its name and type + * + * @param string $template_resource template resource specification + * @param string $resource_type return resource type + * @param string $resource_name return resource name + */ + private function getResourceTypeName ($template_resource, &$resource_type, &$resource_name) + { + if (strpos($template_resource, ':') === false) { + // no resource given, use default + $resource_type = $this->smarty->default_resource_type; + $resource_name = $template_resource; + } else { + // get type and name from path + list($resource_type, $resource_name) = explode(':', $template_resource, 2); + if (strlen($resource_type) == 1) { + // 1 char is not resource type, but part of filepath + $resource_type = 'file'; + $resource_name = $template_resource; + } else { + $resource_type = strtolower($resource_type); + } + } + } + + /** + * Load template resource handler by type + * + * @param string $resource_type template resource type + * @return object resource handler object + */ + private function loadTemplateResourceHandler ($resource_type) + { + // load resource handler if required + if (!isset($this->smarty->resource_objects[$resource_type])) { + // try registered resource + if (isset($this->smarty->_plugins['resource'][$resource_type])) { + require_once(SMARTY_SYSPLUGINS_DIR . 'internal.resource_registered.php'); + // $this->smarty->loadPlugin('Smarty_Internal_Resource_Registered'); + return $this->smarty->resource_objects[$resource_type] = new Smarty_Internal_Resource_Registered($this->smarty); + } else { + // try sysplugins dir + $_resource_class = "Smarty_Internal_Resource_{$resource_type}"; + if ($this->smarty->loadPlugin($_resource_class)) { + return $this->smarty->resource_objects[$resource_type] = new $_resource_class($this->smarty); + } else { + // try plugins dir + $_resource_class = "Smarty_Resource_{$resource_type}"; + if ($this->smarty->loadPlugin($_resource_class)) { + if (class_exists($_resource_class, false)) { + return $this->smarty->resource_objects[$resource_type] = new $_resource_class($this->smarty); + } else { + $this->smarty->register_resource($resource_type, + array("smarty_resource_{$resource_type}_source", + "smarty_resource_{$resource_type}_timestamp", + "smarty_resource_{$resource_type}_secure", + "smarty_resource_{$resource_type}_trusted")); + require_once(SMARTY_SYSPLUGINS_DIR . 'internal.resource_registered.php'); + // $this->smarty->loadPlugin('Smarty_Internal_Resource_Registered'); + return $this->smarty->resource_objects[$resource_type] = new Smarty_Internal_Resource_Registered($this->smarty); + } + } else { + // try streams + $_known_stream = stream_get_wrappers(); + if (in_array($resource_type, $_known_stream)) { + // is known stream + if ($this->smarty->security) { + $this->smarty->security_handler->isTrustedStream($resource_type); + } + require_once(SMARTY_SYSPLUGINS_DIR . 'internal.resource_stream.php'); + // $this->smarty->loadPlugin('Smarty_Internal_Resource_Stream'); + return $this->smarty->resource_objects[$resource_type] = new Smarty_Internal_Resource_Stream($this->smarty); + // $resource_name = str_replace(':', '://', $template_resource); + } else { + throw new Exception('Unkown resource type \'' . $resource_type . '\''); + } + } + } + } + } else { + return $this->smarty->resource_objects[$resource_type]; + } + } + /** * Create property header */ @@ -703,7 +745,7 @@ class Smarty_Internal_Template extends Smarty_Internal_TemplateBase { */ public function is_cached () { - return $this->iscached(); + return $this->iscached($this); } } diff --git a/libs/sysplugins/internal.templatecompilerbase.php b/libs/sysplugins/internal.templatecompilerbase.php index 5f4fa4f9..402e2045 100644 --- a/libs/sysplugins/internal.templatecompilerbase.php +++ b/libs/sysplugins/internal.templatecompilerbase.php @@ -66,7 +66,11 @@ class Smarty_Internal_TemplateCompilerBase { } // on empty template just return header if ($_content == '') { - $template->compiled_template = $template->createPropertyHeader() . $template_header; + if ($template->suppressHeader) { + $template->compiled_template = ''; + } else { + $template->compiled_template = $template->createPropertyHeader() . $template_header; + } return true; } // init cacher plugin @@ -77,7 +81,11 @@ class Smarty_Internal_TemplateCompilerBase { if (!$this->compile_error) { // close cacher and return compiled template - $template->compiled_template = $template->createPropertyHeader() . $template_header . $template->cacher_object->closeCacher($this, $_compiled_code); + if ($template->suppressHeader) { + $template->compiled_template = $template->cacher_object->closeCacher($this, $_compiled_code); + } else { + $template->compiled_template = $template->createPropertyHeader() . $template_header . $template->cacher_object->closeCacher($this, $_compiled_code); + } // run postfilter if required if (isset($this->smarty->autoload_filters['post']) || isset($this->smarty->registered_filters['post'])) { $template->compiled_template = $this->smarty->filter_handler->execute('post', $template->compiled_template); @@ -92,8 +100,8 @@ class Smarty_Internal_TemplateCompilerBase { /** * Compile Tag * - * This is a call back from the lexer/parser - * It executes the required compile plugin for the Smarty 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