/** * 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 ($source->smarty->getTemplateDir() as $key => $directory) { try { $s = Smarty_Template_Source::load(null, $source->smarty, 'file:[' . $key . ']' . $source->name); if (!$s->exists) { continue; } $sources[$s->uid] = $s; $uid .= $s->filepath; } 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); $source->exists = $exists; if ($_template && $_template->smarty->compile_check) { $source->timestamp = $s->getTimeStamp(); } }
/** * get a Compiled Object of this source * * @param Smarty_Internal_Template $_template template object * * @return Smarty_Template_Compiled compiled object */ static function load($_template) { if (!isset($_template->source)) { $_template->source = Smarty_Template_Source::load($_template); } $src = $_template->source; $_cache_key = null; // check runtime cache if ($crc = !$src->recompiled && $_template->smarty->resource_caching) { $_cache_key = $src->unique_resource . '#'; if ($_template->caching) { $_cache_key .= 'caching#'; } $_cache_key .= $_template->compile_id; if (isset($src->compileds[$_cache_key])) { return $src->compileds[$_cache_key]; } } $compiled = new Smarty_Template_Compiled($_cache_key); if (method_exists($src->handler, 'populateCompiledFilepath')) { $src->handler->populateCompiledFilepath($compiled, $_template); } else { $compiled->populateCompiledFilepath($_template); } // runtime cache if ($crc) { $src->compileds[$_cache_key] = $compiled; } return $compiled; }
/** * populate Source Object with meta data from Resource * * @param Smarty_Template_Source $source source object * @param Smarty_Internal_Template $_template template object * * @throws SmartyException */ 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) { /* @var \Smarty_Template_Source $_s */ $_s = Smarty_Template_Source::load(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) { $exists = $exists && $_s->exists; } } $source->components = $sources; $source->filepath = $_s->filepath; $source->uid = sha1($uid); $source->exists = $exists; if ($_template) { $source->timestamp = $_s->timestamp; } }
/** * Compile all template or config files * * @param \Smarty $smarty * @param string $extension template file name extension * @param bool $force_compile force all to recompile * @param int $time_limit set maximum execution time * @param int $max_errors set maximum allowed errors * @param bool $isConfig flag true if called for config files * * @return int number of template files compiled */ protected function compileAll(Smarty $smarty, $extension, $force_compile, $time_limit, $max_errors, $isConfig = false) { // switch off time limit if (function_exists('set_time_limit')) { @set_time_limit($time_limit); } $_count = 0; $_error_count = 0; $sourceDir = $isConfig ? $smarty->getConfigDir() : $smarty->getTemplateDir(); // loop over array of source directories foreach ($sourceDir as $_dir) { $_dir_1 = new RecursiveDirectoryIterator($_dir); $_dir_2 = new RecursiveIteratorIterator($_dir_1); foreach ($_dir_2 as $_fileinfo) { $_file = $_fileinfo->getFilename(); if (substr(basename($_fileinfo->getPathname()), 0, 1) == '.' || strpos($_file, '.svn') !== false) { continue; } if (!substr_compare($_file, $extension, -strlen($extension)) == 0) { continue; } if ($_fileinfo->getPath() !== substr($_dir, 0, -1)) { $_file = substr($_fileinfo->getPath(), strlen($_dir)) . DS . $_file; } echo "\n<br>", $_dir, '---', $_file; flush(); $_start_time = microtime(true); $_smarty = clone $smarty; $_smarty->force_compile = $force_compile; try { /* @var Smarty_Internal_Template $_tpl */ $_tpl = new $smarty->template_class($_file, $_smarty); $_tpl->caching = Smarty::CACHING_OFF; $_tpl->source = $isConfig ? Smarty_Template_Config::load($_tpl) : Smarty_Template_Source::load($_tpl); if ($_tpl->mustCompile()) { $_tpl->compileTemplateSource(); $_count++; echo ' compiled in ', microtime(true) - $_start_time, ' seconds'; flush(); } else { echo ' is up to date'; flush(); } } catch (Exception $e) { echo "\n<br> ------>Error: ", $e->getMessage(), "<br><br>\n"; $_error_count++; } // free memory unset($_tpl); $_smarty->_clearTemplateCache(); if ($max_errors !== null && $_error_count == $max_errors) { echo "\n<br><br>too many errors\n"; exit; } } } echo "\n<br>"; return $_count; }
/** * 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']); }
/** * Compiles code for the {extends} tag * * @param array $args array with attributes from parser * @param \Smarty_Internal_TemplateCompilerBase $compiler compiler object * * @return string compiled code * @throws \SmartyCompilerException * @throws \SmartyException */ public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler) { // check and get attributes $_attr = $this->getAttributes($compiler, $args); if ($_attr['nocache'] === true) { $compiler->trigger_template_error('nocache option not allowed', null, true); } if (strpos($_attr['file'], '$_tmp') !== false) { $compiler->trigger_template_error('illegal value for file attribute', null, true); } $name = $_attr['file']; if ($compiler->has_variable_string || !(substr_count($name, '"') == 2 || substr_count($name, "'") == 2) || substr_count($name, '(') != 0 || substr_count($name, '$_smarty_tpl->') != 0) { /** @var Smarty_Internal_Template $_smarty_tpl * used in evaluated code */ $_smarty_tpl = $compiler->template; eval("\$tpl_name = @{$name};"); } else { $tpl_name = trim($name, '\'"'); } // create source object $_source = Smarty_Template_Source::load(null, $compiler->smarty, $tpl_name); // check for recursion $uid = $_source->uid; if (isset($compiler->extends_uid[$uid])) { $compiler->trigger_template_error("illegal recursive call of \"{$_source->filepath}\"", $compiler->parser->lex->line - 1); } $compiler->extends_uid[$uid] = true; if (empty($_source->components)) { array_unshift($compiler->sources, $_source); } else { foreach ($_source->components as $source) { array_unshift($compiler->sources, $source); $uid = $source->uid; if (isset($compiler->extends_uid[$uid])) { $compiler->trigger_template_error("illegal recursive call of \"{$source->filepath}\"", $compiler->parser->lex->line - 1); } $compiler->extends_uid[$uid] = true; } } $compiler->inheritance_child = true; $compiler->parser->lex->yypushstate(Smarty_Internal_Templatelexer::CHILDBODY); return ''; }
/** * 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); } }
/** * Empty cache for a specific template * * @param Smarty $smarty Smarty object * @param string $resource_name template name * @param string $cache_id cache id * @param string $compile_id compile id * @param integer $exp_time expiration time (number of seconds, not timestamp) * * @return integer number of cache files deleted */ public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) { $cache_name = null; if (isset($resource_name)) { $source = Smarty_Template_Source::load(null, $smarty, $resource_name); if ($source->exists) { $cache_name = $source->name; } else { return 0; } // remove from template cache if (isset($smarty->_cache['template_objects'])) { foreach ($smarty->_cache['template_objects'] as $key => $_tpl) { if (isset($_tpl->cached) && $_tpl->source->uid == $source->uid) { unset($smarty->_cache['template_objects'][$key]); } } } } return $this->delete($cache_name, $cache_id, $compile_id, $exp_time); }
/** * Template code runtime function to set up an inline subtemplate * * @param \Smarty_Internal_Template $callerTpl * @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(Smarty_Internal_Template $callerTpl, $template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $parent_scope, $cache_tpl_obj, $uid = null) { $_templateId = isset($callerTpl->smarty->_cache['template_objects']) ? $callerTpl->smarty->_getTemplateId($template, $cache_id, $compile_id) : null; // already in template cache? /* @var Smarty_Internal_Template $tpl */ if (isset($callerTpl->smarty->_cache['template_objects'][$_templateId])) { // clone cached template object because of possible recursive call $tpl = clone $callerTpl->smarty->_cache['template_objects'][$_templateId]; $tpl->parent = $callerTpl; if ((bool) $tpl->caching !== (bool) $caching) { unset($tpl->compiled); } // get variables from calling scope if ($parent_scope == Smarty::SCOPE_LOCAL) { $tpl->tpl_vars = $callerTpl->tpl_vars; $tpl->config_vars = $callerTpl->config_vars; } $tpl->tpl_function = $callerTpl->tpl_function; //if (isset($callerTpl->_cache['inheritanceBlocks'])) { // $tpl->_cache['inheritanceBlocks'] = $callerTpl->_cache['inheritanceBlocks']; //} } else { $tpl = clone $callerTpl; $tpl->parent = $callerTpl; $tpl->isChild = false; 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)) { $tpl->compiled = $callerTpl->compiled; if (isset($tpl->compiled->includes["{$tpl->source->type}:{$tpl->source->name}"]) && $tpl->compiled->includes["{$tpl->source->type}:{$tpl->source->name}"] > 1) { $cache_tpl_obj = true; } if (isset($tpl->compiled->file_dependency[$uid])) { $info = $tpl->compiled->file_dependency[$uid]; $tpl->source = new Smarty_Template_Source(isset($tpl->smarty->_cache['resource_handlers'][$info[2]]) ? $tpl->smarty->_cache['resource_handlers'][$info[2]] : Smarty_Resource::load($tpl->smarty, $info[2]), $tpl->smarty, $info[0], $info[2], $info[0]); $tpl->source->filepath = $info[0]; $tpl->source->timestamp = $info[1]; $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 = $callerTpl->cached; } // get variables from calling scope if ($parent_scope != Smarty::SCOPE_LOCAL) { if ($parent_scope == Smarty::SCOPE_PARENT) { $tpl->tpl_vars =& $callerTpl->tpl_vars; $tpl->config_vars =& $callerTpl->config_vars; } elseif ($parent_scope == Smarty::SCOPE_GLOBAL) { $tpl->tpl_vars =& Smarty::$global_tpl_vars; $tpl->config_vars = $callerTpl->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 = $callerTpl->tpl_vars; $tpl->config_vars = $callerTpl->config_vars; } } if (!empty($data)) { // set up variable values foreach ($data as $_key => $_val) { $tpl->tpl_vars[$_key] = new Smarty_Variable($_val); } } return $tpl; }
/** * render template * * @param bool $merge_tpl_vars if true parent template variables merged in to local scope * @param bool $no_output_filter if true do not run output filter * @param bool $display true: display, false: fetch null: subtemplate * * @throws Exception * @throws SmartyException * @return string rendered template output */ public function render($no_output_filter = true, $display = null) { $parentIsTpl = isset($this->parent) && $this->parent->_objType == 2; if ($this->smarty->debugging) { $this->smarty->_debug->start_template($this, $display); } // checks if template exists if (!$this->source->exists) { if ($parentIsTpl) { $parent_resource = " in '{$this->parent->template_resource}'"; } else { $parent_resource = ''; } throw new SmartyException("Unable to load template {$this->source->type} '{$this->source->name}'{$parent_resource}"); } // check URL debugging control if (!$this->smarty->debugging && $this->smarty->debugging_ctrl == 'URL') { $this->smarty->_debug->debugUrl($this); } // disable caching for evaluated code if ($this->source->handler->recompiled) { $this->caching = false; } // read from cache or render $isCacheTpl = $this->caching == Smarty::CACHING_LIFETIME_CURRENT || $this->caching == Smarty::CACHING_LIFETIME_SAVED; if ($isCacheTpl) { if (!isset($this->cached)) { $this->loadCached(); } $this->cached->render($this, $no_output_filter); } elseif ($this->source->handler->uncompiled) { $this->source->render($this); } else { if (!isset($this->compiled)) { $this->loadCompiled(); } $this->compiled->render($this); } // display or fetch if ($display) { if ($this->caching && $this->smarty->cache_modified_check) { $this->smarty->ext->_cachemodify->cacheModifiedCheck($this->cached, $this, isset($content) ? $content : ob_get_clean()); } else { if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) && !$no_output_filter && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) { echo $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this); } else { ob_end_flush(); flush(); } } if ($this->smarty->debugging) { $this->smarty->_debug->end_template($this); // debug output $this->smarty->_debug->display_debug($this, true); } return ''; } else { if ($this->smarty->debugging) { $this->smarty->_debug->end_template($this); if ($this->smarty->debugging == 2 and !$display) { $this->smarty->_debug->display_debug($this, true); } } if ($parentIsTpl) { if (!empty($this->tpl_function)) { $this->parent->tpl_function = array_merge($this->parent->tpl_function, $this->tpl_function); } foreach ($this->compiled->required_plugins as $code => $tmp1) { foreach ($tmp1 as $name => $tmp) { foreach ($tmp as $type => $data) { $this->parent->compiled->required_plugins[$code][$name][$type] = $data; } } } } if (!$no_output_filter && (!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) && (isset($this->smarty->autoload_filters['output']) || isset($this->smarty->registered_filters['output']))) { return $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this); } // return cache content return null; } }
/** * 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 = array()) { if (!isset($parameter['isChild'])) { $parameter['isChild'] = false; } // check and get attributes $_attr = $this->getAttributes($compiler, $args); // get template name $include_file = $_attr['file']; 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; } } // 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 || $compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes || $_attr['inline'] === true) && !$compiler->template->source->recompiled; // variable template name ? if ($compiler->has_variable_string || !(substr_count($include_file, '"') == 2 || substr_count($include_file, "'") == 2) || substr_count($include_file, '(') != 0 || substr_count($include_file, '$_smarty_tpl->') != 0) { $merge_compiled_includes = false; if ($compiler->template->caching) { // must use individual cache file $_attr['caching'] = 1; } if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes && $_attr['inline'] !== true) { $compiler->trigger_template_error(' variable template file names not allow within {block} tags'); } } // 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 ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes && $_attr['inline'] !== true) { $compiler->trigger_template_error(' variable compile_id not allow within {block} tags'); } } } /* * 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) { if ($compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache) && $_caching != self::CACHING_NOCACHE_CODE) { // $merge_compiled_includes = false; if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) { $compiler->trigger_template_error(' invalid caching mode of subtemplate within {block} tags'); } } $c_id = isset($_attr['compile_id']) ? $_attr['compile_id'] : $compiler->template->compile_id; // we must observe different compile_id and caching $uid = sha1($c_id . ($_caching ? '--caching' : '--nocaching')); $tpl_name = null; /** @var Smarty_Internal_Template $_smarty_tpl * used in evaluated code */ $_smarty_tpl = $compiler->template; eval("\$tpl_name = {$include_file};"); if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid])) { $compiler->smarty->allow_ambiguous_resources = true; $tpl = new $compiler->smarty->template_class($tpl_name, $compiler->smarty, $compiler->template, $compiler->template->cache_id, $c_id, $_caching); if (!isset($tpl->source)) { $tpl->source = Smarty_Template_Source::load($tpl); } $tpl->loadCompiler(); // save unique function name $compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func'] = $renderName = 'render_' . str_replace(array('.', ','), '_', uniqid('', true)); if ($compiler->inheritance) { $tpl->compiler->inheritance = true; } $tpl->source->isChild = $parameter['isChild']; // make sure whole chain gets compiled $tpl->mustCompile = true; if (!$tpl->source->uncompiled && $tpl->source->exists) { $tpl->compiler->suppressTemplatePropertyHeader = true; $compiled_code = "\n/* Merged included template \"" . $tpl_name . "\" */\n"; // get compiled code $compiled_code .= "public function {$renderName} (\$_smarty_tpl) {\n"; //$compiled_code .= "\$_smarty_tpl->context->initTemplate(\$this, \$_smarty_tpl);\n"; $compiled_code .= $tpl->compiler->compileTemplate($tpl, null, $compiler->parent_compiler); $compiled_code .= "}\n"; unset($tpl->compiler); $compiler->parent_compiler->mergedSubTemplatesCode[$renderName] = $compiled_code; $has_compiled_template = true; unset($tpl); } } 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', $compiler->lex->taglineno); } } 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) { // if ($has_compiled_template && !$compiler->tag_nocache && !$compiler->nocache) { // never call inline templates in nocache mode //$compiler->suppressNocacheProcessing = true; //$_hash = $compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['nocache_hash']; $_output = ''; 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 && $_smarty_tpl->caching) { //$compiler->suppressNocacheProcessing = false; $_output .= substr($compiler->processNocacheCode($_vars_nc, true), 6, -3); //$compiler->suppressNocacheProcessing = true; } if (isset($_assign)) { $_output .= " \$_smarty_tpl->tpl_vars[{$_assign}] = new Smarty_Variable(\$this->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, \$_smarty_tpl, " . var_export($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid], true) . ", true));\n"; } else { $_output .= "\$this->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, \$_smarty_tpl, " . var_export($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid], true) . ");\n"; } if ($update_compile_id) { $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"); } return $_output; } if ($call_nocache) { $compiler->tag_nocache = true; } $_output = ""; 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 .= "\$_smarty_tpl->tpl_vars[{$_assign}] = new Smarty_Variable(\$this->getSubTemplate ({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, \$_smarty_tpl, " . var_export($parameter['isChild'], true) . ", true));\n"; } else { $_output .= "\$this->getSubTemplate ({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, \$_smarty_tpl, " . var_export($parameter['isChild'], true) . ");\n"; } if ($update_compile_id) { $_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"; } return $_output; }
/** * Check if a template resource exists * * @param string $resource_name template name * * @return boolean status */ public function templateExists($resource_name) { // create source object $source = Smarty_Template_Source::load(null, $this, $resource_name); return $source->exists; }
/** * 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) { //load source $tpl->source = null; unset($tpl->compiled); if (!isset($tpl->source)) { $tpl->source = Smarty_Template_Source::load($tpl); } }
/** * Get template's unique ID * * @param Smarty $smarty Smarty object * @param string $resource_name template name * * @return string filepath of cache file * @throws \SmartyException * */ protected function getTemplateUid(Smarty $smarty, $resource_name) { if (isset($resource_name)) { $source = Smarty_Template_Source::load(null, $smarty, $resource_name); if ($source->exists) { return $source->uid; } } return ''; }
/** * Load source object * * @throws SmartyException */ public function loadSource() { if (!isset($this->source)) { $this->source = Smarty_Template_Source::load($this); } }
/** * 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; } } }
/** * Template code runtime function to get subtemplate content * * @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 integer $caching cache mode * @param integer $cache_lifetime life time of cache data * @param $data * @param $_scope * @param \Smarty_Internal_Template $parent * @param bool $newBuffer * * @return string template content * @throws \Exception * */ public function getSubTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $_scope, Smarty_Internal_Template $parent, $isChild = false, $newBuffer = false) { $tpl = $parent->smarty->setupTemplate($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $_scope, $parent); if (!isset($tpl->source)) { $tpl->source = Smarty_Template_Source::load($tpl); } $tpl->source->isChild = $isChild; return $tpl->render(false, true, false, $newBuffer ? null : $parent->context); }
/** * initialize Source Object for given resource * wrapper for backward compatibility to versions < 3.1.22 * 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_Source Source Object */ public static function source(Smarty_Internal_Template $_template = null, Smarty $smarty = null, $template_resource = null) { return Smarty_Template_Source::load($_template, $smarty, $template_resource); }
/** * Empty cache for a specific template * * @param Smarty $smarty Smarty object * @param string $resource_name template name * @param string $cache_id cache id * @param string $compile_id compile id * @param integer $exp_time expiration time (number of seconds, not timestamp) * * @return integer number of cache files deleted */ public function clear(Smarty $smarty, $resource_name, $cache_id, $compile_id, $exp_time) { $cache_name = null; if (isset($resource_name)) { $source = Smarty_Template_Source::load(null, $smarty, $resource_name); if ($source->exists) { $cache_name = $source->name; } else { return 0; } } return $this->delete($cache_name, $cache_id, $compile_id, $exp_time); }
/** * Load source resource * * @throws SmartyException */ public function loadSource() { $this->source = Smarty_Template_Source::load($this); if ($this->smarty->template_resource_caching && !$this->source->recompiled && isset($this->templateId)) { $this->smarty->template_objects[$this->templateId] = $this; } }
/** * @param Smarty_Internal_Template $_template * * @return Smarty_Template_Cached */ static function load(Smarty_Internal_Template $_template) { if (!isset($_template->source)) { $_template->source = Smarty_Template_Source::load($_template); } $_template->cached = $cached = new Smarty_Template_Cached($_template); // // check if cache is valid // if (!($_template->caching == Smarty::CACHING_LIFETIME_CURRENT || $_template->caching == Smarty::CACHING_LIFETIME_SAVED) || $_template->source->recompiled) { $cached->handler->populate($cached, $_template); return $cached; } while (true) { while (true) { $cached->handler->populate($cached, $_template); if ($cached->timestamp === false || $_template->smarty->force_compile || $_template->smarty->force_cache) { $cached->valid = false; } else { $cached->valid = true; } if ($cached->valid && $_template->caching == Smarty::CACHING_LIFETIME_CURRENT && $_template->cache_lifetime >= 0 && time() > $cached->timestamp + $_template->cache_lifetime) { // lifetime expired $cached->valid = false; } if ($cached->valid || !$_template->smarty->cache_locking) { break; } if (!$cached->handler->locked($_template->smarty, $cached)) { $cached->handler->acquireLock($_template->smarty, $cached); break 2; } } if ($cached->valid) { if (!$_template->smarty->cache_locking || $cached->handler->locked($_template->smarty, $cached) === null) { // load cache file for the following checks if ($_template->smarty->debugging) { Smarty_Internal_Debug::start_cache($_template); } $cached->process($_template); if ($_template->smarty->debugging) { Smarty_Internal_Debug::end_cache($_template); } } else { continue; } } else { return $cached; } if ($cached->valid && $_template->caching === Smarty::CACHING_LIFETIME_SAVED && $_template->properties['cache_lifetime'] >= 0 && time() > $_template->cached->timestamp + $_template->properties['cache_lifetime']) { $cached->valid = false; } if (!$cached->valid && $_template->smarty->cache_locking) { $cached->handler->acquireLock($_template->smarty, $cached); return $cached; } else { return $cached; } } }