smarty_internal_compile_include.php (14722B)
1 <?php 2 /** 3 * Smarty Internal Plugin Compile Include 4 * Compiles the {include} tag 5 * 6 * @package Smarty 7 * @subpackage Compiler 8 * @author Uwe Tews 9 */ 10 11 /** 12 * Smarty Internal Plugin Compile Include Class 13 * 14 * @package Smarty 15 * @subpackage Compiler 16 */ 17 class Smarty_Internal_Compile_Include extends Smarty_Internal_CompileBase 18 { 19 /** 20 * caching mode to create nocache code but no cache file 21 */ 22 const CACHING_NOCACHE_CODE = 9999; 23 /** 24 * Attribute definition: Overwrites base class. 25 * 26 * @var array 27 * @see Smarty_Internal_CompileBase 28 */ 29 public $required_attributes = array('file'); 30 /** 31 * Attribute definition: Overwrites base class. 32 * 33 * @var array 34 * @see Smarty_Internal_CompileBase 35 */ 36 public $shorttag_order = array('file'); 37 /** 38 * Attribute definition: Overwrites base class. 39 * 40 * @var array 41 * @see Smarty_Internal_CompileBase 42 */ 43 public $option_flags = array('nocache', 'inline', 'caching'); 44 /** 45 * Attribute definition: Overwrites base class. 46 * 47 * @var array 48 * @see Smarty_Internal_CompileBase 49 */ 50 public $optional_attributes = array('_any'); 51 52 /** 53 * Compiles code for the {include} tag 54 * 55 * @param array $args array with attributes from parser 56 * @param Smarty_Internal_SmartyTemplateCompiler $compiler compiler object 57 * @param array $parameter array with compilation parameter 58 * 59 * @throws SmartyCompilerException 60 * @return string compiled code 61 */ 62 public function compile($args, Smarty_Internal_SmartyTemplateCompiler $compiler, $parameter) 63 { 64 // check and get attributes 65 $_attr = $this->getAttributes($compiler, $args); 66 67 // save possible attributes 68 $include_file = $_attr['file']; 69 70 if (isset($_attr['assign'])) { 71 // output will be stored in a smarty variable instead of being displayed 72 $_assign = $_attr['assign']; 73 } 74 75 $_parent_scope = Smarty::SCOPE_LOCAL; 76 if (isset($_attr['scope'])) { 77 $_attr['scope'] = trim($_attr['scope'], "'\""); 78 if ($_attr['scope'] == 'parent') { 79 $_parent_scope = Smarty::SCOPE_PARENT; 80 } elseif ($_attr['scope'] == 'root') { 81 $_parent_scope = Smarty::SCOPE_ROOT; 82 } elseif ($_attr['scope'] == 'global') { 83 $_parent_scope = Smarty::SCOPE_GLOBAL; 84 } 85 } 86 87 // assume caching is off 88 $_caching = Smarty::CACHING_OFF; 89 90 if ($_attr['nocache'] === true) { 91 $compiler->tag_nocache = true; 92 } 93 94 $call_nocache = $compiler->tag_nocache || $compiler->nocache; 95 96 // caching was on and {include} is not in nocache mode 97 if ($compiler->template->caching && !$compiler->nocache && !$compiler->tag_nocache) { 98 $_caching = self::CACHING_NOCACHE_CODE; 99 } 100 101 // flag if included template code should be merged into caller 102 $merge_compiled_includes = ($compiler->smarty->merge_compiled_includes || ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) || $_attr['inline'] === true) && !$compiler->template->source->recompiled; 103 104 if ($merge_compiled_includes && $_attr['inline'] !== true) { 105 // variable template name ? 106 if ($compiler->has_variable_string || !((substr_count($include_file, '"') == 2 || substr_count($include_file, "'") == 2)) || substr_count($include_file, '(') != 0 || substr_count($include_file, '$_smarty_tpl->') != 0) { 107 $merge_compiled_includes = false; 108 if ($compiler->template->caching) { 109 // must use individual cache file 110 //$_attr['caching'] = 1; 111 } 112 if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes && $_attr['inline'] !== true) { 113 $compiler->trigger_template_error(' variable template file names not allow within {block} tags'); 114 } 115 } 116 // variable compile_id? 117 if (isset($_attr['compile_id'])) { 118 if (!((substr_count($_attr['compile_id'], '"') == 2 || substr_count($_attr['compile_id'], "'") == 2 || is_numeric($_attr['compile_id']))) || substr_count($_attr['compile_id'], '(') != 0 || substr_count($_attr['compile_id'], '$_smarty_tpl->') != 0) { 119 $merge_compiled_includes = false; 120 if ($compiler->template->caching) { 121 // must use individual cache file 122 //$_attr['caching'] = 1; 123 } 124 if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes && $_attr['inline'] !== true) { 125 $compiler->trigger_template_error(' variable compile_id not allow within {block} tags'); 126 } 127 } 128 } 129 } 130 131 /* 132 * if the {include} tag provides individual parameter for caching or compile_id 133 * the subtemplate must not be included into the common cache file and is treated like 134 * a call in nocache mode. 135 * 136 */ 137 if ($_attr['nocache'] !== true && $_attr['caching']) { 138 $_caching = $_new_caching = (int) $_attr['caching']; 139 $call_nocache = true; 140 } else { 141 $_new_caching = Smarty::CACHING_LIFETIME_CURRENT; 142 } 143 if (isset($_attr['cache_lifetime'])) { 144 $_cache_lifetime = $_attr['cache_lifetime']; 145 $call_nocache = true; 146 $_caching = $_new_caching; 147 } else { 148 $_cache_lifetime = '$_smarty_tpl->cache_lifetime'; 149 } 150 if (isset($_attr['cache_id'])) { 151 $_cache_id = $_attr['cache_id']; 152 $call_nocache = true; 153 $_caching = $_new_caching; 154 } else { 155 $_cache_id = '$_smarty_tpl->cache_id'; 156 } 157 if (isset($_attr['compile_id'])) { 158 $_compile_id = $_attr['compile_id']; 159 } else { 160 $_compile_id = '$_smarty_tpl->compile_id'; 161 } 162 163 // if subtemplate will be called in nocache mode do not merge 164 if ($compiler->template->caching && $call_nocache) { 165 $merge_compiled_includes = false; 166 } 167 168 $has_compiled_template = false; 169 if ($merge_compiled_includes) { 170 if ($compiler->template->caching && ($compiler->tag_nocache || $compiler->nocache) && $_caching != self::CACHING_NOCACHE_CODE) { 171 // $merge_compiled_includes = false; 172 if ($compiler->inheritance && $compiler->smarty->inheritance_merge_compiled_includes) { 173 $compiler->trigger_template_error(' invalid caching mode of subtemplate within {block} tags'); 174 } 175 } 176 $c_id = isset($_attr['compile_id']) ? $_attr['compile_id'] : $compiler->template->compile_id; 177 // we must observe different compile_id and caching 178 $uid = sha1($c_id . ($_caching ? '--caching' : '--nocaching')); 179 $tpl_name = null; 180 181 /** @var Smarty_Internal_Template $_smarty_tpl 182 * used in evaluated code 183 */ 184 $_smarty_tpl = $compiler->template; 185 eval("\$tpl_name = $include_file;"); 186 if (!isset($compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid])) { 187 $compiler->smarty->allow_ambiguous_resources = true; 188 $tpl = new $compiler->smarty->template_class ($tpl_name, $compiler->smarty, $compiler->template, $compiler->template->cache_id, $c_id, $_caching); 189 // save unique function name 190 $compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func'] = $tpl->properties['unifunc'] = 'content_' . str_replace(array('.', ','), '_', uniqid('', true)); 191 if ($compiler->inheritance) { 192 $tpl->compiler->inheritance = true; 193 } 194 // make sure whole chain gets compiled 195 $tpl->mustCompile = true; 196 if (!($tpl->source->uncompiled) && $tpl->source->exists) { 197 $tpl->compiler->suppressTemplatePropertyHeader = true; 198 $compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['nocache_hash'] = $tpl->properties['nocache_hash'] = str_replace(array('.', ','), '_', uniqid(rand(), true)); 199 // get compiled code 200 $compiled_code = Smarty_Internal_Extension_CodeFrame::createFunctionFrame($tpl, $tpl->compiler->compileTemplate($tpl, null, $compiler->parent_compiler)); 201 unset($tpl->compiler); 202 203 // remove header code 204 $compiled_code = preg_replace("/(<\?php \/\*%%SmartyHeaderCode:{$tpl->properties['nocache_hash']}%%\*\/(.+?)\/\*\/%%SmartyHeaderCode%%\*\/\?>\n)/s", '', $compiled_code); 205 if ($tpl->has_nocache_code) { 206 // replace nocache_hash 207 $compiled_code = str_replace("{$tpl->properties['nocache_hash']}", $compiler->template->properties['nocache_hash'], $compiled_code); 208 $compiler->template->has_nocache_code = true; 209 } 210 $compiler->parent_compiler->mergedSubTemplatesCode[$tpl->properties['unifunc']] = $compiled_code; 211 $has_compiled_template = true; 212 if (!empty($tpl->required_plugins['compiled'])) { 213 foreach ($tpl->required_plugins['compiled'] as $name => $callBack) { 214 if (!isset($compiler->template->required_plugins['compiled'][$name])) { 215 $compiler->template->required_plugins['compiled'][$name] = $callBack; 216 } 217 } 218 } 219 if (!empty($tpl->required_plugins['nocache'])) { 220 foreach ($tpl->required_plugins['nocache'] as $name => $callBack) { 221 if (!isset($compiler->template->required_plugins['nocache'][$name])) { 222 $compiler->template->required_plugins['nocache'][$name] = $callBack; 223 } 224 } 225 } 226 unset ($tpl); 227 } 228 } else { 229 $has_compiled_template = true; 230 } 231 } 232 // delete {include} standard attributes 233 unset($_attr['file'], $_attr['assign'], $_attr['cache_id'], $_attr['compile_id'], $_attr['cache_lifetime'], $_attr['nocache'], $_attr['caching'], $_attr['scope'], $_attr['inline']); 234 // remaining attributes must be assigned as smarty variable 235 $_vars_nc = ''; 236 if (!empty($_attr)) { 237 if ($_parent_scope == Smarty::SCOPE_LOCAL) { 238 $_pairs = array(); 239 // create variables 240 foreach ($_attr as $key => $value) { 241 $_pairs[] = "'$key'=>$value"; 242 $_vars_nc .= "\$_smarty_tpl->tpl_vars['$key'] = new Smarty_Variable($value);\n"; 243 } 244 $_vars = 'array(' . join(',', $_pairs) . ')'; 245 } else { 246 $compiler->trigger_template_error('variable passing not allowed in parent/global scope', $compiler->lex->taglineno); 247 } 248 } else { 249 $_vars = 'array()'; 250 } 251 $update_compile_id = $compiler->template->caching && !$compiler->tag_nocache && !$compiler->nocache && $_compile_id != '$_smarty_tpl->compile_id'; 252 if ($has_compiled_template && !$call_nocache) { 253 // if ($has_compiled_template && !$compiler->tag_nocache && !$compiler->nocache) { 254 // never call inline templates in nocache mode 255 //$compiler->suppressNocacheProcessing = true; 256 $_hash = $compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['nocache_hash']; 257 $_output = "<?php /* Call merged included template \"" . $tpl_name . "\" */\n"; 258 if ($update_compile_id) { 259 $_output .= $compiler->makeNocacheCode("\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n"); 260 } 261 if (!empty($_vars_nc) && $_caching == 9999 && $_smarty_tpl->caching) { 262 //$compiler->suppressNocacheProcessing = false; 263 $_output .= substr($compiler->processNocacheCode('<?php ' . $_vars_nc . "?>\n", true), 6, - 3); 264 //$compiler->suppressNocacheProcessing = true; 265 } 266 if (isset($_assign)) { 267 $_output .= " \$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(\$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, '{$_hash}', '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}'));\n"; 268 } else { 269 $_output .= "echo \$_smarty_tpl->getInlineSubTemplate({$include_file}, {$_cache_id}, {$_compile_id}, {$_caching}, {$_cache_lifetime}, {$_vars}, {$_parent_scope}, '{$_hash}', '{$compiler->parent_compiler->mergedSubTemplatesData[$tpl_name][$uid]['func']}');\n"; 270 } 271 if ($update_compile_id) { 272 $_output .= $compiler->makeNocacheCode("\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"); 273 } 274 $_output .= "/* End of included template \"" . $tpl_name . "\" */?>\n"; 275 276 return $_output; 277 } 278 279 if ($call_nocache) { 280 $compiler->tag_nocache = true; 281 } 282 $_output = "<?php "; 283 if ($update_compile_id) { 284 $_output .= "\$_compile_id_save[] = \$_smarty_tpl->compile_id;\n\$_smarty_tpl->compile_id = {$_compile_id};\n"; 285 } 286 // was there an assign attribute 287 if (isset($_assign)) { 288 $_output .= "\$_smarty_tpl->tpl_vars[$_assign] = new Smarty_Variable(\$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope));\n"; 289 } else { 290 $_output .= "echo \$_smarty_tpl->getSubTemplate ($include_file, $_cache_id, $_compile_id, $_caching, $_cache_lifetime, $_vars, $_parent_scope);\n"; 291 } 292 if ($update_compile_id) { 293 $_output .= "\$_smarty_tpl->compile_id = array_pop(\$_compile_id_save);\n"; 294 } 295 $_output .= "?>\n"; 296 return $_output; 297 } 298 }