X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/timetracker.git/blobdiff_plain/098a79f0819ebb89b7d48df4a6b154af4560f68e..9a23a8c0a51b7ec38a96f525484134f3cb85dc7e:/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php diff --git a/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php b/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php new file mode 100644 index 00000000..070fb840 --- /dev/null +++ b/WEB-INF/lib/smarty/sysplugins/smarty_internal_template.php @@ -0,0 +1,998 @@ + array(), + 'nocache_hash' => '', + 'function' => array()); + // required plugins + public $required_plugins = array('compiled' => array(), 'nocache' => array()); + public $saved_modifier = null; + public $smarty = null; + // blocks for template inheritance + public $block_data = array(); + public $wrapper = null; + /** + * Create template data object + * + * Some of the global Smarty settings copied to template scope + * It load the required template resources and cacher plugins + * + * @param string $template_resource template resource string + * @param object $_parent back pointer to parent object with variables or null + * @param mixed $_cache_id cache id or null + * @param mixed $_compile_id compile id or null + */ + public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null) + { + $this->smarty = &$smarty; + // Smarty parameter + $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id; + $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id; + $this->caching = $_caching === null ? $this->smarty->caching : $_caching; + if ($this->caching === true) $this->caching = Smarty::CACHING_LIFETIME_CURRENT; + $this->cache_lifetime = $_cache_lifetime === null ?$this->smarty->cache_lifetime : $_cache_lifetime; + $this->parent = $_parent; + // dummy local smarty variable + $this->tpl_vars['smarty'] = new Smarty_Variable; + // Template resource + $this->template_resource = $template_resource; + // copy block data of template inheritance + if ($this->parent instanceof Smarty_Internal_Template) { + $this->block_data = $this->parent->block_data; + } + + } + + /** + * Returns the template filepath + * + * The template filepath is determined by the actual resource handler + * + * @return string the template filepath + */ + public function getTemplateFilepath () + { + return $this->template_filepath === null ? + $this->template_filepath = $this->resource_object->getTemplateFilepath($this) : + $this->template_filepath; + } + + /** + * Returns the timpestamp of the template source + * + * The template timestamp is determined by the actual resource handler + * + * @return integer the template timestamp + */ + public function getTemplateTimestamp () + { + return $this->template_timestamp === null ? + $this->template_timestamp = $this->resource_object->getTemplateTimestamp($this) : + $this->template_timestamp; + } + + /** + * Returns the template source code + * + * The template source is being read by the actual resource handler + * + * @return string the template source + */ + public function getTemplateSource () + { + if ($this->template_source === null) { + if (!$this->resource_object->getTemplateSource($this)) { + throw new SmartyException("Unable to read template {$this->resource_type} '{$this->resource_name}'"); + } + } + return $this->template_source; + } + + /** + * Returns if the template is existing + * + * The status is determined by the actual resource handler + * + * @return boolean true if the template exists + */ + public function isExisting ($error = false) + { + if ($this->isExisting === null) { + $this->isExisting = $this->resource_object->isExisting($this); + } + if (!$this->isExisting && $error) { + throw new SmartyException("Unable to load template {$this->resource_type} '{$this->resource_name}'"); + } + return $this->isExisting; + } + + /** + * Returns if the current template must be compiled by the Smarty compiler + * + * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration + * + * @return boolean true if the template must be compiled + */ + public function mustCompile () + { + $this->isExisting(true); + if ($this->mustCompile === null) { + $this->mustCompile = ($this->resource_object->usesCompiler && ($this->smarty->force_compile || $this->resource_object->isEvaluated || $this->getCompiledTimestamp () === false || + // ($this->smarty->compile_check && $this->getCompiledTimestamp () !== $this->getTemplateTimestamp ()))); + ($this->smarty->compile_check && $this->getCompiledTimestamp () < $this->getTemplateTimestamp ()))); + } + return $this->mustCompile; + } + + /** + * Returns the compiled template filepath + * + * @return string the template filepath + */ + public function getCompiledFilepath () + { + return $this->compiled_filepath === null ? + ($this->compiled_filepath = !$this->resource_object->isEvaluated ? $this->resource_object->getCompiledFilepath($this) : false) : + $this->compiled_filepath; + } + + /** + * Returns the timpestamp of the compiled template + * + * @return integer the template timestamp + */ + public function getCompiledTimestamp () + { + return $this->compiled_timestamp === null ? + ($this->compiled_timestamp = (!$this->resource_object->isEvaluated && file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false) : + $this->compiled_timestamp; + } + + /** + * Returns the compiled template + * + * It checks if the template must be compiled or just read from the template resource + * + * @return string the compiled template + */ + public function getCompiledTemplate () + { + if ($this->compiled_template === null) { + // see if template needs compiling. + if ($this->mustCompile()) { + $this->compileTemplateSource(); + } else { + if ($this->compiled_template === null) { + $this->compiled_template = !$this->resource_object->isEvaluated && $this->resource_object->usesCompiler ? file_get_contents($this->getCompiledFilepath()) : false; + } + } + } + return $this->compiled_template; + } + + /** + * Compiles the template + * + * If the template is not evaluated the compiled template is saved on disk + */ + public function compileTemplateSource () + { + if (!$this->resource_object->isEvaluated) { + $this->properties['file_dependency'] = array(); + $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type); + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_compile($this); + } + // compile template + if (!is_object($this->compiler_object)) { + // load compiler + $this->smarty->loadPlugin($this->resource_object->compiler_class); + $this->compiler_object = new $this->resource_object->compiler_class($this->resource_object->template_lexer_class, $this->resource_object->template_parser_class, $this->smarty); + } + // compile locking + if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated) { + if ($saved_timestamp = $this->getCompiledTimestamp()) { + touch($this->getCompiledFilepath()); + } + } + // call compiler + try { + $this->compiler_object->compileTemplate($this); + } + catch (Exception $e) { + // restore old timestamp in case of error + if ($this->smarty->compile_locking && !$this->resource_object->isEvaluated && $saved_timestamp) { + touch($this->getCompiledFilepath(), $saved_timestamp); + } + throw $e; + } + // compiling succeded + if (!$this->resource_object->isEvaluated && $this->write_compiled_code) { + // write compiled template + Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->compiled_template, $this->smarty); + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_compile($this); + } + // release objects to free memory + Smarty_Internal_TemplateCompilerBase::$_tag_objects = array(); + unset($this->compiler_object->parser->root_buffer, + $this->compiler_object->parser->current_buffer, + $this->compiler_object->parser, + $this->compiler_object->lex, + $this->compiler_object->template, + $this->compiler_object + ); + } + + /** + * Returns the filepath of the cached template output + * + * The filepath is determined by the actual cache resource + * + * @return string the cache filepath + */ + public function getCachedFilepath () + { + return $this->cached_filepath === null ? + $this->cached_filepath = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedFilepath($this) : + $this->cached_filepath; + } + + /** + * Returns the timpestamp of the cached template output + * + * The timestamp is determined by the actual cache resource + * + * @return integer the template timestamp + */ + public function getCachedTimestamp () + { + return $this->cached_timestamp === null ? + $this->cached_timestamp = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedTimestamp($this) : + $this->cached_timestamp; + } + + /** + * Returns the cached template output + * + * @return string |booelan the template content or false if the file does not exist + */ + public function getCachedContent () + { + return $this->rendered_content === null ? + $this->rendered_content = ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) ? false : $this->cache_resource_object->getCachedContents($this) : + $this->rendered_content; + } + + /** + * Writes the cached template output + */ + public function writeCachedContent ($content) + { + if ($this->resource_object->isEvaluated || !($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED)) { + // don't write cache file + return false; + } + $this->properties['cache_lifetime'] = $this->cache_lifetime; + return $this->cache_resource_object->writeCachedContent($this, $this->createPropertyHeader(true) .$content); + } + + /** + * Checks of a valid version redered HTML output is in the cache + * + * If the cache is valid the contents is stored in the template object + * + * @return boolean true if cache is valid + */ + public function isCached ($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + if ($template === null) { + $no_render = true; + } elseif ($template === false) { + $no_render = false; + } else { + if ($parent === null) { + $parent = $this; + } + $this->smarty->isCached ($template, $cache_id, $compile_id, $parent); + } + if ($this->isCached === null) { + $this->isCached = false; + if (($this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED) && !$this->resource_object->isEvaluated) { + $cachedTimestamp = $this->getCachedTimestamp(); + if ($cachedTimestamp === false || $this->smarty->force_compile || $this->smarty->force_cache) { + return $this->isCached; + } + if ($this->caching === Smarty::CACHING_LIFETIME_SAVED || ($this->caching == Smarty::CACHING_LIFETIME_CURRENT && (time() <= ($cachedTimestamp + $this->cache_lifetime) || $this->cache_lifetime < 0))) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_cache($this); + } + $this->rendered_content = $this->cache_resource_object->getCachedContents($this, $no_render); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_cache($this); + } + if ($this->cacheFileChecked) { + $this->isCached = true; + return $this->isCached; + } + $this->cacheFileChecked = true; + if ($this->caching === Smarty::CACHING_LIFETIME_SAVED && $this->properties['cache_lifetime'] >= 0 && (time() > ($this->getCachedTimestamp() + $this->properties['cache_lifetime']))) { + $this->tpl_vars = array(); + $this->rendered_content = null; + return $this->isCached; + } + if (!empty($this->properties['file_dependency']) && $this->smarty->compile_check) { + $resource_type = null; + $resource_name = null; + foreach ($this->properties['file_dependency'] as $_file_to_check) { + If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') { + $mtime = filemtime($_file_to_check[0]); + } else { + $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name); + $resource_handler = $this->loadTemplateResourceHandler($resource_type); + $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name); + } + // If ($mtime > $this->getCachedTimestamp()) { + If ($mtime > $_file_to_check[1]) { + $this->tpl_vars = array(); + $this->rendered_content = null; + return $this->isCached; + } + } + } + $this->isCached = true; + } + } + } + return $this->isCached; + } + + /** + * Render the output using the compiled template or the PHP template source + * + * The rendering process is accomplished by just including the PHP files. + * The only exceptions are evaluated templates (string template). Their code has + * to be evaluated + */ + public function renderTemplate () + { + if ($this->resource_object->usesCompiler) { + if ($this->mustCompile() && $this->compiled_template === null) { + $this->compileTemplateSource(); + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_render($this); + } + $_smarty_tpl = $this; + ob_start(); + if ($this->resource_object->isEvaluated) { + eval("?>" . $this->compiled_template); + } else { + include($this->getCompiledFilepath ()); + // check file dependencies at compiled code + if ($this->smarty->compile_check) { + if (!empty($this->properties['file_dependency'])) { + $this->mustCompile = false; + $resource_type = null; + $resource_name = null; + foreach ($this->properties['file_dependency'] as $_file_to_check) { + If ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') { + $mtime = filemtime($_file_to_check[0]); + } else { + $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name); + $resource_handler = $this->loadTemplateResourceHandler($resource_type); + $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name); + } + // If ($mtime != $_file_to_check[1]) { + If ($mtime > $_file_to_check[1]) { + $this->mustCompile = true; + break; + } + } + if ($this->mustCompile) { + // recompile and render again + ob_get_clean(); + $this->compileTemplateSource(); + ob_start(); + include($this->getCompiledFilepath ()); + } + } + } + } + } else { + if (is_callable(array($this->resource_object, 'renderUncompiled'))) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_render($this); + } + ob_start(); + $this->resource_object->renderUncompiled($this); + } else { + throw new SmartyException("Resource '$this->resource_type' must have 'renderUncompiled' methode"); + } + } + $this->rendered_content = ob_get_clean(); + if (!$this->resource_object->isEvaluated && empty($this->properties['file_dependency'][$this->templateUid])) { + $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp(),$this->resource_type); + } + if ($this->parent instanceof Smarty_Internal_Template) { + $this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']); + foreach($this->required_plugins as $code => $tmp1) { + foreach($tmp1 as $name => $tmp) { + foreach($tmp as $type => $data) { + $this->parent->required_plugins[$code][$name][$type] = $data; + } + } + } + } + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_render($this); + } + // write to cache when nessecary + if (!$this->resource_object->isEvaluated && ($this->caching == Smarty::CACHING_LIFETIME_SAVED || $this->caching == Smarty::CACHING_LIFETIME_CURRENT)) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_cache($this); + } + $this->properties['has_nocache_code'] = false; + // get text between non-cached items + $cache_split = preg_split("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content); + // get non-cached items + preg_match_all("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content, $cache_parts); + $output = ''; + // loop over items, stitch back together + foreach($cache_split as $curr_idx => $curr_split) { + // escape PHP tags in template content + $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '', $curr_split); + if (isset($cache_parts[0][$curr_idx])) { + $this->properties['has_nocache_code'] = true; + // remove nocache tags from cache output + $output .= preg_replace("!/\*/?%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]); + } + } + if (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output'])) { + $output = Smarty_Internal_Filter_Handler::runFilter('output', $output, $this); + } + // rendering (must be done before writing cache file because of {function} nocache handling) + $_smarty_tpl = $this; + ob_start(); + eval("?>" . $output); + $this->rendered_content = ob_get_clean(); + // write cache file content + $this->writeCachedContent(''. $output. ''); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_cache($this); + } + } else { + // var_dump('renderTemplate', $this->has_nocache_code, $this->template_resource, $this->properties['nocache_hash'], $this->parent->properties['nocache_hash'], $this->rendered_content); + if ($this->has_nocache_code && !empty($this->properties['nocache_hash']) && !empty($this->parent->properties['nocache_hash'])) { + // replace nocache_hash + $this->rendered_content = preg_replace("/{$this->properties['nocache_hash']}/", $this->parent->properties['nocache_hash'], $this->rendered_content); + $this->parent->has_nocache_code = $this->has_nocache_code; + } + } + } + + /** + * Returns the rendered HTML output + * + * If the cache is valid the cached content is used, otherwise + * the output is rendered from the compiled template or PHP template source + * + * @return string rendered HTML output + */ + public function getRenderedTemplate () + { + // disable caching for evaluated code + if ($this->resource_object->isEvaluated) { + $this->caching = false; + } + // checks if template exists + $this->isExisting(true); + // read from cache or render + if ($this->rendered_content === null) { + if ($this->isCached) { + if ($this->smarty->debugging) { + Smarty_Internal_Debug::start_cache($this); + } + $this->rendered_content = $this->cache_resource_object->getCachedContents($this, false); + if ($this->smarty->debugging) { + Smarty_Internal_Debug::end_cache($this); + } + } + if ($this->isCached === null) { + $this->isCached(false); + } + if (!$this->isCached) { + // render template (not loaded and not in cache) + $this->renderTemplate(); + } + } + $this->updateParentVariables(); + $this->isCached = null; + return $this->rendered_content; + } + + /** + * 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; + $this->getResourceTypeName($template_resource, $resource_type, $resource_name); + $resource_handler = $this->loadTemplateResourceHandler($resource_type); + // cache template object under a unique ID + // do not cache eval resources + if ($resource_type != 'eval') { + $this->smarty->template_objects[sha1($this->template_resource . $this->cache_id . $this->compile_id)] = $this; + } + return true; + } + + /** + * get system filepath to template + */ + public function buildTemplateFilepath ($file = null) + { + if ($file == null) { + $file = $this->resource_name; + } + // relative file name? + if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $file)) { + foreach((array)$this->smarty->template_dir as $_template_dir) { + if (strpos('/\\', substr($_template_dir, -1)) === false) { + $_template_dir .= DS; + } + $_filepath = $_template_dir . $file; + if (file_exists($_filepath)) { + return $_filepath; + } + if (!preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_template_dir)) { + // try PHP include_path + if (($_filepath = Smarty_Internal_Get_Include_Path::getIncludePath($_filepath)) !== false) { + return $_filepath; + } + } + } + } + // try absolute filepath + if (file_exists($file)) return $file; + // no tpl file found + if (!empty($this->smarty->default_template_handler_func)) { + if (!is_callable($this->smarty->default_template_handler_func)) { + throw new SmartyException("Default template handler not callable"); + } else { + $_return = call_user_func_array($this->smarty->default_template_handler_func, + array($this->resource_type, $this->resource_name, &$this->template_source, &$this->template_timestamp, $this)); + if (is_string($_return)) { + return $_return; + } elseif ($_return === true) { + return $file; + } + } + } + return false; + } + + /** + * Update Smarty variables in other scopes + */ + public function updateParentVariables ($scope = Smarty::SCOPE_LOCAL) + { + $has_root = false; + foreach ($this->tpl_vars as $_key => $_variable) { + $_variable_scope = $this->tpl_vars[$_key]->scope; + if ($scope == Smarty::SCOPE_LOCAL && $_variable_scope == Smarty::SCOPE_LOCAL) { + continue; + } + if (isset($this->parent) && ($scope == Smarty::SCOPE_PARENT || $_variable_scope == Smarty::SCOPE_PARENT)) { + if (isset($this->parent->tpl_vars[$_key])) { + // variable is already defined in parent, copy value + $this->parent->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value; + } else { + // create variable in parent + $this->parent->tpl_vars[$_key] = clone $_variable; + $this->parent->tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL; + } + } + if ($scope == Smarty::SCOPE_ROOT || $_variable_scope == Smarty::SCOPE_ROOT) { + if ($this->parent == null) { + continue; + } + if (!$has_root) { + // find root + $root_ptr = $this; + while ($root_ptr->parent != null) { + $root_ptr = $root_ptr->parent; + $has_root = true; + } + } + if (isset($root_ptr->tpl_vars[$_key])) { + // variable is already defined in root, copy value + $root_ptr->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value; + } else { + // create variable in root + $root_ptr->tpl_vars[$_key] = clone $_variable; + $root_ptr->tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL; + } + } + if ($scope == Smarty::SCOPE_GLOBAL || $_variable_scope == Smarty::SCOPE_GLOBAL) { + if (isset(Smarty::$global_tpl_vars[$_key])) { + // variable is already defined in root, copy value + Smarty::$global_tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value; + } else { + // create global variable + Smarty::$global_tpl_vars[$_key] = clone $_variable; + } + Smarty::$global_tpl_vars[$_key]->scope = Smarty::SCOPE_LOCAL; + } + } + } + + /** + * 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 + */ + protected 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; + } + } + } + + /** + * Load template resource handler by type + * + * @param string $resource_type template resource type + * @return object resource handler object + */ + protected function loadTemplateResourceHandler ($resource_type) + { + // try registered resource + if (isset($this->smarty->registered_resources[$resource_type])) { + return new Smarty_Internal_Resource_Registered($this); + } else { + // try sysplugins dir + if (in_array($resource_type, array('file', 'string', 'extends', 'php', 'stream', 'eval'))) { + $_resource_class = 'Smarty_Internal_Resource_' . ucfirst($resource_type); + return new $_resource_class($this->smarty); + } else { + // try plugins dir + $_resource_class = 'Smarty_Resource_' . ucfirst($resource_type); + if ($this->smarty->loadPlugin($_resource_class)) { + if (class_exists($_resource_class, false)) { + return new $_resource_class($this->smarty); + } else { + return new Smarty_Internal_Resource_Registered($this, $resource_type); + } + } else { + // try streams + $_known_stream = stream_get_wrappers(); + if (in_array($resource_type, $_known_stream)) { + // is known stream + if (is_object($this->smarty->security_policy)) { + $this->smarty->security_policy->isTrustedStream($resource_type); + } + return new Smarty_Internal_Resource_Stream($this->smarty); + } else { + throw new SmartyException('Unkown resource type \'' . $resource_type . '\''); + } + } + } + } + } + + /** + * Create property header + */ + public function createPropertyHeader ($cache = false) + { + $plugins_string = ''; + // include code for plugins + if (!$cache) { + if (!empty($this->required_plugins['compiled'])) { + $plugins_string = 'required_plugins['compiled'] as $tmp) { + foreach($tmp as $data) { + $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$data['file']}';\n"; + } + } + $plugins_string .= '?>'; + } + if (!empty($this->required_plugins['nocache'])) { + $this->has_nocache_code = true; + $plugins_string .= "properties['nocache_hash']}%%*/required_plugins['nocache'] as $tmp) { + foreach($tmp as $data) { + $plugins_string .= "if (!is_callable(\'{$data['function']}\')) include \'{$data['file']}\';\n"; + } + } + $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n"; + } + } + // build property code + $this->properties['has_nocache_code'] = $this->has_nocache_code; + $properties_string = "properties['nocache_hash']}%%*/" ; + if ($this->smarty->direct_access_security) { + $properties_string .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n"; + } + if ($cache) { + // remove compiled code of{function} definition + unset($this->properties['function']); + if (!empty($this->smarty->template_functions)) { + // copy code of {function} tags called in nocache mode + foreach ($this->smarty->template_functions as $name => $function_data) { + if (isset($function_data['called_nocache'])) { + unset($function_data['called_nocache'], $this->smarty->template_functions[$name]['called_nocache']); + $this->properties['function'][$name] = $function_data; + } + } + } + } + $properties_string .= "\$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . "); /*/%%SmartyHeaderCode%%*/?>\n"; + return $properties_string . $plugins_string; + } + + /** + * Decode saved properties from compiled template and cache files + */ + public function decodeProperties ($properties) + { + $this->has_nocache_code = $properties['has_nocache_code']; + $this->properties['nocache_hash'] = $properties['nocache_hash']; + if (isset($properties['cache_lifetime'])) { + $this->properties['cache_lifetime'] = $properties['cache_lifetime']; + } + if (isset($properties['file_dependency'])) { + $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']); + } + if (!empty($properties['function'])) { + $this->properties['function'] = array_merge($this->properties['function'], $properties['function']); + $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']); + } + } + + /** + * creates a local Smarty variable for array assignments + */ + public function createLocalArrayVariable($tpl_var, $nocache = false, $scope = Smarty::SCOPE_LOCAL) + { + if (!isset($this->tpl_vars[$tpl_var])) { + $tpl_var_inst = $this->getVariable($tpl_var, null, true, false); + if ($tpl_var_inst instanceof Undefined_Smarty_Variable) { + $this->tpl_vars[$tpl_var] = new Smarty_variable(array(), $nocache, $scope); + } else { + $this->tpl_vars[$tpl_var] = clone $tpl_var_inst; + if ($scope != Smarty::SCOPE_LOCAL) { + $this->tpl_vars[$tpl_var]->scope = $scope; + } + } + } + if (!(is_array($this->tpl_vars[$tpl_var]->value) || $this->tpl_vars[$tpl_var]->value instanceof ArrayAccess)) { + settype($this->tpl_vars[$tpl_var]->value, 'array'); + } + } + + /** + * [util function] counts an array, arrayaccess/traversable or PDOStatement object + * @param mixed $value + * @return int the count for arrays and objects that implement countable, 1 for other objects that don't, and 0 for empty elements + */ + public function _count($value) + { + if (is_array($value) === true || $value instanceof Countable) { + return count($value); + } elseif ($value instanceof Iterator) { + $value->rewind(); + if ($value->valid()) { + return iterator_count($value); + } + } elseif ($value instanceof PDOStatement) { + return $value->rowCount(); + } elseif ($value instanceof Traversable) { + return iterator_count($value); + } elseif ($value instanceof ArrayAccess) { + if ($value->offsetExists(0)) { + return 1; + } + } elseif (is_object($value)) { + return count($value); + } + return 0; + } + + /** + * wrapper for fetch + */ + public function fetch ($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false) + { + if ($template == null) { + return $this->smarty->fetch($this); + } else { + if (!isset($parent)) { + $parent = $this; + } + return $this->smarty->fetch($template, $cache_id, $compile_id, $parent, $display); + } + + } + + /** + * wrapper for display + */ + public function display ($template = null, $cache_id = null, $compile_id = null, $parent = null) + { + if ($template == null) { + return $this->smarty->display($this); + } else { + if (!isset($parent)) { + $parent = $this; + } + return $this->smarty->display($template, $cache_id, $compile_id, $parent); + } + + } + + /** + * set Smarty property in template context + * @param string $property_name property name + * @param mixed $value value + */ + public function __set($property_name, $value) + { + if ($property_name == 'resource_object' || $property_name == 'cache_resource_object') { + $this->$property_name = $value; + } elseif (property_exists($this->smarty, $property_name)) { + $this->smarty->$property_name = $value; + } else { + throw new SmartyException("invalid template property '$property_name'."); + } + } + + /** + * get Smarty property in template context + * @param string $property_name property name + */ + public function __get($property_name) + { + if ($property_name == 'resource_object') { + // load template resource + $this->resource_object = null; + if (!$this->parseResourceName ($this->template_resource, $this->resource_type, $this->resource_name, $this->resource_object)) { + throw new SmartyException ("Unable to parse resource name \"{$template_resource}\""); + } + return $this->resource_object; + } + if ($property_name == 'cache_resource_object') { + // load cache resource + $this->cache_resource_object = $this->loadCacheResource(); + return $this->cache_resource_object; + } + if (property_exists($this->smarty, $property_name)) { + return $this->smarty->$property_name; + } else { + throw new SmartyException("template property '$property_name' does not exist."); + } + } + + + /** + * Takes unknown class methods and lazy loads sysplugin files for them + * class name format: Smarty_Method_MethodName + * plugin filename format: method.methodname.php + * + * @param string $name unknown methode name + * @param array $args aurgument array + */ + public function __call($name, $args) + { + static $camel_func; + if (!isset($camel_func)) + $camel_func = create_function('$c', 'return "_" . strtolower($c[1]);'); + // see if this is a set/get for a property + $first3 = strtolower(substr($name, 0, 3)); + if (in_array($first3, array('set', 'get')) && substr($name, 3, 1) !== '_') { + // try to keep case correct for future PHP 6.0 case-sensitive class methods + // lcfirst() not available < PHP 5.3.0, so improvise + $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4); + // convert camel case to underscored name + $property_name = preg_replace_callback('/([A-Z])/', $camel_func, $property_name); + if (property_exists($this, $property_name)) { + if ($first3 == 'get') + return $this->$property_name; + else + return $this->$property_name = $args[0]; + } + } + // Smarty Backward Compatible wrapper + if (strpos($name,'_') !== false) { + if (!isset($this->wrapper)) { + $this->wrapper = new Smarty_Internal_Wrapper($this); + } + return $this->wrapper->convert($name, $args); + } + // pass call to Smarty object + return call_user_func_array(array($this->smarty,$name),$args); + } + +} +?> \ No newline at end of file