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