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 9.2KB

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