smarty_internal_compile_function.php (11498B)
1 <?php 2 /** 3 * Smarty Internal Plugin Compile Function 4 * Compiles the {function} {/function} tags 5 * 6 * @package Smarty 7 * @subpackage Compiler 8 * @author Uwe Tews 9 */ 10 11 /** 12 * Smarty Internal Plugin Compile Function Class 13 * 14 * @package Smarty 15 * @subpackage Compiler 16 */ 17 class Smarty_Internal_Compile_Function extends Smarty_Internal_CompileBase 18 { 19 20 /** 21 * Attribute definition: Overwrites base class. 22 * 23 * @var array 24 * @see Smarty_Internal_CompileBase 25 */ 26 public $required_attributes = array('name'); 27 28 /** 29 * Attribute definition: Overwrites base class. 30 * 31 * @var array 32 * @see Smarty_Internal_CompileBase 33 */ 34 public $shorttag_order = array('name'); 35 36 /** 37 * Attribute definition: Overwrites base class. 38 * 39 * @var array 40 * @see Smarty_Internal_CompileBase 41 */ 42 public $optional_attributes = array('_any'); 43 44 /** 45 * Compiles code for the {function} tag 46 * 47 * @param array $args array with attributes from parser 48 * @param object $compiler compiler object 49 * @param array $parameter array with compilation parameter 50 * 51 * @return boolean true 52 */ 53 public function compile($args, $compiler, $parameter) 54 { 55 // check and get attributes 56 $_attr = $this->getAttributes($compiler, $args); 57 58 if ($_attr['nocache'] === true) { 59 $compiler->trigger_template_error('nocache option not allowed', $compiler->lex->taglineno); 60 } 61 unset($_attr['nocache']); 62 $_name = trim($_attr['name'], "'\""); 63 $compiler->parent_compiler->templateProperties['tpl_function'][$_name] = array(); 64 $save = array($_attr, $compiler->parser->current_buffer, $compiler->template->has_nocache_code, $compiler->template->required_plugins, $compiler->template->caching); 65 $this->openTag($compiler, 'function', $save); 66 // set flag that we are compiling a template function 67 $compiler->compiles_template_function = true; 68 // Init temporary context 69 $compiler->template->required_plugins = array('compiled' => array(), 'nocache' => array()); 70 $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template($compiler->parser); 71 $compiler->template->has_nocache_code = false; 72 $compiler->template->caching = true; 73 return true; 74 } 75 } 76 77 /** 78 * Smarty Internal Plugin Compile Functionclose Class 79 * 80 * @package Smarty 81 * @subpackage Compiler 82 */ 83 class Smarty_Internal_Compile_Functionclose extends Smarty_Internal_CompileBase 84 { 85 86 /** 87 * Compiler object 88 * 89 * @var object 90 */ 91 private $compiler = null; 92 93 /** 94 * Compiles code for the {/function} tag 95 * 96 * @param array $args array with attributes from parser 97 * @param object|\Smarty_Internal_TemplateCompilerBase $compiler compiler object 98 * @param array $parameter array with compilation parameter 99 * 100 * @return bool true 101 */ 102 public function compile($args, Smarty_Internal_TemplateCompilerBase $compiler, $parameter) 103 { 104 $this->compiler = $compiler; 105 $saved_data = $this->closeTag($compiler, array('function')); 106 $_attr = $saved_data[0]; 107 $_name = trim($_attr['name'], "'\""); 108 // reset flag that we are compiling a template function 109 $compiler->compiles_template_function = false; 110 $compiler->parent_compiler->templateProperties['tpl_function'][$_name]['called_functions'] = $compiler->called_functions; 111 $compiler->parent_compiler->templateProperties['tpl_function'][$_name]['compiled_filepath'] = $compiler->parent_compiler->template->compiled->filepath; 112 $compiler->parent_compiler->templateProperties['tpl_function'][$_name]['uid'] = $compiler->template->source->uid; 113 $compiler->called_functions = array(); 114 $_parameter = $_attr; 115 unset($_parameter['name']); 116 // default parameter 117 $_paramsArray = array(); 118 foreach ($_parameter as $_key => $_value) { 119 if (is_int($_key)) { 120 $_paramsArray[] = "$_key=>$_value"; 121 } else { 122 $_paramsArray[] = "'$_key'=>$_value"; 123 } 124 } 125 if (!empty($_paramsArray)) { 126 $_params = 'array(' . implode(",", $_paramsArray) . ')'; 127 $_paramsCode = "\$params = array_merge($_params, \$params);\n"; 128 } else { 129 $_paramsCode = ''; 130 } 131 $_functionCode = $compiler->parser->current_buffer; 132 // setup buffer for template function code 133 $compiler->parser->current_buffer = new Smarty_Internal_ParseTree_Template($compiler->parser); 134 135 $_funcName = "smarty_template_function_{$_name}_{$compiler->template->properties['nocache_hash']}"; 136 $_funcNameCaching = $_funcName . '_nocache'; 137 if ($compiler->template->has_nocache_code) { 138 $compiler->parent_compiler->templateProperties['tpl_function'][$_name]['call_name_caching'] = $_funcNameCaching; 139 $output = "<?php\n"; 140 $output .= "/* {$_funcNameCaching} */\n"; 141 $output .= "if (!function_exists('{$_funcNameCaching}')) {\n"; 142 $output .= "function {$_funcNameCaching} (\$_smarty_tpl,\$params) {\n"; 143 // build plugin include code 144 if (!empty($compiler->template->required_plugins['compiled'])) { 145 foreach ($compiler->template->required_plugins['compiled'] as $tmp) { 146 foreach ($tmp as $data) { 147 $output .= "if (!is_callable('{$data['function']}')) require_once '{$data['file']}';\n"; 148 } 149 } 150 } 151 if (!empty($compiler->template->required_plugins['nocache'])) { 152 $output .= "echo '/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php "; 153 foreach ($compiler->template->required_plugins['nocache'] as $tmp) { 154 foreach ($tmp as $data) { 155 $output .= "if (!is_callable(\'{$data['function']}\')) require_once \'{$data['file']}\';\n"; 156 } 157 } 158 $output .= "?>/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/';\n"; 159 } 160 $output .= "ob_start();\n"; 161 $output .= $_paramsCode; 162 $output .= "\$_smarty_tpl->properties['saved_tpl_vars'][] = \$_smarty_tpl->tpl_vars;\n"; 163 $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}"; 164 $output .= "\$params = var_export(\$params, true);\n"; 165 $output .= "echo \"/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php "; 166 $output .= "\\\$saved_tpl_vars = \\\$_smarty_tpl->tpl_vars;\nforeach (\$params as \\\$key => \\\$value) {\n\\\$_smarty_tpl->tpl_vars[\\\$key] = new Smarty_Variable(\\\$value);\n}\n?>"; 167 $output .= "/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/\n\";?>"; 168 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output)); 169 $compiler->parser->current_buffer->append_subtree($_functionCode); 170 $output = "<?php echo \"/*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/<?php "; 171 $output .= "foreach (Smarty::\\\$global_tpl_vars as \\\$key => \\\$value){\n"; 172 $output .= "if (\\\$_smarty_tpl->tpl_vars[\\\$key] === \\\$value) \\\$saved_tpl_vars[\\\$key] = \\\$value;\n}\n"; 173 $output .= "\\\$_smarty_tpl->tpl_vars = \\\$saved_tpl_vars;?>\n"; 174 $output .= "/*/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%*/\";\n?>"; 175 $output .= "<?php echo str_replace('{$compiler->template->properties['nocache_hash']}', \$_smarty_tpl->properties['nocache_hash'], ob_get_clean());\n"; 176 $output .= "\$_smarty_tpl->tpl_vars = array_pop(\$_smarty_tpl->properties['saved_tpl_vars']);\n}\n}\n"; 177 $output .= "/*/ {$_funcName}_nocache */\n\n"; 178 $output .= "?>\n"; 179 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output)); 180 $_functionCode = new Smarty_Internal_ParseTree_Tag($compiler->parser, preg_replace_callback("/((<\?php )?echo '\/\*%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%\*\/([\S\s]*?)\/\*\/%%SmartyNocache:{$compiler->template->properties['nocache_hash']}%%\*\/';(\?>\n)?)/", array($this, 'removeNocache'), $_functionCode->to_smarty_php())); 181 } 182 $compiler->parent_compiler->templateProperties['tpl_function'][$_name]['call_name'] = $_funcName; 183 $output = "<?php\n"; 184 $output .= "/* {$_funcName} */\n"; 185 $output .= "if (!function_exists('{$_funcName}')) {\n"; 186 $output .= "function {$_funcName}(\$_smarty_tpl,\$params) {\n"; 187 // build plugin include code 188 if (!empty($compiler->template->required_plugins['nocache'])) { 189 $compiler->template->required_plugins['compiled'] = array_merge($compiler->template->required_plugins['compiled'], $compiler->template->required_plugins['nocache']); 190 } 191 if (!empty($compiler->template->required_plugins['compiled'])) { 192 foreach ($compiler->template->required_plugins['compiled'] as $tmp) { 193 foreach ($tmp as $data) { 194 $output .= "if (!is_callable('{$data['function']}')) require_once '{$data['file']}';\n"; 195 } 196 } 197 } 198 $output .= "\$saved_tpl_vars = \$_smarty_tpl->tpl_vars;\n"; 199 $output .= $_paramsCode; 200 $output .= "foreach (\$params as \$key => \$value) {\n\$_smarty_tpl->tpl_vars[\$key] = new Smarty_Variable(\$value);\n}?>"; 201 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output)); 202 $compiler->parser->current_buffer->append_subtree($_functionCode); 203 $output = "<?php foreach (Smarty::\$global_tpl_vars as \$key => \$value){\n"; 204 $output .= "if (\$_smarty_tpl->tpl_vars[\$key] === \$value) \$saved_tpl_vars[\$key] = \$value;\n}\n"; 205 $output .= "\$_smarty_tpl->tpl_vars = \$saved_tpl_vars;\n}\n}\n"; 206 $output .= "/*/ {$_funcName} */\n\n"; 207 $output .= "?>\n"; 208 $compiler->parser->current_buffer->append_subtree(new Smarty_Internal_ParseTree_Tag($compiler->parser, $output)); 209 $compiler->parent_compiler->templateFunctionCode .= $compiler->parser->current_buffer->to_smarty_php(); 210 // restore old buffer 211 $compiler->parser->current_buffer = $saved_data[1]; 212 // restore old status 213 $compiler->template->has_nocache_code = $saved_data[2]; 214 $compiler->template->required_plugins = $saved_data[3]; 215 $compiler->template->caching = $saved_data[4]; 216 return true; 217 } 218 219 /** 220 * @param $match 221 * 222 * @return mixed 223 */ 224 function removeNocache($match) 225 { 226 $code = preg_replace("/((<\?php )?echo '\/\*%%SmartyNocache:{$this->compiler->template->properties['nocache_hash']}%%\*\/)|(\/\*\/%%SmartyNocache:{$this->compiler->template->properties['nocache_hash']}%%\*\/';(\?>\n)?)/", '', $match[0]); 227 $code = str_replace(array('\\\'', '\\\\\''), array('\'', '\\\''), $code); 228 return $code; 229 } 230 }