public function setUp() { $this->smarty = SmartyTests::$smarty; // reset cache for unit test Smarty_Resource::$resources = array(); SmartyTests::init(); }
/** * populate Source Object with meta data from Resource * * @param Smarty_Template_Source $source source object * @param Smarty_Internal_Template $_template template object * * @return void */ public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { $uid = ''; $sources = array(); $timestamp = 0; foreach ($_template->smarty->getTemplateDir() as $key => $directory) { try { $s = Smarty_Resource::source(null, $source->smarty, 'file:' . '[' . $key . ']' . $source->name); if (!$s->exists) { continue; } $sources[$s->uid] = $s; $uid .= $s->filepath; $timestamp = $s->timestamp > $timestamp ? $s->timestamp : $timestamp; } catch (SmartyException $e) { } } if (!$sources) { $source->exists = false; return; } $sources = array_reverse($sources, true); reset($sources); $s = current($sources); $source->components = $sources; $source->filepath = $s->filepath; $source->uid = sha1($uid . $_template->smarty->_joined_template_dir); $source->exists = true; $source->timestamp = $timestamp; }
/** * populate Source Object with meta data from Resource * * @param Smarty_Template_Source $source source object * @param Smarty_Internal_Template $_template template object */ public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { $uid = ''; $sources = array(); $components = explode('|', $source->name); $exists = true; foreach ($components as $component) { $s = Smarty_Resource::source(null, $source->smarty, $component); if ($s->type == 'php') { throw new SmartyException("Resource type {$s->type} cannot be used with the extends resource type"); } $sources[$s->uid] = $s; $uid .= $s->filepath; if ($_template && $_template->smarty->compile_check) { $exists = $exists && $s->exists; } } $source->components = $sources; $source->filepath = $s->filepath; $source->uid = sha1($uid); if ($_template && $_template->smarty->compile_check) { $source->timestamp = $s->timestamp; $source->exists = $exists; } // need the template at getContent() $source->template = $_template; }
/** * get default content from template or config resource handler * * @param Smarty_Template_Source $source * * @throws \SmartyException */ public static function _getDefaultTemplate(Smarty_Template_Source $source) { if ($source->isConfig) { $default_handler = $source->smarty->default_config_handler_func; } else { $default_handler = $source->smarty->default_template_handler_func; } $_content = $_timestamp = null; $_return = call_user_func_array($default_handler, array($source->type, $source->name, &$_content, &$_timestamp, $source->smarty)); if (is_string($_return)) { $source->exists = is_file($_return); if ($source->exists) { $source->timestamp = filemtime($_return); } else { throw new SmartyException("Default handler: Unable to load " . ($source->isConfig ? 'config' : 'template') . " default file '{$_return}' for '{$source->type}:{$source->name}'"); } $source->name = $source->filepath = $_return; $source->uid = sha1($source->filepath); } elseif ($_return === true) { $source->content = $_content; $source->exists = true; $source->uid = $source->name = sha1($_content); $source->handler = Smarty_Resource::load($source->smarty, 'eval'); } else { $source->exists = false; throw new SmartyException('Default handler: No ' . ($source->isConfig ? 'config' : 'template') . " default content for '{$source->type}:{$source->name}'"); } }
/** * populate Source Object with meta data from Resource * * @param Smarty_Template_Source $source source object * @param Smarty_Internal_Template $_template template object * * @return void */ public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { $uid = ''; $sources = array(); $exists = true; foreach ($_template->smarty->getTemplateDir() as $key => $directory) { try { $s = Smarty_Resource::source(null, $source->smarty, '[' . $key . ']' . $source->name); if (!$s->exists) { continue; } $sources[$s->uid] = $s; $uid .= $s->filepath; } catch (SmartyException $e) { } } if (!$sources) { $source->exists = false; $source->template = $_template; return; } $sources = array_reverse($sources, true); reset($sources); $s = current($sources); $source->components = $sources; $source->filepath = $s->filepath; $source->uid = sha1($uid); $source->exists = $exists; if ($_template && $_template->smarty->compile_check) { $source->timestamp = $s->timestamp; } // need the template at getContent() $source->template = $_template; }
/** * This function is executed automatically when a compiled or cached template file is included * - Decode saved properties from compiled template and cache files * - Check if compiled or cache file is valid * * @param array $properties special template properties * @param bool $cache flag if called from cache file * * @return bool flag if compiled or cache file is valid */ public function decodeProperties(Smarty_Internal_Template $tpl, $properties, $cache = false) { $is_valid = true; if (Smarty::SMARTY_VERSION != $properties['version']) { // new version must rebuild $is_valid = false; } elseif ($is_valid && !empty($properties['file_dependency']) && (!$cache && $tpl->smarty->compile_check || $tpl->smarty->compile_check == 1)) { // check file dependencies at compiled code foreach ($properties['file_dependency'] as $_file_to_check) { if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'extends' || $_file_to_check[2] == 'php') { if ($tpl->source->filepath == $_file_to_check[0]) { // do not recheck current template continue; //$mtime = $tpl->source->getTimeStamp(); } else { // file and php types can be checked without loading the respective resource handlers $mtime = is_file($_file_to_check[0]) ? filemtime($_file_to_check[0]) : false; } } elseif ($_file_to_check[2] == 'string') { continue; } else { $handler = Smarty_Resource::load($tpl->smarty, $_file_to_check[2]); if ($handler->checkTimestamps()) { $source = Smarty_Template_Source::load($tpl, $tpl->smarty, $_file_to_check[0]); $mtime = $source->getTimeStamp(); } else { continue; } } if (!$mtime || $mtime > $_file_to_check[1]) { $is_valid = false; break; } } } if ($cache) { // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc if ($tpl->caching === Smarty::CACHING_LIFETIME_SAVED && $properties['cache_lifetime'] >= 0 && time() > $tpl->cached->timestamp + $properties['cache_lifetime']) { $is_valid = false; } $tpl->cached->cache_lifetime = $properties['cache_lifetime']; $tpl->cached->valid = $is_valid; $resource = $tpl->cached; } else { $tpl->mustCompile = !$is_valid; $resource = $tpl->compiled; $resource->includes = isset($properties['includes']) ? $properties['includes'] : array(); } if ($is_valid) { $resource->unifunc = $properties['unifunc']; $resource->has_nocache_code = $properties['has_nocache_code']; // $tpl->compiled->nocache_hash = $properties['nocache_hash']; $resource->file_dependency = $properties['file_dependency']; if (isset($properties['tpl_function'])) { $tpl->tpl_function = $properties['tpl_function']; } } return $is_valid && !function_exists($properties['unifunc']); }
public static function init() { error_reporting(E_ALL | E_STRICT); self::_init(SmartyTests::$smarty); self::_init(SmartyTests::$smartyBC); SmartyTests::$smartyBC->registerPlugin('block', 'php', 'smarty_php_tag'); Smarty_Resource::$sources = array(); Smarty_Resource::$compileds = array(); }
public function setUp() { $this->smarty = SmartyTests::$smarty; SmartyTests::init(); // empty the template dir $this->smarty->setTemplateDir(array()); // kill cache for unit test Smarty_Resource::$resources = array(); $this->smarty->_resource_handlers = array(); }
/** * populate Source Object with meta data from Resource * * @param Smarty_Template_Source $source source object * @param Smarty_Internal_Template $_template template object */ public function populate(Smarty_Template_Source $source, Smarty_Internal_Template $_template = null) { $filePath = $this->buildFilepath($source, $_template); $s = Smarty_Resource::source(null, $source->smarty, $filePath); $source->components = $s; $source->filepath = $s->filepath; $source->uid = $s->uid; if ($_template && $_template->smarty->compile_check) { $source->timestamp = $s->timestamp; $source->exists = $s->exists; } $source->template = $_template; }
/** * render the uncompiled source * @param Smarty_Internal_Template $_template template object */ public function renderUncompiled(Smarty_Internal_Template $_template) { $level = ob_get_level(); ob_start(); try { $this->handler->renderUncompiled($_template->source, $_template); return ob_get_clean(); } catch (Exception $e) { while (ob_get_level() > $level) { ob_end_clean(); } throw $e; } }
/** * generate compiled files * @uses $_files to store references * @return array list of files array( id => path ) */ protected function makeFiles() { $this->_files = array(); $directory_length = strlen($this->smarty->getCompileDir()); $templates = array('helloworld.tpl' => array(null, 'compile1', 'compile2'), 'helloworld2.tpl' => array(null, 'compile1', 'compile2'), 'ambiguous/case1/foobar.tpl' => array(null, 'compile1', 'compile2'), '[1]ambiguous/case1/foobar.tpl' => array(null, 'compile1', 'compile2')); foreach ($templates as $template => $compile_ids) { foreach ($compile_ids as $compile_id) { $tpl = $this->smarty->createTemplate($template, null, $compile_id); $tpl->fetch(); $this->_files[$template . '#' . $compile_id] = substr($tpl->compiled->filepath, $directory_length - 1); } } Smarty_Resource::$sources = array(); $this->smarty->template_objects = array(); return $this->_files; }
/** * initialize Source Object for given resource * Either [$_template] or [$smarty, $template_resource] must be specified * * @param Smarty_Internal_Template $_template template object * @param Smarty $smarty smarty object * @param string $template_resource resource identifier * * @return Smarty_Template_Config Source Object * @throws SmartyException */ public static function load(Smarty_Internal_Template $_template = null, Smarty $smarty = null, $template_resource = null) { static $_incompatible_resources = array('extends' => true, 'php' => true); $template_resource = $_template->template_resource; if (empty($template_resource)) { throw new SmartyException('Missing config name'); } // parse resource_name, load resource handler list($name, $type) = Smarty_Resource::parseResourceName($template_resource, $_template->smarty->default_config_type); // make sure configs are not loaded via anything smarty can't handle if (isset($_incompatible_resources[$type])) { throw new SmartyException("Unable to use resource '{$type}' for config"); } $source = new Smarty_Template_Config($_template->smarty, $template_resource, $type, $name); $source->handler->populate($source, $_template); if (!$source->exists && isset($_template->smarty->default_config_handler_func)) { Smarty_Internal_Method_RegisterDefaultTemplateHandler::_getDefaultTemplate($source); } return $source; }
/** * Set source object of inline template by $uid * * @param \Smarty_Internal_Template $tpl * @param string $uid * * @throws \SmartyException */ public function setSource(Smarty_Internal_Template $tpl, $uid = null) { // $uid is set if template is inline if (isset($uid)) { // inline templates have same compiled resource $tpl->compiled = $tpl->parent->compiled; if (isset($tpl->compiled->file_dependency[$uid])) { list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid]; $tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ? $tpl->smarty->_cache['resource_handlers'][$resource] : Smarty_Resource::load($tpl->smarty, $resource), $tpl->smarty, $filepath, $resource, $filepath); $tpl->source->filepath = $filepath; $tpl->source->timestamp = $timestamp; $tpl->source->exists = true; $tpl->source->uid = $uid; } else { $tpl->source = null; } } else { $tpl->source = null; unset($tpl->compiled); } if (!isset($tpl->source)) { $tpl->source = Smarty_Template_Source::load($tpl); } }
/** * Delete compiled template file * * @param string $resource_name template name * @param string $compile_id compile id * @param integer $exp_time expiration time * @param Smarty $smarty Smarty instance * * @return integer number of template files deleted */ public static function clearCompiledTemplate($resource_name, $compile_id, $exp_time, Smarty $smarty) { $_compile_dir = realpath($smarty->getCompileDir()) . '/'; $_compile_id = isset($compile_id) ? preg_replace('![^\\w\\|]+!', '_', $compile_id) : null; $_dir_sep = $smarty->use_sub_dirs ? '/' : '^'; if (isset($resource_name)) { $_save_stat = $smarty->caching; $smarty->caching = false; $tpl = new $smarty->template_class($resource_name, $smarty); $smarty->caching = $_save_stat; // remove from template cache $tpl->source; // have the template registered before unset() if ($smarty->allow_ambiguous_resources) { $_templateId = $tpl->source->unique_resource . $tpl->cache_id . $tpl->compile_id; } else { $_templateId = $smarty->joined_template_dir . '#' . $resource_name . $tpl->cache_id . $tpl->compile_id; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); } unset($smarty->template_objects[$_templateId]); if ($tpl->source->exists) { $_resource_part_1 = basename(str_replace('^', '/', $tpl->compiled->filepath)); $_resource_part_1_length = strlen($_resource_part_1); } else { return 0; } $_resource_part_2 = str_replace('.php', '.cache.php', $_resource_part_1); $_resource_part_2_length = strlen($_resource_part_2); } $_dir = $_compile_dir; if ($smarty->use_sub_dirs && isset($_compile_id)) { $_dir .= $_compile_id . $_dir_sep; } if (isset($_compile_id)) { $_compile_id_part = str_replace('\\', '/', $_compile_dir . $_compile_id . $_dir_sep); $_compile_id_part_length = strlen($_compile_id_part); } $_count = 0; try { $_compileDirs = new RecursiveDirectoryIterator($_dir); // NOTE: UnexpectedValueException thrown for PHP >= 5.3 } catch (Exception $e) { return 0; } $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); foreach ($_compile as $_file) { if (substr(basename($_file->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) { continue; } $_filepath = str_replace('\\', '/', (string) $_file); if ($_file->isDir()) { if (!$_compile->isDot()) { // delete folder if empty @rmdir($_file->getPathname()); } } else { $unlink = false; if ((!isset($_compile_id) || isset($_filepath[$_compile_id_part_length]) && ($a = !strncmp($_filepath, $_compile_id_part, $_compile_id_part_length))) && (!isset($resource_name) || isset($_filepath[$_resource_part_1_length]) && substr_compare($_filepath, $_resource_part_1, -$_resource_part_1_length, $_resource_part_1_length) == 0 || isset($_filepath[$_resource_part_2_length]) && substr_compare($_filepath, $_resource_part_2, -$_resource_part_2_length, $_resource_part_2_length) == 0)) { if (isset($exp_time)) { if (time() - @filemtime($_filepath) >= $exp_time) { $unlink = true; } } else { $unlink = true; } } if ($unlink && @unlink($_filepath)) { $_count++; } } } // clear compiled cache Smarty_Resource::$sources = array(); Smarty_Resource::$compileds = array(); return $_count; }
/** * get Smarty property in template context * * @param string $property_name property name * * @return \Smarty_Config_Source|\Smarty_Template_Compiled * @throws SmartyException if $property_name is not valid */ public function __get($property_name) { switch ($property_name) { case 'source': if (empty($this->config_resource)) { throw new SmartyException("Unable to parse resource name \"{$this->config_resource}\""); } $this->source = Smarty_Resource::config($this); return $this->source; case 'compiled': $this->compiled = $this->source->getCompiled($this); return $this->compiled; } throw new SmartyException("config attribute '{$property_name}' does not exist."); }
/** * This function is executed automatically when a compiled or cached template file is included * - Decode saved properties from compiled template and cache files * - Check if compiled or cache file is valid * * @param array $properties special template properties * @param bool $cache flag if called from cache file * * @return bool flag if compiled or cache file is valid */ public function decodeProperties($properties, $cache = false) { $properties['version'] = isset($properties['version']) ? $properties['version'] : ''; $is_valid = true; if (Smarty::SMARTY_VERSION != $properties['version']) { // new version must rebuild $is_valid = false; } elseif ((!$cache && $this->smarty->compile_check || $cache && ($this->smarty->compile_check === true || $this->smarty->compile_check === Smarty::COMPILECHECK_ON)) && !empty($properties['file_dependency'])) { // check file dependencies at compiled code foreach ($properties['file_dependency'] as $_file_to_check) { if ($_file_to_check[2] == 'file' || $_file_to_check[2] == 'php') { if ($this->source->filepath == $_file_to_check[0] && isset($this->source->timestamp)) { // do not recheck current template $mtime = $this->source->timestamp; } else { // file and php types can be checked without loading the respective resource handlers $mtime = is_file($_file_to_check[0]) ? @filemtime($_file_to_check[0]) : false; } } elseif ($_file_to_check[2] == 'string') { continue; } else { $source = Smarty_Resource::source(null, $this->smarty, $_file_to_check[0]); $mtime = $source->timestamp; } if (!$mtime || $mtime > $_file_to_check[1]) { $is_valid = false; break; } } } if ($cache) { // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc if ($this->caching === Smarty::CACHING_LIFETIME_SAVED && $properties['cache_lifetime'] >= 0 && time() > $this->cached->timestamp + $properties['cache_lifetime']) { $is_valid = false; } $this->cached->valid = $is_valid; } else { $this->mustCompile = !$is_valid; } if ($is_valid) { $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 (isset($properties['tpl_function'])) { $this->properties['tpl_function'] = array_merge($this->properties['tpl_function'], $properties['tpl_function']); } $this->properties['version'] = $properties['version']; $this->properties['unifunc'] = $properties['unifunc']; } return $is_valid; }
/** * log include count * * @param \Smarty_Internal_SmartyTemplateCompiler $compiler * @param string $include_file * @param bool $variable_template */ private function logInclude(Smarty_Internal_SmartyTemplateCompiler $compiler, $include_file, $variable_template) { if ($variable_template) { return; } list($name, $type) = Smarty_Resource::parseResourceName(trim($include_file, '\'"'), $compiler->template->smarty->default_resource_type); if (in_array($type, array('eval', 'string'))) { return; } $include_name = $type . ':' . $name; $compiled = $compiler->parent_compiler->template->compiled; $compiled->includes[$include_name] = isset($compiled->includes[$include_name]) ? $compiled->includes[$include_name] + 1 : 1; }
/** * Get unique template id * * @param string $template_name * @param null|mixed $cache_id * @param null|mixed $compile_id * * @return string */ public function getTemplateId($template_name, $cache_id = null, $compile_id = null) { $cache_id = isset($cache_id) ? $cache_id : $this->cache_id; $compile_id = isset($compile_id) ? $compile_id : $this->compile_id; $smarty = isset($this->smarty) ? $this->smarty : $this; if ($smarty->allow_ambiguous_resources) { $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}"; } else { $_templateId = $smarty->joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}"; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); } return $_templateId; }
/** * Delete compiled template file * * @param string $resource_name template name * @param string $compile_id compile id * @param integer $exp_time expiration time * @param Smarty $smarty Smarty instance * @return integer number of template files deleted */ public static function clearCompiledTemplate($resource_name, $compile_id, $exp_time, Smarty $smarty) { $_compile_dir = $smarty->getCompileDir(); $_compile_id = isset($compile_id) ? preg_replace('![^\\w\\|]+!', '_', $compile_id) : null; $_dir_sep = $smarty->use_sub_dirs ? DS : '^'; if (isset($resource_name)) { $_save_stat = $smarty->caching; $smarty->caching = false; $tpl = new $smarty->template_class($resource_name, $smarty); $smarty->caching = $_save_stat; if ($tpl->source->exists) { $_resource_part_1 = basename(str_replace('^', '/', $tpl->compiled->filepath)); // remove from template cache unset($smarty->template_objects[sha1(join(DIRECTORY_SEPARATOR, $smarty->getTemplateDir()) . $tpl->template_resource . $tpl->cache_id . $tpl->compile_id)]); } else { // remove from template cache unset($smarty->template_objects[sha1(join(DIRECTORY_SEPARATOR, $smarty->getTemplateDir()) . $tpl->template_resource . $tpl->cache_id . $tpl->compile_id)]); return 0; } $_resource_part_2 = str_replace('.php', '.cache.php', $_resource_part_1); } else { $_resource_part = ''; } $_dir = $_compile_dir; if ($smarty->use_sub_dirs && isset($_compile_id)) { $_dir .= $_compile_id . $_dir_sep; } if (isset($_compile_id)) { $_compile_id_part = $_compile_dir . $_compile_id . $_dir_sep; } $_count = 0; $_compileDirs = new RecursiveDirectoryIterator($_dir); $_compile = new RecursiveIteratorIterator($_compileDirs, RecursiveIteratorIterator::CHILD_FIRST); foreach ($_compile as $_file) { if (substr($_file->getBasename(), 0, 1) == '.' || strpos($_file, '.svn') !== false) { continue; } if ($_file->isDir()) { if (!$_compile->isDot()) { // delete folder if empty @rmdir($_file->getPathname()); } } else { if ((!isset($_compile_id) || strlen((string) $_file) > strlen($_compile_id_part) && substr_compare((string) $_file, $_compile_id_part, 0, strlen($_compile_id_part)) == 0) && (!isset($resource_name) || strlen((string) $_file) > strlen($_resource_part_1) && substr_compare((string) $_file, $_resource_part_1, -strlen($_resource_part_1), strlen($_resource_part_1)) == 0 || strlen((string) $_file) > strlen($_resource_part_2) && substr_compare((string) $_file, $_resource_part_2, -strlen($_resource_part_2), strlen($_resource_part_2)) == 0)) { if (isset($exp_time)) { if (time() - @filemtime($_file) >= $exp_time) { $_count += @unlink((string) $_file) ? 1 : 0; } } else { $_count += @unlink((string) $_file) ? 1 : 0; } } } } // clear compiled cache Smarty_Resource::$sources = array(); Smarty_Resource::$compileds = array(); return $_count; }
/** * modify template_resource according to resource handlers specifications * * @param \Smarty_Internal_Template|\Smarty $obj Smarty instance * @param string $template_resource template_resource to extract resource handler and name of * * @return string unique resource name */ public static function getUniqueTemplateName($obj, $template_resource) { $smarty = $obj->_objType == 2 ? $obj->smarty : $obj; list($name, $type) = self::parseResourceName($template_resource, $smarty->default_resource_type); // TODO: optimize for Smarty's internal resource types $resource = Smarty_Resource::load($smarty, $type); // go relative to a given template? $_file_is_dotted = $name[0] == '.' && ($name[1] == '.' || $name[1] == '/'); if ($obj->_objType == 2 && $_file_is_dotted && ($obj->source->type == 'file' || $obj->parent->source->type == 'extends')) { $name = dirname($obj->source->filepath) . DS . $name; } return $resource->buildUniqueResourceName($smarty, $name); }
/** * Runtime function to render subtemplate * * @param \Smarty_Internal_Template $parent * @param string $template template name * @param mixed $cache_id cache id * @param mixed $compile_id compile id * @param integer $caching cache mode * @param integer $cache_lifetime life time of cache data * @param array $data passed parameter template variables * @param int $scope scope in which {include_test} should execute * @param bool $forceTplCache cache template object * @param string $uid file dependency uid * @param string $content_func function name * */ public function render(Smarty_Internal_Template $parent, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $scope, $forceTplCache, $uid = null, $content_func = null) { // if there are cached template objects calculate $templateID $_templateId = !empty($this->tplObjects) ? $parent->smarty->_getTemplateId($template, $cache_id, $compile_id, $caching) : null; // already in template cache? /* @var Smarty_Internal_Template $tpl */ if (isset($_templateId) && isset($this->tplObjects[$_templateId])) { // clone cached template object because of possible recursive call $tpl = clone $this->tplObjects[$_templateId]; $tpl->parent = $parent; // if $caching mode changed the compiled resource is invalid if ((bool) $tpl->caching !== (bool) $caching) { unset($tpl->compiled); } // get variables from calling scope $tpl->tpl_vars = $parent->tpl_vars; $tpl->config_vars = $parent->config_vars; // get template functions $tpl->tpl_function = $parent->tpl_function; // copy inheritance object? if (isset($parent->ext->_inheritance)) { $tpl->ext->_inheritance = $parent->ext->_inheritance; } else { unset($tpl->ext->_inheritance); } } else { $tpl = clone $parent; $tpl->parent = $parent; if (!isset($tpl->templateId) || $tpl->templateId !== $_templateId) { $tpl->templateId = $_templateId; $tpl->template_resource = $template; $tpl->cache_id = $cache_id; $tpl->compile_id = $compile_id; if (isset($uid)) { // for inline templates we can get all resource information from file dependency if (isset($tpl->compiled->file_dependency[$uid])) { list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid]; $tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ? $tpl->smarty->_cache['resource_handlers'][$resource] : Smarty_Resource::load($tpl->smarty, $resource), $tpl->smarty, $filepath, $resource, $filepath); $tpl->source->filepath = $filepath; $tpl->source->timestamp = $timestamp; $tpl->source->exists = true; $tpl->source->uid = $uid; } else { $tpl->source = null; } } else { $tpl->source = null; } if (!isset($tpl->source)) { $tpl->source = Smarty_Template_Source::load($tpl); unset($tpl->compiled); } unset($tpl->cached); } } $tpl->caching = $caching; $tpl->cache_lifetime = $cache_lifetime; if ($caching == 9999) { $tpl->cached = $parent->cached; } // set template scope $tpl->scope = $scope; $scopePtr = false; if ($scope & ~Smarty::SCOPE_BUBBLE_UP) { if ($scope == Smarty::SCOPE_GLOBAL) { $tpl->tpl_vars = Smarty::$global_tpl_vars; $tpl->config_vars = $tpl->smarty->config_vars; $scopePtr = true; } else { if ($scope == Smarty::SCOPE_PARENT) { $scopePtr = $parent; } elseif ($scope == Smarty::SCOPE_SMARTY) { $scopePtr = $tpl->smarty; } else { $scopePtr = $tpl; while (isset($scopePtr->parent)) { if ($scopePtr->parent->_objType != 2 && $scope & Smarty::SCOPE_TPL_ROOT) { break; } $scopePtr = $scopePtr->parent; } } $tpl->tpl_vars = $scopePtr->tpl_vars; $tpl->config_vars = $scopePtr->config_vars; } } if (!isset($this->tplObjects[$tpl->_getTemplateId()]) && !$tpl->source->handler->recompiled) { // if template is called multiple times set flag to to cache template objects $forceTplCache = $forceTplCache || isset($this->subTplInfo[$tpl->template_resource]) && $this->subTplInfo[$tpl->template_resource] > 1; // check if template object should be cached if ($tpl->parent->_objType == 2 && isset($this->tplObjects[$tpl->parent->templateId]) || $forceTplCache && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC || $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON) { $this->tplObjects[$tpl->_getTemplateId()] = $tpl; } } if (!empty($data)) { // set up variable values foreach ($data as $_key => $_val) { $tpl->tpl_vars[$_key] = new Smarty_Variable($_val); } } if (isset($uid)) { if ($parent->smarty->debugging) { $parent->smarty->_debug->start_template($tpl); $parent->smarty->_debug->start_render($tpl); } $tpl->compiled->getRenderedTemplateCode($tpl, $content_func); if ($parent->smarty->debugging) { $parent->smarty->_debug->end_template($tpl); $parent->smarty->_debug->end_render($tpl); } if ($tpl->caching == 9999 && $tpl->compiled->has_nocache_code) { $parent->cached->hashes[$tpl->compiled->nocache_hash] = true; } } else { if (isset($tpl->compiled)) { $tpl->compiled->render($tpl); } else { $tpl->render(); } } if ($scopePtr) { if ($scope == Smarty::SCOPE_GLOBAL) { Smarty::$global_tpl_vars = $tpl->tpl_vars; $tpl->smarty->config_vars = $tpl->config_vars; } else { $scopePtr->tpl_vars = $tpl->tpl_vars; $scopePtr->config_vars = $tpl->config_vars; } } }
/** * <<magic>> Generic getter. * * @param string $property_name valid: timestamp, exists, content * * @return mixed * @throws SmartyException if $property_name is not valid */ public function __get($property_name) { switch ($property_name) { case 'content': return $this->content = $this->handler->getContent($this); default: throw new SmartyException("source property '{$property_name}' does not exist."); } }
/** * Compiles code for the {include} tag * * @param array $args array with attributes from parser * @param Smarty_Internal_SmartyTemplateCompiler $compiler compiler object * @param array $parameter array with compilation parameter * * @throws SmartyCompilerException * @return string compiled code */ public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter) { // check and get attributes $_attr = $this->getAttributes($compiler, $args); $hashResourceName = $fullResourceName = $source_resource = $_attr['file']; $variable_template = false; $cache_tpl = false; // parse resource_name if (preg_match('/^([\'"])(([A-Za-z0-9_\\-]{2,})[:])?(([^$()]+)|(.+))\\1$/', $source_resource, $match)) { $type = !empty($match[3]) ? $match[3] : $compiler->template->smarty->default_resource_type; $name = !empty($match[5]) ? $match[5] : $match[6]; $handler = Smarty_Resource::load($compiler->smarty, $type); if ($handler->recompiled || $handler->uncompiled) { $variable_template = true; } if (!$variable_template) { if ($type != 'string') { $fullResourceName = "{$type}:{$name}"; $compiled = $compiler->parent_compiler->template->compiled; if (isset($compiled->includes[$fullResourceName])) { $compiled->includes[$fullResourceName]++; $cache_tpl = true; } else { $compiled->includes[$fullResourceName] = 1; } $fullResourceName = "'{$fullResourceName}'"; } } if (empty($match[5])) { $variable_template = true; } } else { $variable_template = true; } if ($compiler->inheritanceForceChild) { $hashResourceName .= '-child'; } if (isset($_attr['assign'])) { // output will be stored in a smarty variable instead of being displayed $_assign = $_attr['assign']; } $_parent_scope = Smarty::SCOPE_LOCAL; if (isset($_attr['scope'])) { $_attr['scope'] = trim($_attr['scope'], "'\""); if ($_attr['scope'] == 'parent') { $_parent_scope = Smarty::SCOPE_PARENT; } elseif ($_attr['scope'] == 'root') { $_parent_scope = Smarty::SCOPE_ROOT; } elseif ($_attr['scope'] == 'global') { $_parent_scope = Smarty::SCOPE_GLOBAL; } } // if ($cache_tpl || $variable_template || $compiler->loopNesting > 0) { $_cache_tpl = 'true'; } else { $_cache_tpl = 'false'; } // assume caching is off $_caching = Smarty::CACHING_OFF; if ($_attr['nocache'] === true) { $compiler->tag_nocache = true; } $call_nocache = $compiler->tag_nocache || $compiler->nocache; // caching was on and {include} is not in nocache mode if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) { $_caching = self::CACHING_NOCACHE_CODE; } // flag if included template code should be merged into caller $merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || $_attr['inline'] === true) && !$compiler->template->source->handler->recompiled; if ($merge_compiled_includes && $_attr['inline'] !== true) { // variable template name ? if ($variable_template) { $merge_compiled_includes = false; if ($compiler->template->caching) { // must use individual cache file //$_attr['caching'] = 1; } } // variable compile_id? if (isset($_attr['compile_id'])) { if (!(substr_count($_attr['compile_id'], '"') == 2 || substr_count($_attr['compile_id'], "'") == 2 || is_numeric($_attr['compile_id'])) || substr_count($_attr['compile_id'], '(') != 0 || substr_count($_attr['compile_id'], '$_smarty_tpl->') != 0) { $merge_compiled_includes = false; if ($compiler->template->caching) { // must use individual cache file //$_attr['caching'] = 1; } } } } /* * if the {include} tag provides individual parameter for caching or compile_id * the subtemplate must not be included into the common cache file and is treated like * a call in nocache mode. * */ if ($_attr['nocache'] !== true && $_attr['caching']) { $_caching = $_new_caching = (int) $_attr['caching']; $call_nocache = true; } else { $_new_caching = Smarty::CACHING_LIFETIME_CURRENT; } if (isset($_attr['cache_lifetime'])) { $_cache_lifetime = $_attr['cache_lifetime']; $call_nocache = true; $_caching = $_new_caching; } else { $_cache_lifetime = '$_smarty_tpl->cache_lifetime'; } if (isset($_attr['cache_id'])) { $_cache_id = $_attr['cache_id']; $call_nocache = true; $_caching = $_new_caching; } else { $_cache_id = '$_smarty_tpl->cache_id'; } if (isset($_attr['compile_id'])) { $_compile_id = $_attr['compile_id']; } else { $_compile_id = '$_smarty_tpl->compile_id'; } // if subtemplate will be called in nocache mode do not merge if ($compiler->template->caching && $call_nocache) { $merge_compiled_includes = false; } $has_compiled_template = false; if ($merge_compiled_includes) { $c_id = isset($_attr['compile_id']) ? $_attr['compile_id'] : $compiler->template->compile_id; // we must observe different compile_id and caching $t_hash = sha1($c_id . ($_caching ? '--caching' : '--nocaching')); if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash])) { $has_compiled_template = $this->compileInlineTemplate($compiler, $fullResourceName, $_caching, $hashResourceName, $t_hash, $c_id); } else { $has_compiled_template = true; } } // delete {include} standard attributes unset($_attr['file'], $_attr['assign'], $_attr['cache_id'], $_attr['compile_id'], $_attr['cache_lifetime'], $_attr['nocache'], $_attr['caching'], $_attr['scope'], $_attr['inline']); // remaining attributes must be assigned as smarty variable $_vars_nc = ''; if (!empty($_attr)) { if ($_parent_scope == Smarty::SCOPE_LOCAL) { $_pairs = array(); // create variables foreach ($_attr as $key => $value) { $_pairs[] = "'{$key}'=>{$value}"; $_vars_nc .= "\$_smarty_tpl->tpl_vars['{$key}'] = new Smarty_Variable({$value});\n"; } $_vars = 'array(' . join(',', $_pairs) . ')'; } else { $compiler->trigger_template_error('variable passing not allowed in parent/global scope', null, true); } } else { $_vars = 'array()'; } $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache && $_compile_id != '$_smarty_tpl->compile_id'; if ($has_compiled_template && !$call_nocache) { $_output = "<?php\n"; if ($update_compile_id) { $_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n"); } if (!empty($_vars_nc) && $_caching == 9999 && $compiler->template->caching) { //$compiler->suppressNocacheProcessing = false; $_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, -3); //$compiler->suppressNocacheProcessing = true; } if (isset($_assign)) { $_output .= "ob_start();\n"; } $_output .= "\$_smarty_tpl->renderInline(\$_smarty_tpl->setupSubTemplate({$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl}, '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['uid']}'), '{$compiler->parent_compiler->mergedSubTemplatesData[$hashResourceName][$t_hash]['func']}');\n"; if (isset($_assign)) { $_output .= "\$_smarty_tpl->tpl_vars[{$_assign}] = new Smarty_Variable(ob_get_clean());\n"; } if ($update_compile_id) { $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"); } $_output .= "?>\n"; return $_output; } if ($call_nocache) { $compiler->tag_nocache = true; } $_output = "<?php "; if ($update_compile_id) { $_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n"; } // was there an assign attribute if (isset($_assign)) { $_output .= "ob_start();\n"; } $_output .= "\$_smarty_tpl->setupSubTemplate({$fullResourceName}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, {$_cache_tpl})->render();\n"; if (isset($_assign)) { $_output .= "\$_smarty_tpl->tpl_vars[{$_assign}] = new Smarty_Variable(ob_get_clean());\n"; } if ($update_compile_id) { $_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"; } $_output .= "?>\n"; return $_output; }
/** * Template code runtime function to set up an inline subtemplate * * @param string $template template name * @param mixed $cache_id cache id * @param mixed $compile_id compile id * @param integer $caching cache mode * @param integer $cache_lifetime life time of cache data * @param array $data passed parameter template variables * @param int $parent_scope scope in which {include} should execute * @param bool $cache_tpl_obj cache template object * @param string|null $uid source uid * * @return \Smarty_Internal_Template template object * @throws \SmartyException */ public function setupSubtemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $uid = null) { // if there are cached template objects calculate $templateID $_templateId = isset($this->smarty->_cache['template_objects']) ? $this->smarty->_getTemplateId($template, $cache_id, $compile_id) : null; // already in template cache? /* @var Smarty_Internal_Template $tpl */ if (isset($this->smarty->_cache['template_objects'][$_templateId])) { // clone cached template object because of possible recursive call $tpl = clone $this->smarty->_cache['template_objects'][$_templateId]; $tpl->parent = $this; // if $caching mode changed the compiled resource is invalid if ((bool) $tpl->caching !== (bool) $caching) { unset($tpl->compiled); } // get variables from calling scope if ($parent_scope == Smarty::SCOPE_LOCAL) { $tpl->tpl_vars = $this->tpl_vars; $tpl->config_vars = $this->config_vars; } $tpl->tpl_function = $this->tpl_function; // copy inheritance object? if (isset($this->_inheritance)) { $tpl->_inheritance = $this->_inheritance; } else { unset($tpl->_inheritance); } } else { $tpl = clone $this; $tpl->parent = $this; if (!isset($tpl->templateId) || $tpl->templateId !== $_templateId) { $tpl->templateId = $_templateId; $tpl->template_resource = $template; $tpl->cache_id = $cache_id; $tpl->compile_id = $compile_id; // $uid is set if template is inline if (isset($uid)) { // inline templates have same compiled resource $tpl->compiled = $this->compiled; // if template is called multiple times set flag to to cache template objects if (isset($tpl->compiled->includes[$template]) && $tpl->compiled->includes[$template] > 1) { $cache_tpl_obj = true; } if (isset($tpl->compiled->file_dependency[$uid])) { list($filepath, $timestamp, $resource) = $tpl->compiled->file_dependency[$uid]; $tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$resource]) ? $tpl->smarty->_cache['resource_handlers'][$resource] : Smarty_Resource::load($tpl->smarty, $resource), $tpl->smarty, $filepath, $resource, $filepath); $tpl->source->filepath = $filepath; $tpl->source->timestamp = $timestamp; $tpl->source->exist = true; $tpl->source->uid = $uid; } else { $tpl->source = null; } } else { $tpl->source = null; unset($tpl->compiled); } if (!isset($tpl->source)) { $tpl->source = Smarty_Template_Source::load($tpl); } unset($tpl->cached); // check if template object should be cached if (!$tpl->source->handler->recompiled && (isset($tpl->parent->templateId) && isset($tpl->smarty->_cache['template_objects'][$tpl->parent->templateId]) || $cache_tpl_obj && $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_AUTOMATIC || $tpl->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON)) { $tpl->smarty->_cache['template_objects'][$tpl->_getTemplateId()] = $tpl; } } } $tpl->caching = $caching; $tpl->cache_lifetime = $cache_lifetime; if ($caching == 9999) { $tpl->cached = $this->cached; } // get variables from calling scope if ($parent_scope != Smarty::SCOPE_LOCAL) { if ($parent_scope == Smarty::SCOPE_PARENT) { $tpl->tpl_vars =& $this->tpl_vars; $tpl->config_vars =& $this->config_vars; } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { $tpl->tpl_vars =& Smarty::$global_tpl_vars; $tpl->config_vars = $this->config_vars; } elseif ($parent_scope == Smarty::SCOPE_ROOT) { $ptr = $tpl->parent; while (!empty($ptr->parent)) { $ptr = $ptr->parent; } $tpl->tpl_vars =& $ptr->tpl_vars; $tpl->config_vars =& $ptr->config_vars; } else { $tpl->tpl_vars = $this->tpl_vars; $tpl->config_vars = $this->config_vars; } } if (!empty($data)) { // set up variable values foreach ($data as $_key => $_val) { $tpl->tpl_vars[$_key] = new Smarty_Variable($_val); } } return $tpl; }
/** * <<magic>> Generic getter. * * @param string $property_name valid: timestamp, exists, content * @return mixed * @throws SmartyException if $property_name is not valid */ public function __get($property_name) { switch ($property_name) { case 'timestamp': case 'exists': $this->handler->populateTimestamp($this); return $this->{$property_name}; case 'content': return $this->content = $this->handler->getContent($this); default: throw new SmartyException("source property '{$property_name}' does not exist."); } }
/** * Get source content * * @return string */ public function getContent() { return isset($this->content) ? $this->content : $this->handler->getContent($this); }
/** * get Smarty property in template context * * @param string $property_name property name */ public function __get($property_name) { switch ($property_name) { case 'source': if (empty($this->template_resource)) { throw new SmartyException("Unable to parse resource name \"{$this->template_resource}\""); } $this->source = Smarty_Resource::source($this); // cache template object under a unique ID // do not cache eval resources if ($this->source->type != 'eval') { if ($this->smarty->allow_ambiguous_resources) { $_templateId = $this->source->unique_resource . $this->cache_id . $this->compile_id; } else { $_templateId = $this->smarty->joined_template_dir . '#' . $this->template_resource . $this->cache_id . $this->compile_id; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); } $this->smarty->template_objects[$_templateId] = $this; } return $this->source; case 'compiled': $this->compiled = $this->source->getCompiled($this); return $this->compiled; case 'cached': if (!class_exists('Smarty_Template_Cached')) { include SMARTY_SYSPLUGINS_DIR . 'smarty_cacheresource.php'; } $this->cached = new Smarty_Template_Cached($this); return $this->cached; case 'compiler': $this->smarty->loadPlugin($this->source->compiler_class); $this->compiler = new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class, $this->smarty); return $this->compiler; // FIXME: routing of template -> smarty attributes // FIXME: routing of template -> smarty attributes default: if (property_exists($this->smarty, $property_name)) { return $this->smarty->{$property_name}; } } throw new SmartyException("template property '{$property_name}' does not exist."); }
/** * Get unique template id * * @param string $template_name * @param null|mixed $cache_id * @param null|mixed $compile_id * @param null $caching * * @return string */ public function _getTemplateId($template_name, $cache_id = null, $compile_id = null, $caching = null) { $cache_id = $cache_id === null ? $this->cache_id : $cache_id; $compile_id = $compile_id === null ? $this->compile_id : $compile_id; $caching = (int) ($caching === null ? $this->caching : $caching); if ($this->allow_ambiguous_resources) { $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template_name) . "#{$cache_id}#{$compile_id}#{$caching}"; } else { $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}"; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); } return $_templateId; }
/** * creates a template object * * @param string $template the resource handle of the template file * @param mixed $cache_id cache id to be used with this template * @param mixed $compile_id compile id to be used with this template * @param object $parent next higher level of Smarty variables * @param boolean $do_clone flag is Smarty object shall be cloned * @return object template object */ public function createTemplate($template, $cache_id = null, $compile_id = null, $parent = null, $do_clone = true) { if (!empty($cache_id) && (is_object($cache_id) || is_array($cache_id))) { $parent = $cache_id; $cache_id = null; } if (!empty($parent) && is_array($parent)) { $data = $parent; $parent = null; } else { $data = null; } // default to cache_id and compile_id of Smarty object $cache_id = $cache_id === null ? $this->cache_id : $cache_id; $compile_id = $compile_id === null ? $this->compile_id : $compile_id; // already in template cache? if ($this->allow_ambiguous_resources) { $_templateId = Smarty_Resource::getUniqueTemplateName($this, $template) . $cache_id . $compile_id; } else { $_templateId = $this->joined_template_dir . '#' . $template . $cache_id . $compile_id; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); } if ($do_clone) { if (isset($this->template_objects[$_templateId])) { // return cached template object $tpl = clone $this->template_objects[$_templateId]; $tpl->smarty = clone $tpl->smarty; $tpl->parent = $parent; $tpl->tpl_vars = array(); $tpl->config_vars = array(); } else { $tpl = new $this->template_class($template, clone $this, $parent, $cache_id, $compile_id); } } else { if (isset($this->template_objects[$_templateId])) { // return cached template object $tpl = $this->template_objects[$_templateId]; $tpl->parent = $parent; $tpl->tpl_vars = array(); $tpl->config_vars = array(); } else { $tpl = new $this->template_class($template, $this, $parent, $cache_id, $compile_id); } } // fill data if present if (!empty($data) && is_array($data)) { // set up variable values foreach ($data as $_key => $_val) { $tpl->tpl_vars[$_key] = new Smarty_variable($_val); } } return $tpl; }
/** * Get unique template id * * @param string $template_name * @param null|mixed $cache_id * @param null|mixed $compile_id * @param null $caching * @param \Smarty_Internal_Template $template * * @return string */ public function _getTemplateId($template_name, $cache_id = null, $compile_id = null, $caching = null, Smarty_Internal_Template $template = null) { $template_name = strpos($template_name, ':') === false ? "{$this->default_resource_type}:{$template_name}" : $template_name; $cache_id = $cache_id === null ? $this->cache_id : $cache_id; $compile_id = $compile_id === null ? $this->compile_id : $compile_id; $caching = (int) ($caching === null ? $this->caching : $caching); if (isset($template) && strpos($template_name, ':.') !== false || $this->allow_ambiguous_resources) { $_templateId = Smarty_Resource::getUniqueTemplateName(isset($template) ? $template : $this, $template_name) . "#{$cache_id}#{$compile_id}#{$caching}"; } else { $_templateId = $this->_joined_template_dir . "#{$template_name}#{$cache_id}#{$compile_id}#{$caching}"; } if (isset($_templateId[150])) { $_templateId = sha1($_templateId); } return $_templateId; }