/mzz/libs/smarty/sysplugins/smarty_internal_template.php

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