You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

smarty_internal_template.php 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. <?php
  2. /**
  3. * Smarty Internal Plugin Template
  4. * This file contains the Smarty template engine
  5. *
  6. * @package Smarty
  7. * @subpackage Template
  8. * @author Uwe Tews
  9. */
  10. /**
  11. * Main class with template data structures and methods
  12. *
  13. * @package Smarty
  14. * @subpackage Template
  15. *
  16. * @property Smarty_Template_Compiled $compiled
  17. * @property Smarty_Template_Cached $cached
  18. * @property Smarty_Internal_TemplateCompilerBase $compiler
  19. * @property mixed|\Smarty_Template_Cached registered_plugins
  20. *
  21. * The following methods will be dynamically loaded by the extension handler when they are called.
  22. * They are located in a corresponding Smarty_Internal_Method_xxxx class
  23. *
  24. * @method bool mustCompile()
  25. */
  26. class Smarty_Internal_Template extends Smarty_Internal_TemplateBase
  27. {
  28. /**
  29. * This object type (Smarty = 1, template = 2, data = 4)
  30. *
  31. * @var int
  32. */
  33. public $_objType = 2;
  34. /**
  35. * Global smarty instance
  36. *
  37. * @var Smarty
  38. */
  39. public $smarty = null;
  40. /**
  41. * Source instance
  42. *
  43. * @var Smarty_Template_Source|Smarty_Template_Config
  44. */
  45. public $source = null;
  46. /**
  47. * Inheritance runtime extension
  48. *
  49. * @var Smarty_Internal_Runtime_Inheritance
  50. */
  51. public $inheritance = null;
  52. /**
  53. * Template resource
  54. *
  55. * @var string
  56. */
  57. public $template_resource = null;
  58. /**
  59. * flag if compiled template is invalid and must be (re)compiled
  60. *
  61. * @var bool
  62. */
  63. public $mustCompile = null;
  64. /**
  65. * Template Id
  66. *
  67. * @var null|string
  68. */
  69. public $templateId = null;
  70. /**
  71. * Scope in which variables shall be assigned
  72. *
  73. * @var int
  74. */
  75. public $scope = 0;
  76. /**
  77. * Flag which is set while rending a cache file
  78. *
  79. * @var bool
  80. */
  81. public $isRenderingCache = false;
  82. /**
  83. * Callbacks called before rendering template
  84. *
  85. * @var callback[]
  86. */
  87. public $startRenderCallbacks = array();
  88. /**
  89. * Callbacks called after rendering template
  90. *
  91. * @var callback[]
  92. */
  93. public $endRenderCallbacks = array();
  94. /**
  95. * Template object cache
  96. *
  97. * @var Smarty_Internal_Template[]
  98. */
  99. public static $tplObjCache = array();
  100. /**
  101. * Template object cache for Smarty::isCached() === true
  102. *
  103. * @var Smarty_Internal_Template[]
  104. */
  105. public static $isCacheTplObj = array();
  106. /**
  107. * Sub template Info Cache
  108. * - index name
  109. * - value use count
  110. *
  111. * @var int[]
  112. */
  113. public static $subTplInfo = array();
  114. /**
  115. * Create template data object
  116. * Some of the global Smarty settings copied to template scope
  117. * It load the required template resources and caching plugins
  118. *
  119. * @param string $template_resource template resource string
  120. * @param Smarty $smarty Smarty instance
  121. * @param null|\Smarty_Internal_Template|\Smarty|\Smarty_Internal_Data $_parent back pointer to parent object
  122. * with variables or null
  123. * @param mixed $_cache_id cache id or null
  124. * @param mixed $_compile_id compile id or null
  125. * @param bool|int|null $_caching use caching?
  126. * @param int|null $_cache_lifetime cache life-time in seconds
  127. * @param bool $_isConfig
  128. *
  129. * @throws \SmartyException
  130. */
  131. public function __construct($template_resource, Smarty $smarty, Smarty_Internal_Data $_parent = null,
  132. $_cache_id = null, $_compile_id = null, $_caching = null, $_cache_lifetime = null,
  133. $_isConfig = false)
  134. {
  135. $this->smarty = $smarty;
  136. // Smarty parameter
  137. $this->cache_id = $_cache_id === null ? $this->smarty->cache_id : $_cache_id;
  138. $this->compile_id = $_compile_id === null ? $this->smarty->compile_id : $_compile_id;
  139. $this->caching = (int)($_caching === null ? $this->smarty->caching : $_caching);
  140. $this->cache_lifetime = $_cache_lifetime === null ? $this->smarty->cache_lifetime : $_cache_lifetime;
  141. $this->compile_check = (int)$smarty->compile_check;
  142. $this->parent = $_parent;
  143. // Template resource
  144. $this->template_resource = $template_resource;
  145. $this->source = $_isConfig ? Smarty_Template_Config::load($this) : Smarty_Template_Source::load($this);
  146. parent::__construct();
  147. if ($smarty->security_policy && method_exists($smarty->security_policy, 'registerCallBacks')) {
  148. $smarty->security_policy->registerCallBacks($this);
  149. }
  150. }
  151. /**
  152. * render template
  153. *
  154. * @param bool $no_output_filter if true do not run output filter
  155. * @param null|bool $display true: display, false: fetch null: sub-template
  156. *
  157. * @return string
  158. * @throws \Exception
  159. * @throws \SmartyException
  160. */
  161. public function render($no_output_filter = true, $display = null)
  162. {
  163. if ($this->smarty->debugging) {
  164. if (!isset($this->smarty->_debug)) {
  165. $this->smarty->_debug = new Smarty_Internal_Debug();
  166. }
  167. $this->smarty->_debug->start_template($this, $display);
  168. }
  169. // checks if template exists
  170. if (!$this->source->exists) {
  171. throw new SmartyException("Unable to load template '{$this->source->type}:{$this->source->name}'" .
  172. ($this->_isSubTpl() ? " in '{$this->parent->template_resource}'" : ''));
  173. }
  174. // disable caching for evaluated code
  175. if ($this->source->handler->recompiled) {
  176. $this->caching = Smarty::CACHING_OFF;
  177. }
  178. // read from cache or render
  179. if ($this->caching === Smarty::CACHING_LIFETIME_CURRENT || $this->caching === Smarty::CACHING_LIFETIME_SAVED) {
  180. if (!isset($this->cached) || $this->cached->cache_id !== $this->cache_id ||
  181. $this->cached->compile_id !== $this->compile_id
  182. ) {
  183. $this->loadCached(true);
  184. }
  185. $this->cached->render($this, $no_output_filter);
  186. } else {
  187. if (!isset($this->compiled) || $this->compiled->compile_id !== $this->compile_id) {
  188. $this->loadCompiled(true);
  189. }
  190. $this->compiled->render($this);
  191. }
  192. // display or fetch
  193. if ($display) {
  194. if ($this->caching && $this->smarty->cache_modified_check) {
  195. $this->smarty->ext->_cacheModify->cacheModifiedCheck($this->cached, $this,
  196. isset($content) ? $content : ob_get_clean());
  197. } else {
  198. if ((!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) &&
  199. !$no_output_filter && (isset($this->smarty->autoload_filters[ 'output' ]) ||
  200. isset($this->smarty->registered_filters[ 'output' ]))
  201. ) {
  202. echo $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this);
  203. } else {
  204. echo ob_get_clean();
  205. }
  206. }
  207. if ($this->smarty->debugging) {
  208. $this->smarty->_debug->end_template($this);
  209. // debug output
  210. $this->smarty->_debug->display_debug($this, true);
  211. }
  212. return '';
  213. } else {
  214. if ($this->smarty->debugging) {
  215. $this->smarty->_debug->end_template($this);
  216. if ($this->smarty->debugging === 2 && $display === false) {
  217. $this->smarty->_debug->display_debug($this, true);
  218. }
  219. }
  220. if (!$no_output_filter &&
  221. (!$this->caching || $this->cached->has_nocache_code || $this->source->handler->recompiled) &&
  222. (isset($this->smarty->autoload_filters[ 'output' ]) ||
  223. isset($this->smarty->registered_filters[ 'output' ]))
  224. ) {
  225. return $this->smarty->ext->_filterHandler->runFilter('output', ob_get_clean(), $this);
  226. }
  227. // return cache content
  228. return null;
  229. }
  230. }
  231. /**
  232. * Runtime function to render sub-template
  233. *
  234. * @param string $template template name
  235. * @param mixed $cache_id cache id
  236. * @param mixed $compile_id compile id
  237. * @param integer $caching cache mode
  238. * @param integer $cache_lifetime life time of cache data
  239. * @param array $data passed parameter template variables
  240. * @param int $scope scope in which {include} should execute
  241. * @param bool $forceTplCache cache template object
  242. * @param string $uid file dependency uid
  243. * @param string $content_func function name
  244. *
  245. * @throws \Exception
  246. * @throws \SmartyException
  247. */
  248. public function _subTemplateRender($template, $cache_id, $compile_id, $caching, $cache_lifetime, $data, $scope,
  249. $forceTplCache, $uid = null, $content_func = null)
  250. {
  251. $tpl = clone $this;
  252. $tpl->parent = $this;
  253. $smarty = &$this->smarty;
  254. $_templateId = $smarty->_getTemplateId($template, $cache_id, $compile_id, $caching, $tpl);
  255. // recursive call ?
  256. if (isset($tpl->templateId) ? $tpl->templateId : $tpl->_getTemplateId() !== $_templateId) {
  257. // already in template cache?
  258. if (isset(self::$tplObjCache[ $_templateId ])) {
  259. // copy data from cached object
  260. $cachedTpl = &self::$tplObjCache[ $_templateId ];
  261. $tpl->templateId = $cachedTpl->templateId;
  262. $tpl->template_resource = $cachedTpl->template_resource;
  263. $tpl->cache_id = $cachedTpl->cache_id;
  264. $tpl->compile_id = $cachedTpl->compile_id;
  265. $tpl->source = $cachedTpl->source;
  266. if (isset($cachedTpl->compiled)) {
  267. $tpl->compiled = $cachedTpl->compiled;
  268. } else {
  269. unset($tpl->compiled);
  270. }
  271. if ($caching !== 9999 && isset($cachedTpl->cached)) {
  272. $tpl->cached = $cachedTpl->cached;
  273. } else {
  274. unset($tpl->cached);
  275. }
  276. } else {
  277. $tpl->templateId = $_templateId;
  278. $tpl->template_resource = $template;
  279. $tpl->cache_id = $cache_id;
  280. $tpl->compile_id = $compile_id;
  281. if (isset($uid)) {
  282. // for inline templates we can get all resource information from file dependency
  283. list($filepath, $timestamp, $type) = $tpl->compiled->file_dependency[ $uid ];
  284. $tpl->source = new Smarty_Template_Source($smarty, $filepath, $type, $filepath);
  285. $tpl->source->filepath = $filepath;
  286. $tpl->source->timestamp = $timestamp;
  287. $tpl->source->exists = true;
  288. $tpl->source->uid = $uid;
  289. } else {
  290. $tpl->source = Smarty_Template_Source::load($tpl);
  291. unset($tpl->compiled);
  292. }
  293. if ($caching !== 9999) {
  294. unset($tpl->cached);
  295. }
  296. }
  297. } else {
  298. // on recursive calls force caching
  299. $forceTplCache = true;
  300. }
  301. $tpl->caching = $caching;
  302. $tpl->cache_lifetime = $cache_lifetime;
  303. // set template scope
  304. $tpl->scope = $scope;
  305. if (!isset(self::$tplObjCache[ $tpl->templateId ]) && !$tpl->source->handler->recompiled) {
  306. // check if template object should be cached
  307. if ($forceTplCache || (isset(self::$subTplInfo[ $tpl->template_resource ]) &&
  308. self::$subTplInfo[ $tpl->template_resource ] > 1) ||
  309. ($tpl->_isSubTpl() && isset(self::$tplObjCache[ $tpl->parent->templateId ]))
  310. ) {
  311. self::$tplObjCache[ $tpl->templateId ] = $tpl;
  312. }
  313. }
  314. if (!empty($data)) {
  315. // set up variable values
  316. foreach ($data as $_key => $_val) {
  317. $tpl->tpl_vars[ $_key ] = new Smarty_Variable($_val, $this->isRenderingCache);
  318. }
  319. }
  320. if ($tpl->caching === 9999) {
  321. if (!isset($tpl->compiled)) {
  322. $this->loadCompiled(true);
  323. }
  324. if ($tpl->compiled->has_nocache_code) {
  325. $this->cached->hashes[ $tpl->compiled->nocache_hash ] = true;
  326. }
  327. }
  328. $tpl->_cache = array();
  329. if (isset($uid)) {
  330. if ($smarty->debugging) {
  331. if (!isset($smarty->_debug)) {
  332. $smarty->_debug = new Smarty_Internal_Debug();
  333. }
  334. $smarty->_debug->start_template($tpl);
  335. $smarty->_debug->start_render($tpl);
  336. }
  337. $tpl->compiled->getRenderedTemplateCode($tpl, $content_func);
  338. if ($smarty->debugging) {
  339. $smarty->_debug->end_template($tpl);
  340. $smarty->_debug->end_render($tpl);
  341. }
  342. } else {
  343. if (isset($tpl->compiled)) {
  344. $tpl->compiled->render($tpl);
  345. } else {
  346. $tpl->render();
  347. }
  348. }
  349. }
  350. /**
  351. * Get called sub-templates and save call count
  352. *
  353. */
  354. public function _subTemplateRegister()
  355. {
  356. foreach ($this->compiled->includes as $name => $count) {
  357. if (isset(self::$subTplInfo[ $name ])) {
  358. self::$subTplInfo[ $name ] += $count;
  359. } else {
  360. self::$subTplInfo[ $name ] = $count;
  361. }
  362. }
  363. }
  364. /**
  365. * Check if this is a sub template
  366. *
  367. * @return bool true is sub template
  368. */
  369. public function _isSubTpl()
  370. {
  371. return isset($this->parent) && $this->parent->_isTplObj();
  372. }
  373. /**
  374. * Assign variable in scope
  375. *
  376. * @param string $varName variable name
  377. * @param mixed $value value
  378. * @param bool $nocache nocache flag
  379. * @param int $scope scope into which variable shall be assigned
  380. *
  381. */
  382. public function _assignInScope($varName, $value, $nocache = false, $scope = 0)
  383. {
  384. if (isset($this->tpl_vars[ $varName ])) {
  385. $this->tpl_vars[ $varName ] = clone $this->tpl_vars[ $varName ];
  386. $this->tpl_vars[ $varName ]->value = $value;
  387. if ($nocache || $this->isRenderingCache) {
  388. $this->tpl_vars[ $varName ]->nocache = true;
  389. }
  390. } else {
  391. $this->tpl_vars[ $varName ] = new Smarty_Variable($value, $nocache || $this->isRenderingCache);
  392. }
  393. if ($scope >= 0) {
  394. if ($scope > 0 || $this->scope > 0) {
  395. $this->smarty->ext->_updateScope->_updateScope($this, $varName, $scope);
  396. }
  397. }
  398. }
  399. /**
  400. * Check if plugins are callable require file otherwise
  401. *
  402. * @param array $plugins required plugins
  403. *
  404. * @throws \SmartyException
  405. */
  406. public function _checkPlugins($plugins) {
  407. static $checked = array();
  408. foreach($plugins as $plugin) {
  409. $name = join('::', (array)$plugin[ 'function' ]);
  410. if (!isset($checked[$name])) {
  411. if (!is_callable($plugin['function'])) {
  412. if (is_file($plugin['file'])) {
  413. require_once $plugin['file'];
  414. if (is_callable($plugin['function'])) {
  415. $checked[ $name ] = true;
  416. }
  417. }
  418. } else {
  419. $checked[ $name ] = true;
  420. }
  421. }
  422. if (!isset($checked[ $name ])) {
  423. if (false !== $this->smarty->loadPlugin($name)) {
  424. $checked[ $name ] = true;
  425. } else {
  426. throw new SmartyException("Plugin '{$name}' not callable");
  427. }
  428. }
  429. }
  430. }
  431. /**
  432. * This function is executed automatically when a compiled or cached template file is included
  433. * - Decode saved properties from compiled template and cache files
  434. * - Check if compiled or cache file is valid
  435. *
  436. * @param \Smarty_Internal_Template $tpl
  437. * @param array $properties special template properties
  438. * @param bool $cache flag if called from cache file
  439. *
  440. * @return bool flag if compiled or cache file is valid
  441. * @throws \SmartyException
  442. */
  443. public function _decodeProperties(Smarty_Internal_Template $tpl, $properties, $cache = false)
  444. {
  445. // on cache resources other than file check version stored in cache code
  446. if (!isset($properties[ 'version' ]) || Smarty::SMARTY_VERSION !== $properties[ 'version' ]) {
  447. if ($cache) {
  448. $tpl->smarty->clearAllCache();
  449. } else {
  450. $tpl->smarty->clearCompiledTemplate();
  451. }
  452. return false;
  453. }
  454. $is_valid = true;
  455. if (!empty($properties[ 'file_dependency' ]) &&
  456. ((!$cache && $tpl->compile_check) || $tpl->compile_check === Smarty::COMPILECHECK_ON)
  457. ) {
  458. // check file dependencies at compiled code
  459. foreach ($properties[ 'file_dependency' ] as $_file_to_check) {
  460. if ($_file_to_check[ 2 ] === 'file' || $_file_to_check[ 2 ] === 'php') {
  461. if ($tpl->source->filepath === $_file_to_check[ 0 ]) {
  462. // do not recheck current template
  463. continue;
  464. //$mtime = $tpl->source->getTimeStamp();
  465. } else {
  466. // file and php types can be checked without loading the respective resource handlers
  467. $mtime = is_file($_file_to_check[ 0 ]) ? filemtime($_file_to_check[ 0 ]) : false;
  468. }
  469. } else {
  470. $handler = Smarty_Resource::load($tpl->smarty, $_file_to_check[ 2 ]);
  471. if ($handler->checkTimestamps()) {
  472. $source = Smarty_Template_Source::load($tpl, $tpl->smarty, $_file_to_check[ 0 ]);
  473. $mtime = $source->getTimeStamp();
  474. } else {
  475. continue;
  476. }
  477. }
  478. if ($mtime === false || $mtime > $_file_to_check[ 1 ]) {
  479. $is_valid = false;
  480. break;
  481. }
  482. }
  483. }
  484. if ($cache) {
  485. // CACHING_LIFETIME_SAVED cache expiry has to be validated here since otherwise we'd define the unifunc
  486. if ($tpl->caching === Smarty::CACHING_LIFETIME_SAVED && $properties[ 'cache_lifetime' ] >= 0 &&
  487. (time() > ($tpl->cached->timestamp + $properties[ 'cache_lifetime' ]))
  488. ) {
  489. $is_valid = false;
  490. }
  491. $tpl->cached->cache_lifetime = $properties[ 'cache_lifetime' ];
  492. $tpl->cached->valid = $is_valid;
  493. $resource = $tpl->cached;
  494. } else {
  495. $tpl->mustCompile = !$is_valid;
  496. $resource = $tpl->compiled;
  497. $resource->includes = isset($properties[ 'includes' ]) ? $properties[ 'includes' ] : array();
  498. }
  499. if ($is_valid) {
  500. $resource->unifunc = $properties[ 'unifunc' ];
  501. $resource->has_nocache_code = $properties[ 'has_nocache_code' ];
  502. // $tpl->compiled->nocache_hash = $properties['nocache_hash'];
  503. $resource->file_dependency = $properties[ 'file_dependency' ];
  504. }
  505. return $is_valid && !function_exists($properties[ 'unifunc' ]);
  506. }
  507. /**
  508. * Compiles the template
  509. * If the template is not evaluated the compiled template is saved on disk
  510. */
  511. public function compileTemplateSource()
  512. {
  513. return $this->compiled->compileTemplateSource($this);
  514. }
  515. /**
  516. * Writes the content to cache resource
  517. *
  518. * @param string $content
  519. *
  520. * @return bool
  521. */
  522. public function writeCachedContent($content)
  523. {
  524. return $this->smarty->ext->_updateCache->writeCachedContent($this, $content);
  525. }
  526. /**
  527. * Get unique template id
  528. *
  529. * @return string
  530. * @throws \SmartyException
  531. */
  532. public function _getTemplateId()
  533. {
  534. return isset($this->templateId) ? $this->templateId : $this->templateId =
  535. $this->smarty->_getTemplateId($this->template_resource, $this->cache_id, $this->compile_id);
  536. }
  537. /**
  538. * runtime error not matching capture tags
  539. */
  540. public function capture_error()
  541. {
  542. throw new SmartyException("Not matching {capture} open/close in '{$this->template_resource}'");
  543. }
  544. /**
  545. * Load compiled object
  546. *
  547. * @param bool $force force new compiled object
  548. */
  549. public function loadCompiled($force = false)
  550. {
  551. if ($force || !isset($this->compiled)) {
  552. $this->compiled = Smarty_Template_Compiled::load($this);
  553. }
  554. }
  555. /**
  556. * Load cached object
  557. *
  558. * @param bool $force force new cached object
  559. */
  560. public function loadCached($force = false)
  561. {
  562. if ($force || !isset($this->cached)) {
  563. $this->cached = Smarty_Template_Cached::load($this);
  564. }
  565. }
  566. /**
  567. * Load inheritance object
  568. *
  569. */
  570. public function _loadInheritance()
  571. {
  572. if (!isset($this->inheritance)) {
  573. $this->inheritance = new Smarty_Internal_Runtime_Inheritance();
  574. }
  575. }
  576. /**
  577. * Unload inheritance object
  578. *
  579. */
  580. public function _cleanUp()
  581. {
  582. $this->startRenderCallbacks = array();
  583. $this->endRenderCallbacks = array();
  584. $this->inheritance = null;
  585. }
  586. /**
  587. * Load compiler object
  588. *
  589. * @throws \SmartyException
  590. */
  591. public function loadCompiler()
  592. {
  593. if (!class_exists($this->source->compiler_class)) {
  594. $this->smarty->loadPlugin($this->source->compiler_class);
  595. }
  596. $this->compiler =
  597. new $this->source->compiler_class($this->source->template_lexer_class, $this->source->template_parser_class,
  598. $this->smarty);
  599. }
  600. /**
  601. * Handle unknown class methods
  602. *
  603. * @param string $name unknown method-name
  604. * @param array $args argument array
  605. *
  606. * @return mixed
  607. * @throws SmartyException
  608. */
  609. public function __call($name, $args)
  610. {
  611. // method of Smarty object?
  612. if (method_exists($this->smarty, $name)) {
  613. return call_user_func_array(array($this->smarty, $name), $args);
  614. }
  615. // parent
  616. return parent::__call($name, $args);
  617. }
  618. /**
  619. * set Smarty property in template context
  620. *
  621. * @param string $property_name property name
  622. * @param mixed $value value
  623. *
  624. * @throws SmartyException
  625. */
  626. public function __set($property_name, $value)
  627. {
  628. switch ($property_name) {
  629. case 'compiled':
  630. case 'cached':
  631. case 'compiler':
  632. $this->$property_name = $value;
  633. return;
  634. default:
  635. // Smarty property ?
  636. if (property_exists($this->smarty, $property_name)) {
  637. $this->smarty->$property_name = $value;
  638. return;
  639. }
  640. }
  641. throw new SmartyException("invalid template property '$property_name'.");
  642. }
  643. /**
  644. * get Smarty property in template context
  645. *
  646. * @param string $property_name property name
  647. *
  648. * @return mixed|Smarty_Template_Cached
  649. * @throws SmartyException
  650. */
  651. public function __get($property_name)
  652. {
  653. switch ($property_name) {
  654. case 'compiled':
  655. $this->loadCompiled();
  656. return $this->compiled;
  657. case 'cached':
  658. $this->loadCached();
  659. return $this->cached;
  660. case 'compiler':
  661. $this->loadCompiler();
  662. return $this->compiler;
  663. default:
  664. // Smarty property ?
  665. if (property_exists($this->smarty, $property_name)) {
  666. return $this->smarty->$property_name;
  667. }
  668. }
  669. throw new SmartyException("template property '$property_name' does not exist.");
  670. }
  671. /**
  672. * Template data object destructor
  673. */
  674. public function __destruct()
  675. {
  676. if ($this->smarty->cache_locking && isset($this->cached) && $this->cached->is_locked) {
  677. $this->cached->handler->releaseLock($this->smarty, $this->cached);
  678. }
  679. }
  680. }