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_template_compiled.php 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <?php
  2. /**
  3. * Smarty Resource Data Object
  4. * Meta Data Container for Template Files
  5. *
  6. * @package Smarty
  7. * @subpackage TemplateResources
  8. * @author Rodney Rehm
  9. * @property string $content compiled content
  10. */
  11. class Smarty_Template_Compiled extends Smarty_Template_Resource_Base
  12. {
  13. /**
  14. * nocache hash
  15. *
  16. * @var string|null
  17. */
  18. public $nocache_hash = null;
  19. /**
  20. * get a Compiled Object of this source
  21. *
  22. * @param Smarty_Internal_Template $_template template object
  23. *
  24. * @return Smarty_Template_Compiled compiled object
  25. */
  26. static function load($_template)
  27. {
  28. // check runtime cache
  29. if (!$_template->source->handler->recompiled &&
  30. ($_template->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON)
  31. ) {
  32. $_cache_key = $_template->source->unique_resource . '#';
  33. if ($_template->caching) {
  34. $_cache_key .= 'caching#';
  35. }
  36. $_cache_key .= $_template->compile_id;
  37. if (isset($_template->source->compileds[$_cache_key])) {
  38. return $_template->source->compileds[$_cache_key];
  39. }
  40. }
  41. $compiled = new Smarty_Template_Compiled();
  42. if ($_template->source->handler->hasCompiledHandler) {
  43. $_template->source->handler->populateCompiledFilepath($compiled, $_template);
  44. } else {
  45. $compiled->populateCompiledFilepath($_template);
  46. }
  47. // runtime cache
  48. if (!$_template->source->handler->recompiled &&
  49. ($_template->smarty->resource_cache_mode & Smarty::RESOURCE_CACHE_ON)
  50. ) {
  51. $_template->source->compileds[$_cache_key] = $compiled;
  52. }
  53. return $compiled;
  54. }
  55. /**
  56. * populate Compiled Object with compiled filepath
  57. *
  58. * @param Smarty_Internal_Template $_template template object
  59. **/
  60. public function populateCompiledFilepath(Smarty_Internal_Template $_template)
  61. {
  62. $_compile_id = isset($_template->compile_id) ? preg_replace('![^\w]+!', '_', $_template->compile_id) : null;
  63. if ($_template->source->isConfig) {
  64. $_flag = '_' .
  65. ((int) $_template->smarty->config_read_hidden + (int) $_template->smarty->config_booleanize * 2 +
  66. (int) $_template->smarty->config_overwrite * 4);
  67. } else {
  68. $_flag =
  69. '_' . ((int) $_template->smarty->merge_compiled_includes + (int) $_template->smarty->escape_html * 2);
  70. }
  71. $_filepath = $_template->source->uid . $_flag;
  72. // if use_sub_dirs, break file into directories
  73. if ($_template->smarty->use_sub_dirs) {
  74. $_filepath = substr($_filepath, 0, 2) . DS . substr($_filepath, 2, 2) . DS . substr($_filepath, 4, 2) . DS .
  75. $_filepath;
  76. }
  77. $_compile_dir_sep = $_template->smarty->use_sub_dirs ? DS : '^';
  78. if (isset($_compile_id)) {
  79. $_filepath = $_compile_id . $_compile_dir_sep . $_filepath;
  80. }
  81. // caching token
  82. if ($_template->caching) {
  83. $_cache = '.cache';
  84. } else {
  85. $_cache = '';
  86. }
  87. $_compile_dir = $_template->smarty->getCompileDir();
  88. // set basename if not specified
  89. $_basename = $_template->source->handler->getBasename($_template->source);
  90. if ($_basename === null) {
  91. $_basename = basename(preg_replace('![^\w]+!', '_', $_template->source->name));
  92. }
  93. // separate (optional) basename by dot
  94. if ($_basename) {
  95. $_basename = '.' . $_basename;
  96. }
  97. $this->filepath = $_compile_dir . $_filepath . '.' . $_template->source->type . $_basename . $_cache . '.php';
  98. $this->exists = is_file($this->filepath);
  99. if (!$this->exists) {
  100. $this->timestamp = false;
  101. }
  102. }
  103. /**
  104. * load compiled template or compile from source
  105. *
  106. * @param Smarty_Internal_Template $_template
  107. *
  108. * @throws Exception
  109. */
  110. public function process(Smarty_Internal_Template $_template)
  111. {
  112. $_smarty_tpl = $_template;
  113. if ($_template->source->handler->recompiled || !$_template->compiled->exists ||
  114. $_template->smarty->force_compile || ($_template->smarty->compile_check &&
  115. $_template->source->getTimeStamp() > $_template->compiled->getTimeStamp())
  116. ) {
  117. $this->compileTemplateSource($_template);
  118. $compileCheck = $_template->smarty->compile_check;
  119. $_template->smarty->compile_check = false;
  120. if ($_template->source->handler->recompiled) {
  121. $level = ob_get_level();
  122. ob_start();
  123. try {
  124. eval("?>" . $this->content);
  125. }
  126. catch (Exception $e) {
  127. while (ob_get_level() > $level) {
  128. ob_end_clean();
  129. }
  130. throw $e;
  131. }
  132. ob_get_clean();
  133. $this->content = null;
  134. } else {
  135. $this->loadCompiledTemplate($_template);
  136. }
  137. $_template->smarty->compile_check = $compileCheck;
  138. } else {
  139. $_template->mustCompile = true;
  140. @include($_template->compiled->filepath);
  141. if ($_template->mustCompile) {
  142. $this->compileTemplateSource($_template);
  143. $compileCheck = $_template->smarty->compile_check;
  144. $_template->smarty->compile_check = false;
  145. $this->loadCompiledTemplate($_template);
  146. $_template->smarty->compile_check = $compileCheck;
  147. }
  148. }
  149. $_template->smarty->ext->_subTemplate->registerSubTemplates($_template);
  150. $this->processed = true;
  151. }
  152. /**
  153. * Load fresh compiled template by including the PHP file
  154. * HHVM requires a work around because of a PHP incompatibility
  155. *
  156. * @param \Smarty_Internal_Template $_template
  157. */
  158. private function loadCompiledTemplate(Smarty_Internal_Template $_template)
  159. {
  160. if (function_exists('opcache_invalidate')) {
  161. opcache_invalidate($_template->compiled->filepath);
  162. }
  163. $_smarty_tpl = $_template;
  164. if (defined('HHVM_VERSION')) {
  165. $_template->smarty->ext->_hhvm->includeHhvm($_template, $_template->compiled->filepath);
  166. } else {
  167. include($_template->compiled->filepath);
  168. }
  169. }
  170. /**
  171. * render compiled template code
  172. *
  173. * @param Smarty_Internal_Template $_template
  174. *
  175. * @return string
  176. * @throws Exception
  177. */
  178. public function render(Smarty_Internal_Template $_template)
  179. {
  180. if ($_template->smarty->debugging) {
  181. $_template->smarty->_debug->start_render($_template);
  182. }
  183. if (!$this->processed) {
  184. $this->process($_template);
  185. }
  186. if (isset($_template->cached)) {
  187. $_template->cached->file_dependency =
  188. array_merge($_template->cached->file_dependency, $this->file_dependency);
  189. }
  190. $this->getRenderedTemplateCode($_template);
  191. if ($_template->caching && $this->has_nocache_code) {
  192. $_template->cached->hashes[$this->nocache_hash] = true;
  193. }
  194. if (isset($_template->parent) && $_template->parent->_objType == 2 && !empty($_template->tpl_function)) {
  195. $_template->parent->tpl_function = array_merge($_template->parent->tpl_function, $_template->tpl_function);
  196. }
  197. if ($_template->smarty->debugging) {
  198. $_template->smarty->_debug->end_render($_template);
  199. }
  200. }
  201. /**
  202. * compile template from source
  203. *
  204. * @param Smarty_Internal_Template $_template
  205. *
  206. * @return string
  207. * @throws Exception
  208. */
  209. public function compileTemplateSource(Smarty_Internal_Template $_template)
  210. {
  211. $_template->source->compileds = array();
  212. $this->file_dependency = array();
  213. $this->tpl_function = array();
  214. $this->includes = array();
  215. $this->nocache_hash = null;
  216. $this->unifunc = null;
  217. // compile locking
  218. if (!$_template->source->handler->recompiled) {
  219. if ($saved_timestamp = $_template->compiled->getTimeStamp()) {
  220. touch($_template->compiled->filepath);
  221. }
  222. }
  223. // call compiler
  224. try {
  225. $_template->loadCompiler();
  226. $code = $_template->compiler->compileTemplate($_template);
  227. }
  228. catch (Exception $e) {
  229. // restore old timestamp in case of error
  230. if (!$_template->source->handler->recompiled && $saved_timestamp) {
  231. touch($_template->compiled->filepath, $saved_timestamp);
  232. }
  233. throw $e;
  234. }
  235. // compiling succeeded
  236. if ($_template->compiler->write_compiled_code) {
  237. // write compiled template
  238. $this->write($_template, $code);
  239. $code = '';
  240. }
  241. // release compiler object to free memory
  242. unset($_template->compiler);
  243. return $code;
  244. }
  245. /**
  246. * Write compiled code by handler
  247. *
  248. * @param Smarty_Internal_Template $_template template object
  249. * @param string $code compiled code
  250. *
  251. * @return boolean success
  252. */
  253. public function write(Smarty_Internal_Template $_template, $code)
  254. {
  255. if (!$_template->source->handler->recompiled) {
  256. if ($_template->smarty->ext->_writeFile->writeFile($this->filepath, $code, $_template->smarty) === true) {
  257. $this->timestamp = $this->exists = is_file($this->filepath);
  258. if ($this->exists) {
  259. $this->timestamp = filemtime($this->filepath);
  260. return true;
  261. }
  262. }
  263. return false;
  264. } else {
  265. $this->content = $code;
  266. }
  267. $this->timestamp = time();
  268. $this->exists = true;
  269. return true;
  270. }
  271. /**
  272. * Read compiled content from handler
  273. *
  274. * @param Smarty_Internal_Template $_template template object
  275. *
  276. * @return string content
  277. */
  278. public function read(Smarty_Internal_Template $_template)
  279. {
  280. if (!$_template->source->handler->recompiled) {
  281. return file_get_contents($this->filepath);
  282. }
  283. return isset($this->content) ? $this->content : false;
  284. }
  285. }