/app/smarty/sysplugins/smarty_internal_template.php

https://github.com/pws5068/RSNCorp · PHP · 813 lines · 547 code · 31 blank · 235 comment · 173 complexity · 9eb611dd7f0f3b0870e7c4dfde87b664 MD5 · raw file

  1. <?php
  2. /**
  3. * Smarty Internal Plugin Template
  4. *
  5. * This file contains the Smarty template engine
  6. *
  7. * @package Smarty
  8. * @subpackage Templates
  9. * @author Uwe Tews
  10. */
  11. /**
  12. * Main class with template data structures and methods
  13. */
  14. class Smarty_Internal_Template extends Smarty_Internal_Data {
  15. // object cache
  16. public $compiler_object = null;
  17. public $cacher_object = null;
  18. // Smarty parameter
  19. public $cache_id = null;
  20. public $compile_id = null;
  21. public $caching = null;
  22. public $cache_lifetime = null;
  23. public $cacher_class = null;
  24. public $caching_type = null;
  25. public $force_compile = null;
  26. public $forceNocache = false;
  27. // Template resource
  28. public $template_resource = null;
  29. public $resource_type = null;
  30. public $resource_name = null;
  31. public $resource_object = null;
  32. private $isExisting = null;
  33. public $templateUid = '';
  34. // Template source
  35. public $template_filepath = null;
  36. public $template_source = null;
  37. private $template_timestamp = null;
  38. // Compiled template
  39. private $compiled_filepath = null;
  40. public $compiled_template = null;
  41. private $compiled_timestamp = null;
  42. public $mustCompile = null;
  43. public $suppressHeader = false;
  44. public $suppressFileDependency = false;
  45. public $extract_code = false;
  46. public $extracted_compiled_code = '';
  47. public $has_nocache_code = false;
  48. // Rendered content
  49. public $rendered_content = null;
  50. // Cache file
  51. private $cached_filepath = null;
  52. public $cached_timestamp = null;
  53. private $isCached = null;
  54. private $cache_resource_object = null;
  55. private $cacheFileChecked = false;
  56. // template variables
  57. public $tpl_vars = array();
  58. public $parent = null;
  59. public $config_vars = array();
  60. // storage for plugin
  61. public $plugin_data = array();
  62. // special properties
  63. public $properties = array ('file_dependency' => array(),
  64. 'nocache_hash' => '',
  65. 'function' => array());
  66. // storage for block data
  67. public $block_data = array();
  68. // required plugins
  69. public $required_plugins = array('compiled' => array(), 'nocache' => array());
  70. /**
  71. * Create template data object
  72. *
  73. * Some of the global Smarty settings copied to template scope
  74. * It load the required template resources and cacher plugins
  75. *
  76. * @param string $template_resource template resource string
  77. * @param object $_parent back pointer to parent object with variables or null
  78. * @param mixed $_cache_id cache id or null
  79. * @param mixed $_compile_id compile id or null
  80. */
  81. public function __construct($template_resource, $smarty, $_parent = null, $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null)
  82. {
  83. $this->smarty = &$smarty;
  84. // Smarty parameter
  85. $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
  86. $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
  87. $this->force_compile = $this->smarty->force_compile;
  88. $this->caching = $_caching === null ? $this->smarty->caching : $_caching;
  89. if ($this->caching === true) $this->caching = SMARTY_CACHING_LIFETIME_CURRENT;
  90. $this->cache_lifetime = $_cache_lifetime === null ?$this->smarty->cache_lifetime : $_cache_lifetime;
  91. $this->force_cache = $this->smarty->force_cache;
  92. $this->security = $this->smarty->security;
  93. $this->parent = $_parent;
  94. // dummy local smarty variable
  95. $this->tpl_vars['smarty'] = new Smarty_Variable;
  96. // Template resource
  97. $this->template_resource = $template_resource;
  98. // parse resource name
  99. if (!$this->parseResourceName ($template_resource, $this->resource_type, $this->resource_name, $this->resource_object)) {
  100. throw new Exception ("Unable to parse resource name \"{$template_resource}\"");
  101. }
  102. // load cache resource
  103. if (!$this->resource_object->isEvaluated && ($this->caching == SMARTY_CACHING_LIFETIME_CURRENT || $this->caching == SMARTY_CACHING_LIFETIME_SAVED)) {
  104. $this->cache_resource_object = $this->smarty->cache->loadResource();
  105. }
  106. }
  107. /**
  108. * Returns the template filepath
  109. *
  110. * The template filepath is determined by the actual resource handler
  111. *
  112. * @return string the template filepath
  113. */
  114. public function getTemplateFilepath ()
  115. {
  116. return $this->template_filepath === null ?
  117. $this->template_filepath = $this->resource_object->getTemplateFilepath($this) :
  118. $this->template_filepath;
  119. }
  120. /**
  121. * Returns the timpestamp of the template source
  122. *
  123. * The template timestamp is determined by the actual resource handler
  124. *
  125. * @return integer the template timestamp
  126. */
  127. public function getTemplateTimestamp ()
  128. {
  129. return $this->template_timestamp === null ?
  130. $this->template_timestamp = $this->resource_object->getTemplateTimestamp($this) :
  131. $this->template_timestamp;
  132. }
  133. /**
  134. * Returns the template source code
  135. *
  136. * The template source is being read by the actual resource handler
  137. *
  138. * @return string the template source
  139. */
  140. public function getTemplateSource ()
  141. {
  142. if ($this->template_source === null) {
  143. if (!$this->resource_object->getTemplateSource($this)) {
  144. throw new Exception("Unable to read template {$this->resource_type} '{$this->resource_name}'");
  145. }
  146. }
  147. return $this->template_source;
  148. }
  149. /**
  150. * Returns if the template is existing
  151. *
  152. * The status is determined by the actual resource handler
  153. *
  154. * @return boolean true if the template exists
  155. */
  156. public function isExisting ($error = false)
  157. {
  158. if ($this->isExisting === null) {
  159. $this->isExisting = $this->resource_object->isExisting($this);
  160. }
  161. if (!$this->isExisting && $error) {
  162. throw new Exception("Unable to load template {$this->resource_type} '{$this->resource_name}'");
  163. }
  164. return $this->isExisting;
  165. }
  166. /**
  167. * Returns if the current template must be compiled by the Smarty compiler
  168. *
  169. * It does compare the timestamps of template source and the compiled templates and checks the force compile configuration
  170. *
  171. * @return boolean true if the template must be compiled
  172. */
  173. public function mustCompile ()
  174. {
  175. $this->isExisting(true);
  176. if ($this->mustCompile === null) {
  177. $this->mustCompile = ($this->resource_object->usesCompiler && ($this->force_compile || $this->resource_object->isEvaluated || $this->getCompiledTimestamp () === false ||
  178. // ($this->smarty->compile_check && $this->getCompiledTimestamp () !== $this->getTemplateTimestamp ())));
  179. ($this->smarty->compile_check && $this->getCompiledTimestamp () < $this->getTemplateTimestamp ())));
  180. }
  181. return $this->mustCompile;
  182. }
  183. /**
  184. * Returns the compiled template filepath
  185. *
  186. * @return string the template filepath
  187. */
  188. public function getCompiledFilepath ()
  189. {
  190. return $this->compiled_filepath === null ?
  191. ($this->compiled_filepath = !$this->resource_object->isEvaluated ? $this->resource_object->getCompiledFilepath($this) : false) :
  192. $this->compiled_filepath;
  193. }
  194. /**
  195. * Returns the timpestamp of the compiled template
  196. *
  197. * @return integer the template timestamp
  198. */
  199. public function getCompiledTimestamp ()
  200. {
  201. return $this->compiled_timestamp === null ?
  202. ($this->compiled_timestamp = (!$this->resource_object->isEvaluated && file_exists($this->getCompiledFilepath())) ? filemtime($this->getCompiledFilepath()) : false) :
  203. $this->compiled_timestamp;
  204. }
  205. /**
  206. * Returns the compiled template
  207. *
  208. * It checks if the template must be compiled or just read from the template resource
  209. *
  210. * @return string the compiled template
  211. */
  212. public function getCompiledTemplate ()
  213. {
  214. if ($this->compiled_template === null) {
  215. // see if template needs compiling.
  216. if ($this->mustCompile()) {
  217. $this->compileTemplateSource();
  218. } else {
  219. if ($this->compiled_template === null) {
  220. $this->compiled_template = !$this->resource_object->isEvaluated && $this->resource_object->usesCompiler ? file_get_contents($this->getCompiledFilepath()) : false;
  221. }
  222. }
  223. }
  224. return $this->compiled_template;
  225. }
  226. /**
  227. * Compiles the template
  228. *
  229. * If the template is not evaluated the compiled template is saved on disk
  230. */
  231. public function compileTemplateSource ()
  232. {
  233. if (!$this->resource_object->isEvaluated) {
  234. $this->properties['file_dependency'] = array();
  235. $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp());
  236. }
  237. if ($this->smarty->debugging) {
  238. Smarty_Internal_Debug::start_compile($this);
  239. }
  240. // compile template
  241. if (!is_object($this->compiler_object)) {
  242. // load compiler
  243. $this->smarty->loadPlugin($this->resource_object->compiler_class);
  244. $this->compiler_object = new $this->resource_object->compiler_class($this->resource_object->template_lexer_class, $this->resource_object->template_parser_class, $this->smarty);
  245. }
  246. // call compiler
  247. if ($this->compiler_object->compileTemplate($this)) {
  248. // compiling succeded
  249. if (!$this->resource_object->isEvaluated) {
  250. // write compiled template
  251. Smarty_Internal_Write_File::writeFile($this->getCompiledFilepath(), $this->compiled_template, $this->smarty);
  252. }
  253. } else {
  254. // error compiling template
  255. throw new Exception("Error compiling template {$this->getTemplateFilepath ()}");
  256. return false;
  257. }
  258. if ($this->smarty->debugging) {
  259. Smarty_Internal_Debug::end_compile($this);
  260. }
  261. }
  262. /**
  263. * Returns the filepath of the cached template output
  264. *
  265. * The filepath is determined by the actual cache resource
  266. *
  267. * @return string the cache filepath
  268. */
  269. public function getCachedFilepath ()
  270. {
  271. return $this->cached_filepath === null ?
  272. $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) :
  273. $this->cached_filepath;
  274. }
  275. /**
  276. * Returns the timpestamp of the cached template output
  277. *
  278. * The timestamp is determined by the actual cache resource
  279. *
  280. * @return integer the template timestamp
  281. */
  282. public function getCachedTimestamp ()
  283. {
  284. return $this->cached_timestamp === null ?
  285. $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) :
  286. $this->cached_timestamp;
  287. }
  288. /**
  289. * Returns the cached template output
  290. *
  291. * @return string |booelan the template content or false if the file does not exist
  292. */
  293. public function getCachedContent ()
  294. {
  295. return $this->rendered_content === null ?
  296. $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) :
  297. $this->rendered_content;
  298. }
  299. /**
  300. * Writes the cached template output
  301. */
  302. public function writeCachedContent ($content)
  303. {
  304. if ($this->resource_object->isEvaluated || !($this->caching == SMARTY_CACHING_LIFETIME_CURRENT || $this->caching == SMARTY_CACHING_LIFETIME_SAVED)) {
  305. // don't write cache file
  306. return false;
  307. }
  308. $this->properties['cache_lifetime'] = $this->cache_lifetime;
  309. return $this->cache_resource_object->writeCachedContent($this, $this->createPropertyHeader(true) . $content);
  310. }
  311. /**
  312. * Checks of a valid version redered HTML output is in the cache
  313. *
  314. * If the cache is valid the contents is stored in the template object
  315. *
  316. * @return boolean true if cache is valid
  317. */
  318. public function isCached ()
  319. {
  320. if ($this->isCached === null) {
  321. $this->isCached = false;
  322. if (($this->caching == SMARTY_CACHING_LIFETIME_CURRENT || $this->caching == SMARTY_CACHING_LIFETIME_SAVED) && !$this->resource_object->isEvaluated) {
  323. if (!isset($this->cache_resource_object)) {
  324. $this->cache_resource_object = $this->smarty->loadCacheResource();
  325. }
  326. $cachedTimestamp = $this->getCachedTimestamp();
  327. if ($cachedTimestamp === false || $this->force_compile || $this->force_cache) {
  328. return $this->isCached;
  329. }
  330. if ($this->caching === SMARTY_CACHING_LIFETIME_SAVED || ($this->caching == SMARTY_CACHING_LIFETIME_CURRENT && (time() <= ($cachedTimestamp + $this->cache_lifetime) || $this->cache_lifetime < 0))) {
  331. if ($this->smarty->debugging) {
  332. Smarty_Internal_Debug::start_cache($this);
  333. }
  334. $this->rendered_content = $this->cache_resource_object->getCachedContents($this);
  335. if ($this->smarty->debugging) {
  336. Smarty_Internal_Debug::end_cache($this);
  337. }
  338. if ($this->cacheFileChecked) {
  339. $this->isCached = true;
  340. return $this->isCached;
  341. }
  342. $this->cacheFileChecked = true;
  343. if ($this->caching === SMARTY_CACHING_LIFETIME_SAVED && $this->properties['cache_lifetime'] > 0 && (time() > ($this->getCachedTimestamp() + $this->properties['cache_lifetime']))) {
  344. $this->rendered_content = null;
  345. return $this->isCached;
  346. }
  347. if (!empty($this->properties['file_dependency']) && $this->smarty->compile_check) {
  348. foreach ($this->properties['file_dependency'] as $_file_to_check) {
  349. $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name);
  350. If ($resource_type == 'file') {
  351. $mtime = filemtime($_file_to_check[0]);
  352. } else {
  353. $resource_handler = $this->loadTemplateResourceHandler($resource_type);
  354. $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name);
  355. }
  356. // If ($mtime > $this->getCachedTimestamp()) {
  357. If ($mtime > $_file_to_check[1]) {
  358. $this->rendered_content = null;
  359. return $this->isCached;
  360. }
  361. }
  362. }
  363. $this->isCached = true;
  364. }
  365. }
  366. }
  367. return $this->isCached;
  368. }
  369. /**
  370. * Render the output using the compiled template or the PHP template source
  371. *
  372. * The rendering process is accomplished by just including the PHP files.
  373. * The only exceptions are evaluated templates (string template). Their code has
  374. * to be evaluated
  375. */
  376. public function renderTemplate ()
  377. {
  378. if ($this->resource_object->usesCompiler) {
  379. if ($this->mustCompile() && $this->compiled_template === null) {
  380. $this->compileTemplateSource();
  381. }
  382. if ($this->smarty->debugging) {
  383. Smarty_Internal_Debug::start_render($this);
  384. }
  385. $_smarty_tpl = $this;
  386. ob_start();
  387. if ($this->resource_object->isEvaluated) {
  388. eval("?>" . $this->compiled_template);
  389. } else {
  390. include($this->getCompiledFilepath ());
  391. // check file dependencies at compiled code
  392. if ($this->smarty->compile_check) {
  393. if (!empty($this->properties['file_dependency'])) {
  394. $this->mustCompile = false;
  395. foreach ($this->properties['file_dependency'] as $_file_to_check) {
  396. $this->getResourceTypeName($_file_to_check[0], $resource_type, $resource_name);
  397. If ($resource_type == 'file') {
  398. $mtime = filemtime($_file_to_check[0]);
  399. } else {
  400. $resource_handler = $this->loadTemplateResourceHandler($resource_type);
  401. $mtime = $resource_handler->getTemplateTimestampTypeName($resource_type, $resource_name);
  402. }
  403. // If ($mtime != $_file_to_check[1]) {
  404. If ($mtime > $_file_to_check[1]) {
  405. $this->mustCompile = true;
  406. break;
  407. }
  408. }
  409. if ($this->mustCompile) {
  410. // recompile and render again
  411. ob_get_clean();
  412. $this->compileTemplateSource();
  413. ob_start();
  414. include($this->getCompiledFilepath ());
  415. }
  416. }
  417. }
  418. }
  419. } else {
  420. if (is_callable(array($this->resource_object, 'renderUncompiled'))) {
  421. if ($this->smarty->debugging) {
  422. Smarty_Internal_Debug::start_render($this);
  423. }
  424. ob_start();
  425. $this->resource_object->renderUncompiled($this);
  426. } else {
  427. throw new Exception("Resource '$this->resource_type' must have 'renderUncompiled' methode");
  428. }
  429. }
  430. $this->rendered_content = ob_get_clean();
  431. if (!$this->resource_object->isEvaluated && empty($this->properties['file_dependency'][$this->templateUid])) {
  432. $this->properties['file_dependency'][$this->templateUid] = array($this->getTemplateFilepath(), $this->getTemplateTimestamp());
  433. }
  434. if ($this->parent instanceof Smarty_Template or $this->parent instanceof Smarty_Internal_Template) {
  435. $this->parent->properties['file_dependency'] = array_merge($this->parent->properties['file_dependency'], $this->properties['file_dependency']);
  436. foreach($this->required_plugins as $code => $tmp1) {
  437. foreach($tmp1 as $name => $tmp) {
  438. foreach($tmp as $type => $data) {
  439. $this->parent->required_plugins[$code][$name][$type] = $data;
  440. }
  441. }
  442. }
  443. }
  444. if ($this->smarty->debugging) {
  445. Smarty_Internal_Debug::end_render($this);
  446. }
  447. // write to cache when nessecary
  448. if (!$this->resource_object->isEvaluated && ($this->caching == SMARTY_CACHING_LIFETIME_SAVED || $this->caching == SMARTY_CACHING_LIFETIME_CURRENT)) {
  449. if ($this->smarty->debugging) {
  450. Smarty_Internal_Debug::start_cache($this);
  451. }
  452. $this->properties['has_nocache_code'] = false;
  453. // get text between non-cached items
  454. $cache_split = preg_split("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content);
  455. // get non-cached items
  456. preg_match_all("!/\*%%SmartyNocache:{$this->properties['nocache_hash']}%%\*\/(.+?)/\*/%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!s", $this->rendered_content, $cache_parts);
  457. $output = '';
  458. // loop over items, stitch back together
  459. foreach($cache_split as $curr_idx => $curr_split) {
  460. // escape PHP tags in template content
  461. $output .= preg_replace('/(<%|%>|<\?php|<\?|\?>)/', '<?php echo \'$1\'; ?>', $curr_split);
  462. if (isset($cache_parts[0][$curr_idx])) {
  463. $this->properties['has_nocache_code'] = true;
  464. // remove nocache tags from cache output
  465. $output .= preg_replace("!/\*/?%%SmartyNocache:{$this->properties['nocache_hash']}%%\*/!", '', $cache_parts[0][$curr_idx]);
  466. }
  467. }
  468. // rendering (must be done before writing cache file because of {function} nocache handling)
  469. $_smarty_tpl = $this;
  470. ob_start();
  471. eval("?>" . $output);
  472. $this->rendered_content = ob_get_clean();
  473. // write cache file content
  474. $this->writeCachedContent($output);
  475. if ($this->smarty->debugging) {
  476. Smarty_Internal_Debug::end_cache($this);
  477. }
  478. } else {
  479. // var_dump('renderTemplate', $this->has_nocache_code, $this->template_resource, $this->properties['nocache_hash'], $this->parent->properties['nocache_hash'], $this->rendered_content);
  480. if ($this->has_nocache_code && !empty($this->properties['nocache_hash']) && !empty($this->parent->properties['nocache_hash'])) {
  481. // replace nocache_hash
  482. $this->rendered_content = preg_replace("/{$this->properties['nocache_hash']}/", $this->parent->properties['nocache_hash'], $this->rendered_content);
  483. $this->parent->has_nocache_code = $this->has_nocache_code;
  484. }
  485. }
  486. }
  487. /**
  488. * Returns the rendered HTML output
  489. *
  490. * If the cache is valid the cached content is used, otherwise
  491. * the output is rendered from the compiled template or PHP template source
  492. *
  493. * @return string rendered HTML output
  494. */
  495. public function getRenderedTemplate ()
  496. {
  497. // disable caching for evaluated code
  498. if ($this->resource_object->isEvaluated) {
  499. $this->caching = false;
  500. }
  501. // checks if template exists
  502. $this->isExisting(true);
  503. // read from cache or render
  504. if ($this->rendered_content === null && !$this->isCached()) {
  505. // render template (not loaded and not in cache)
  506. $this->renderTemplate();
  507. }
  508. $this->updateParentVariables();
  509. $this->isCached = null;
  510. return $this->rendered_content;
  511. }
  512. /**
  513. * Parse a template resource in its name and type
  514. * Load required resource handler
  515. *
  516. * @param string $template_resource template resource specification
  517. * @param string $resource_type return resource type
  518. * @param string $resource_name return resource name
  519. * @param object $resource_handler return resource handler object
  520. */
  521. public function parseResourceName($template_resource, &$resource_type, &$resource_name, &$resource_handler)
  522. {
  523. if (empty($template_resource))
  524. return false;
  525. $this->getResourceTypeName($template_resource, $resource_type, $resource_name);
  526. $resource_handler = $this->loadTemplateResourceHandler($resource_type);
  527. // cache template object under a unique ID
  528. // do not cache string resources
  529. // ***** if ($resource_type != 'string' && $this->smarty->caching) {
  530. if ($resource_type != 'string') {
  531. $this->smarty->template_objects[crc32($this->template_resource . $this->cache_id . $this->compile_id)] = $this;
  532. }
  533. return true;
  534. }
  535. /**
  536. * get system filepath to template
  537. */
  538. public function buildTemplateFilepath ($file = null)
  539. {
  540. if ($file == null) {
  541. $file = $this->resource_name;
  542. }
  543. foreach((array)$this->smarty->template_dir as $_template_dir) {
  544. if (strpos('/\\', substr($_template_dir, -1)) === false) {
  545. $_template_dir .= DS;
  546. }
  547. $_filepath = $_template_dir . $file;
  548. if (file_exists($_filepath))
  549. return $_filepath;
  550. }
  551. if (file_exists($file)) return $file;
  552. // no tpl file found
  553. if (!empty($this->smarty->default_template_handler_func)) {
  554. if (!is_callable($this->smarty->default_template_handler_func)) {
  555. throw new Exception("Default template handler not callable");
  556. } else {
  557. $_return = call_user_func_array($this->smarty->default_template_handler_func,
  558. array($this->resource_type, $this->resource_name, &$this->template_source, &$this->template_timestamp, $this));
  559. if (is_string($_return)) {
  560. return $_return;
  561. } elseif ($_return === true) {
  562. return $file;
  563. }
  564. }
  565. }
  566. // throw new Exception("Unable to load template \"{$file}\"");
  567. return false;
  568. }
  569. /**
  570. * Update Smarty variables in other scopes
  571. */
  572. public function updateParentVariables ($scope = SMARTY_LOCAL_SCOPE)
  573. {
  574. $has_root = false;
  575. foreach ($this->tpl_vars as $_key => $_variable) {
  576. $_variable_scope = $this->tpl_vars[$_key]->scope;
  577. if ($scope == SMARTY_LOCAL_SCOPE && $_variable_scope == SMARTY_LOCAL_SCOPE) {
  578. continue;
  579. }
  580. if (isset($this->parent) && ($scope == SMARTY_PARENT_SCOPE || $_variable_scope == SMARTY_PARENT_SCOPE)) {
  581. if (isset($this->parent->tpl_vars[$_key])) {
  582. // variable is already defined in parent, copy value
  583. $this->parent->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value;
  584. } else {
  585. // create variable in parent
  586. $this->parent->tpl_vars[$_key] = clone $_variable;
  587. $this->parent->tpl_vars[$_key]->scope = SMARTY_LOCAL_SCOPE;
  588. }
  589. }
  590. if ($scope == SMARTY_ROOT_SCOPE || $_variable_scope == SMARTY_ROOT_SCOPE) {
  591. if ($this->parent == null) {
  592. continue;
  593. }
  594. if (!$has_root) {
  595. // find root
  596. $root_ptr = $this;
  597. while ($root_ptr->parent != null) {
  598. $root_ptr = $root_ptr->parent;
  599. $has_root = true;
  600. }
  601. }
  602. if (isset($root_ptr->tpl_vars[$_key])) {
  603. // variable is already defined in root, copy value
  604. $root_ptr->tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value;
  605. } else {
  606. // create variable in root
  607. $root_ptr->tpl_vars[$_key] = clone $_variable;
  608. $root_ptr->tpl_vars[$_key]->scope = SMARTY_LOCAL_SCOPE;
  609. }
  610. }
  611. if ($scope == SMARTY_GLOBAL_SCOPE || $_variable_scope == SMARTY_GLOBAL_SCOPE) {
  612. if (isset($this->smarty->global_tpl_vars[$_key])) {
  613. // variable is already defined in root, copy value
  614. $this->smarty->global_tpl_vars[$_key]->value = $this->tpl_vars[$_key]->value;
  615. } else {
  616. // create variable in root
  617. $this->smarty->global_tpl_vars[$_key] = clone $_variable;
  618. }
  619. $this->smarty->global_tpl_vars[$_key]->scope = SMARTY_LOCAL_SCOPE;
  620. }
  621. }
  622. }
  623. /**
  624. * Split a template resource in its name and type
  625. *
  626. * @param string $template_resource template resource specification
  627. * @param string $resource_type return resource type
  628. * @param string $resource_name return resource name
  629. */
  630. protected function getResourceTypeName ($template_resource, &$resource_type, &$resource_name)
  631. {
  632. if (strpos($template_resource, ':') === false) {
  633. // no resource given, use default
  634. $resource_type = $this->smarty->default_resource_type;
  635. $resource_name = $template_resource;
  636. } else {
  637. // get type and name from path
  638. list($resource_type, $resource_name) = explode(':', $template_resource, 2);
  639. if (strlen($resource_type) == 1) {
  640. // 1 char is not resource type, but part of filepath
  641. $resource_type = 'file';
  642. $resource_name = $template_resource;
  643. } else {
  644. $resource_type = $resource_type;
  645. }
  646. }
  647. }
  648. /**
  649. * Load template resource handler by type
  650. *
  651. * @param string $resource_type template resource type
  652. * @return object resource handler object
  653. */
  654. protected function loadTemplateResourceHandler ($resource_type)
  655. {
  656. // try registered resource
  657. if (isset($this->smarty->_plugins['resource'][$resource_type])) {
  658. return new Smarty_Internal_Resource_Registered($this->smarty);
  659. } else {
  660. // try sysplugins dir
  661. if (in_array($resource_type, array('file', 'string', 'extends', 'php', 'registered', 'stream'))) {
  662. $_resource_class = 'Smarty_Internal_Resource_' . $resource_type;
  663. return new $_resource_class($this->smarty);
  664. } else {
  665. // try plugins dir
  666. $_resource_class = 'Smarty_Resource_' . $resource_type;
  667. if ($this->smarty->loadPlugin($_resource_class)) {
  668. if (class_exists($_resource_class, false)) {
  669. return new $_resource_class($this->smarty);
  670. } else {
  671. $this->smarty->register_resource($resource_type,
  672. array("smarty_resource_{$resource_type}_source",
  673. "smarty_resource_{$resource_type}_timestamp",
  674. "smarty_resource_{$resource_type}_secure",
  675. "smarty_resource_{$resource_type}_trusted"));
  676. return new Smarty_Internal_Resource_Registered($this->smarty);
  677. }
  678. } else {
  679. // try streams
  680. $_known_stream = stream_get_wrappers();
  681. if (in_array($resource_type, $_known_stream)) {
  682. // is known stream
  683. if ($this->smarty->security) {
  684. $this->smarty->security_handler->isTrustedStream($resource_type);
  685. }
  686. return new Smarty_Internal_Resource_Stream($this->smarty);
  687. } else {
  688. throw new Exception('Unkown resource type \'' . $resource_type . '\'');
  689. }
  690. }
  691. }
  692. }
  693. }
  694. /**
  695. * Create property header
  696. */
  697. public function createPropertyHeader ($cache = false)
  698. {
  699. $plugins_string = '';
  700. // include code for plugins
  701. if (!$cache) {
  702. if (!empty($this->required_plugins['compiled'])) {
  703. $plugins_string = '<?php ';
  704. foreach($this->required_plugins['compiled'] as $tmp) {
  705. foreach($tmp as $data) {
  706. $plugins_string .= "if (!is_callable('{$data['function']}')) include '{$data['file']}';\n";
  707. }
  708. }
  709. $plugins_string .= '?>';
  710. }
  711. if (!empty($this->required_plugins['nocache'])) {
  712. $this->has_nocache_code = true;
  713. $plugins_string .= "<?php echo '/*%%SmartyNocache:{$this->properties['nocache_hash']}%%*/<?php ";
  714. foreach($this->required_plugins['nocache'] as $tmp) {
  715. foreach($tmp as $data) {
  716. $plugins_string .= "if (!is_callable(\'{$data['function']}\')) include \'{$data['file']}\';\n";
  717. }
  718. }
  719. $plugins_string .= "?>/*/%%SmartyNocache:{$this->properties['nocache_hash']}%%*/';?>\n";
  720. }
  721. }
  722. // build property code
  723. $this->properties['has_nocache_code'] = $this->has_nocache_code;
  724. $properties_string = "<?php /*%%SmartyHeaderCode:{$this->properties['nocache_hash']}%%*/" ;
  725. if ($this->smarty->direct_access_security) {
  726. $properties_string .= "if(!defined('SMARTY_DIR')) exit('no direct access allowed');\n";
  727. }
  728. if ($cache) {
  729. // remove compiled code of{function} definition
  730. unset($this->properties['function']);
  731. if (!empty($this->smarty->template_functions)) {
  732. // copy code of {function} tags called in nocache mode
  733. foreach ($this->smarty->template_functions as $name => $function_data) {
  734. if (isset($function_data['called_nocache'])) {
  735. unset($function_data['called_nocache'], $this->smarty->template_functions[$name]['called_nocache']);
  736. $this->properties['function'][$name] = $function_data;
  737. }
  738. }
  739. }
  740. }
  741. $properties_string .= "\$_smarty_tpl->decodeProperties(" . var_export($this->properties, true) . "); /*/%%SmartyHeaderCode%%*/?>\n";
  742. return $properties_string . $plugins_string;
  743. }
  744. /**
  745. * Decode saved properties from compiled template and cache files
  746. */
  747. public function decodeProperties ($properties)
  748. {
  749. $this->has_nocache_code = $properties['has_nocache_code'];
  750. $this->properties['nocache_hash'] = $properties['nocache_hash'];
  751. if (isset($properties['cache_lifetime'])) {
  752. $this->properties['cache_lifetime'] = $properties['cache_lifetime'];
  753. }
  754. if (isset($properties['file_dependency'])) {
  755. $this->properties['file_dependency'] = array_merge($this->properties['file_dependency'], $properties['file_dependency']);
  756. }
  757. if (!empty($properties['function'])) {
  758. $this->properties['function'] = array_merge($this->properties['function'], $properties['function']);
  759. $this->smarty->template_functions = array_merge($this->smarty->template_functions, $properties['function']);
  760. }
  761. }
  762. /**
  763. * wrapper for display
  764. */
  765. public function display ()
  766. {
  767. return $this->smarty->display($this);
  768. }
  769. /**
  770. * wrapper for fetch
  771. */
  772. public function fetch ()
  773. {
  774. return $this->smarty->fetch($this);
  775. }
  776. }
  777. /**
  778. * wrapper for template class
  779. */
  780. class Smarty_Template extends Smarty_Internal_Template {
  781. }
  782. ?>