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