smarty_template_compiled.php 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  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. $compiled = new Smarty_Template_Compiled();
  29. if ($_template->source->handler->hasCompiledHandler) {
  30. $_template->source->handler->populateCompiledFilepath($compiled, $_template);
  31. } else {
  32. $compiled->populateCompiledFilepath($_template);
  33. }
  34. return $compiled;
  35. }
  36. /**
  37. * populate Compiled Object with compiled filepath
  38. *
  39. * @param Smarty_Internal_Template $_template template object
  40. **/
  41. public function populateCompiledFilepath(Smarty_Internal_Template $_template)
  42. {
  43. $source = &$_template->source;
  44. $smarty = &$_template->smarty;
  45. $this->filepath = $smarty->getCompileDir();
  46. if (isset($_template->compile_id)) {
  47. $this->filepath .= preg_replace('![^\w]+!', '_', $_template->compile_id) .
  48. ($smarty->use_sub_dirs ? $smarty->ds : '^');
  49. }
  50. // if use_sub_dirs, break file into directories
  51. if ($smarty->use_sub_dirs) {
  52. $this->filepath .= $source->uid[ 0 ] . $source->uid[ 1 ] . $smarty->ds . $source->uid[ 2 ] .
  53. $source->uid[ 3 ] . $smarty->ds . $source->uid[ 4 ] . $source->uid[ 5 ] . $smarty->ds;
  54. }
  55. $this->filepath .= $source->uid . '_';
  56. if ($source->isConfig) {
  57. $this->filepath .= (int) $smarty->config_read_hidden + (int) $smarty->config_booleanize * 2 +
  58. (int) $smarty->config_overwrite * 4;
  59. } else {
  60. $this->filepath .= (int) $smarty->merge_compiled_includes + (int) $smarty->escape_html * 2 +
  61. (($smarty->merge_compiled_includes && $source->type === 'extends') ?
  62. (int) $smarty->extends_recursion * 4 : 0);
  63. }
  64. $this->filepath .= '.' . $source->type;
  65. $basename = $source->handler->getBasename($source);
  66. if (!empty($basename)) {
  67. $this->filepath .= '.' . $basename;
  68. }
  69. if ($_template->caching) {
  70. $this->filepath .= '.cache';
  71. }
  72. $this->filepath .= '.php';
  73. $this->timestamp = $this->exists = is_file($this->filepath);
  74. if ($this->exists) {
  75. $this->timestamp = filemtime($this->filepath);
  76. }
  77. }
  78. /**
  79. * render compiled template code
  80. *
  81. * @param Smarty_Internal_Template $_template
  82. *
  83. * @return string
  84. * @throws Exception
  85. */
  86. public function render(Smarty_Internal_Template $_template)
  87. {
  88. // checks if template exists
  89. if (!$_template->source->exists) {
  90. $type = $_template->source->isConfig ? 'config' : 'template';
  91. throw new SmartyException("Unable to load {$type} '{$_template->source->type}:{$_template->source->name}'");
  92. }
  93. if ($_template->smarty->debugging) {
  94. if (!isset($_template->smarty->_debug)) {
  95. $_template->smarty->_debug = new Smarty_Internal_Debug();
  96. }
  97. $_template->smarty->_debug->start_render($_template);
  98. }
  99. if (!$this->processed) {
  100. $this->process($_template);
  101. }
  102. if (isset($_template->cached)) {
  103. $_template->cached->file_dependency =
  104. array_merge($_template->cached->file_dependency, $this->file_dependency);
  105. }
  106. if ($_template->source->handler->uncompiled) {
  107. $_template->source->handler->renderUncompiled($_template->source, $_template);
  108. } else {
  109. $this->getRenderedTemplateCode($_template);
  110. }
  111. if ($_template->caching && $this->has_nocache_code) {
  112. $_template->cached->hashes[ $this->nocache_hash ] = true;
  113. }
  114. if ($_template->smarty->debugging) {
  115. $_template->smarty->_debug->end_render($_template);
  116. }
  117. }
  118. /**
  119. * load compiled template or compile from source
  120. *
  121. * @param Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template
  122. *
  123. * @throws Exception
  124. */
  125. public function process(Smarty_Internal_Template $_smarty_tpl)
  126. {
  127. $source = &$_smarty_tpl->source;
  128. $smarty = &$_smarty_tpl->smarty;
  129. if ($source->handler->recompiled) {
  130. $source->handler->process($_smarty_tpl);
  131. } elseif (!$source->handler->uncompiled) {
  132. if (!$this->exists || $smarty->force_compile ||
  133. ($smarty->compile_check && $source->getTimeStamp() > $this->getTimeStamp())
  134. ) {
  135. $this->compileTemplateSource($_smarty_tpl);
  136. $compileCheck = $smarty->compile_check;
  137. $smarty->compile_check = false;
  138. $this->loadCompiledTemplate($_smarty_tpl);
  139. $smarty->compile_check = $compileCheck;
  140. } else {
  141. $_smarty_tpl->mustCompile = true;
  142. @include($this->filepath);
  143. if ($_smarty_tpl->mustCompile) {
  144. $this->compileTemplateSource($_smarty_tpl);
  145. $compileCheck = $smarty->compile_check;
  146. $smarty->compile_check = false;
  147. $this->loadCompiledTemplate($_smarty_tpl);
  148. $smarty->compile_check = $compileCheck;
  149. }
  150. }
  151. $_smarty_tpl->_subTemplateRegister();
  152. $this->processed = true;
  153. }
  154. }
  155. /**
  156. * compile template from source
  157. *
  158. * @param Smarty_Internal_Template $_template
  159. *
  160. * @throws Exception
  161. */
  162. public function compileTemplateSource(Smarty_Internal_Template $_template)
  163. {
  164. $this->file_dependency = array();
  165. $this->includes = array();
  166. $this->nocache_hash = null;
  167. $this->unifunc = null;
  168. // compile locking
  169. if ($saved_timestamp = (!$_template->source->handler->recompiled && is_file($this->filepath))) {
  170. $saved_timestamp = $this->getTimeStamp();
  171. touch($this->filepath);
  172. }
  173. // compile locking
  174. try {
  175. // call compiler
  176. $_template->loadCompiler();
  177. $this->write($_template, $_template->compiler->compileTemplate($_template));
  178. }
  179. catch (Exception $e) {
  180. // restore old timestamp in case of error
  181. if ($saved_timestamp && is_file($this->filepath)) {
  182. touch($this->filepath, $saved_timestamp);
  183. }
  184. unset($_template->compiler);
  185. throw $e;
  186. }
  187. // release compiler object to free memory
  188. unset($_template->compiler);
  189. }
  190. /**
  191. * Write compiled code by handler
  192. *
  193. * @param Smarty_Internal_Template $_template template object
  194. * @param string $code compiled code
  195. *
  196. * @return boolean success
  197. */
  198. public function write(Smarty_Internal_Template $_template, $code)
  199. {
  200. if (!$_template->source->handler->recompiled) {
  201. if ($_template->smarty->ext->_writeFile->writeFile($this->filepath, $code, $_template->smarty) === true) {
  202. $this->timestamp = $this->exists = is_file($this->filepath);
  203. if ($this->exists) {
  204. $this->timestamp = filemtime($this->filepath);
  205. return true;
  206. }
  207. }
  208. return false;
  209. }
  210. return true;
  211. }
  212. /**
  213. * Load fresh compiled template by including the PHP file
  214. * HHVM requires a work around because of a PHP incompatibility
  215. *
  216. * @param \Smarty_Internal_Template $_smarty_tpl do not change variable name, is used by compiled template
  217. */
  218. private function loadCompiledTemplate(Smarty_Internal_Template $_smarty_tpl)
  219. {
  220. if (function_exists('opcache_invalidate')
  221. && (!function_exists('ini_get') || strlen(ini_get("opcache.restrict_api")) < 1)
  222. ) {
  223. opcache_invalidate($this->filepath, true);
  224. } elseif (function_exists('apc_compile_file')) {
  225. apc_compile_file($this->filepath);
  226. }
  227. if (defined('HHVM_VERSION')) {
  228. eval("?>" . file_get_contents($this->filepath));
  229. } else {
  230. include($this->filepath);
  231. }
  232. }
  233. /**
  234. * Read compiled content from handler
  235. *
  236. * @param Smarty_Internal_Template $_template template object
  237. *
  238. * @return string content
  239. */
  240. public function read(Smarty_Internal_Template $_template)
  241. {
  242. if (!$_template->source->handler->recompiled) {
  243. return file_get_contents($this->filepath);
  244. }
  245. return isset($this->content) ? $this->content : false;
  246. }
  247. }