Commit | Line | Data |
---|---|---|
2aa91ff2 S |
1 | <?php |
2 | /** | |
3 | * Smarty Internal Plugin Debug | |
ccd27f54 | 4 | * Class to collect data for the Smarty Debugging Console |
2aa91ff2 S |
5 | * |
6 | * @package Smarty | |
7 | * @subpackage Debug | |
8 | * @author Uwe Tews | |
9 | */ | |
10 | ||
11 | /** | |
12 | * Smarty Internal Plugin Debug Class | |
13 | * | |
14 | * @package Smarty | |
15 | * @subpackage Debug | |
16 | */ | |
17 | class Smarty_Internal_Debug extends Smarty_Internal_Data | |
18 | { | |
19 | /** | |
20 | * template data | |
21 | * | |
22 | * @var array | |
23 | */ | |
24 | public static $template_data = array(); | |
25 | ||
26 | /** | |
27 | * List of uid's which shall be ignored | |
28 | * | |
29 | * @var array | |
30 | */ | |
31 | public static $ignore_uid = array(); | |
32 | ||
33 | /** | |
ccd27f54 S |
34 | * Index of display() and fetch() calls |
35 | * | |
36 | * @var int | |
37 | */ | |
38 | public static $index = 0; | |
39 | ||
40 | /** | |
41 | * Counter for window offset | |
2aa91ff2 | 42 | * |
ccd27f54 | 43 | * @var int |
2aa91ff2 | 44 | */ |
ccd27f54 S |
45 | public static $offset = 0; |
46 | ||
47 | /** | |
48 | * Start logging template | |
49 | * | |
50 | * @param \Smarty_Internal_Template $template template | |
51 | * @param null $mode true: display false: fetch null: subtemolate | |
52 | */ | |
53 | public static function start_template(Smarty_Internal_Template $template, $mode = null) | |
2aa91ff2 | 54 | { |
ccd27f54 S |
55 | if (isset($mode)) { |
56 | self::$index ++; | |
57 | self::$offset ++; | |
58 | self::$template_data[self::$index] = null; | |
2aa91ff2 | 59 | } |
ccd27f54 S |
60 | $key = self::get_key($template); |
61 | self::$template_data[self::$index][$key]['start_template_time'] = microtime(true); | |
62 | } | |
63 | ||
64 | /** | |
65 | * End logging of cache time | |
66 | * | |
67 | * @param \Smarty_Internal_Template $template cached template | |
68 | */ | |
69 | public static function end_template(Smarty_Internal_Template $template) | |
70 | { | |
71 | $key = self::get_key($template); | |
72 | self::$template_data[self::$index][$key]['total_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_template_time']; | |
73 | self::$template_data[self::$index][$key]['properties'] = $template->properties; | |
2aa91ff2 S |
74 | } |
75 | ||
76 | /** | |
77 | * Start logging of compile time | |
78 | * | |
ccd27f54 | 79 | * @param \Smarty_Internal_Template $template |
2aa91ff2 | 80 | */ |
ccd27f54 | 81 | public static function start_compile(Smarty_Internal_Template $template) |
2aa91ff2 S |
82 | { |
83 | static $_is_stringy = array('string' => true, 'eval' => true); | |
84 | if (!empty($template->compiler->trace_uid)) { | |
85 | $key = $template->compiler->trace_uid; | |
ccd27f54 | 86 | if (!isset(self::$template_data[self::$index][$key])) { |
2aa91ff2 | 87 | if (isset($_is_stringy[$template->source->type])) { |
ccd27f54 | 88 | self::$template_data[self::$index][$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\''; |
2aa91ff2 | 89 | } else { |
ccd27f54 | 90 | self::$template_data[self::$index][$key]['name'] = $template->source->filepath; |
2aa91ff2 | 91 | } |
ccd27f54 S |
92 | self::$template_data[self::$index][$key]['compile_time'] = 0; |
93 | self::$template_data[self::$index][$key]['render_time'] = 0; | |
94 | self::$template_data[self::$index][$key]['cache_time'] = 0; | |
2aa91ff2 S |
95 | } |
96 | } else { | |
97 | if (isset(self::$ignore_uid[$template->source->uid])) { | |
98 | return; | |
99 | } | |
100 | $key = self::get_key($template); | |
101 | } | |
ccd27f54 | 102 | self::$template_data[self::$index][$key]['start_time'] = microtime(true); |
2aa91ff2 S |
103 | } |
104 | ||
105 | /** | |
106 | * End logging of compile time | |
107 | * | |
ccd27f54 | 108 | * @param \Smarty_Internal_Template $template |
2aa91ff2 | 109 | */ |
ccd27f54 | 110 | public static function end_compile(Smarty_Internal_Template $template) |
2aa91ff2 S |
111 | { |
112 | if (!empty($template->compiler->trace_uid)) { | |
113 | $key = $template->compiler->trace_uid; | |
114 | } else { | |
115 | if (isset(self::$ignore_uid[$template->source->uid])) { | |
116 | return; | |
117 | } | |
118 | ||
119 | $key = self::get_key($template); | |
120 | } | |
ccd27f54 | 121 | self::$template_data[self::$index][$key]['compile_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_time']; |
2aa91ff2 S |
122 | } |
123 | ||
124 | /** | |
125 | * Start logging of render time | |
126 | * | |
ccd27f54 | 127 | * @param \Smarty_Internal_Template $template |
2aa91ff2 | 128 | */ |
ccd27f54 | 129 | public static function start_render(Smarty_Internal_Template $template) |
2aa91ff2 S |
130 | { |
131 | $key = self::get_key($template); | |
ccd27f54 | 132 | self::$template_data[self::$index][$key]['start_time'] = microtime(true); |
2aa91ff2 S |
133 | } |
134 | ||
135 | /** | |
136 | * End logging of compile time | |
137 | * | |
ccd27f54 | 138 | * @param \Smarty_Internal_Template $template |
2aa91ff2 | 139 | */ |
ccd27f54 | 140 | public static function end_render(Smarty_Internal_Template $template) |
2aa91ff2 S |
141 | { |
142 | $key = self::get_key($template); | |
ccd27f54 | 143 | self::$template_data[self::$index][$key]['render_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_time']; |
2aa91ff2 S |
144 | } |
145 | ||
146 | /** | |
147 | * Start logging of cache time | |
148 | * | |
ccd27f54 | 149 | * @param \Smarty_Internal_Template $template cached template |
2aa91ff2 | 150 | */ |
ccd27f54 | 151 | public static function start_cache(Smarty_Internal_Template $template) |
2aa91ff2 S |
152 | { |
153 | $key = self::get_key($template); | |
ccd27f54 | 154 | self::$template_data[self::$index][$key]['start_time'] = microtime(true); |
2aa91ff2 S |
155 | } |
156 | ||
157 | /** | |
158 | * End logging of cache time | |
159 | * | |
cd8826ea | 160 | * @param \Smarty_Internal_Template $template cached template |
2aa91ff2 | 161 | */ |
ccd27f54 | 162 | public static function end_cache(Smarty_Internal_Template $template) |
2aa91ff2 S |
163 | { |
164 | $key = self::get_key($template); | |
ccd27f54 S |
165 | self::$template_data[self::$index][$key]['cache_time'] += microtime(true) - self::$template_data[self::$index][$key]['start_time']; |
166 | } | |
167 | ||
168 | /** | |
169 | * Register template object | |
170 | * | |
171 | * @param \Smarty_Internal_Template $template cached template | |
172 | */ | |
173 | public static function register_template(Smarty_Internal_Template $template) | |
174 | { | |
2aa91ff2 S |
175 | } |
176 | ||
177 | /** | |
ccd27f54 S |
178 | * Register data object |
179 | * | |
180 | * @param \Smarty_Data $data data object | |
181 | */ | |
182 | public static function register_data(Smarty_Data $data) | |
183 | { | |
184 | } | |
185 | ||
186 | /** | |
187 | * Opens a window for the Smarty Debugging Console and display the data | |
2aa91ff2 S |
188 | * |
189 | * @param Smarty_Internal_Template|Smarty $obj object to debug | |
ccd27f54 | 190 | * @param bool $full |
2aa91ff2 | 191 | */ |
ccd27f54 | 192 | public static function display_debug($obj, $full = false) |
2aa91ff2 | 193 | { |
ccd27f54 S |
194 | if (!$full) { |
195 | self::$offset ++; | |
196 | $savedIndex = self::$index; | |
197 | self::$index = 9999; | |
198 | } | |
2aa91ff2 | 199 | if ($obj instanceof Smarty) { |
cd8826ea | 200 | $smarty = $obj; |
2aa91ff2 | 201 | } else { |
cd8826ea | 202 | $smarty = $obj->smarty; |
2aa91ff2 | 203 | } |
cd8826ea S |
204 | // create fresh instance of smarty for displaying the debug console |
205 | // to avoid problems if the application did overload the Smarty class | |
206 | $debObj = new Smarty(); | |
207 | // copy the working dirs from application | |
208 | $debObj->setCompileDir($smarty->getCompileDir()); | |
209 | // init properties by hand as user may have edited the original Smarty class | |
210 | $debObj->setPluginsDir(is_dir(__DIR__ . '/../plugins') ? __DIR__ . '/../plugins' : $smarty->getPluginsDir()); | |
211 | $debObj->force_compile = false; | |
212 | $debObj->compile_check = true; | |
213 | $debObj->left_delimiter = '{'; | |
214 | $debObj->right_delimiter = '}'; | |
215 | $debObj->security_policy = null; | |
216 | $debObj->debugging = false; | |
217 | $debObj->debugging_ctrl = 'NONE'; | |
218 | $debObj->error_reporting = E_ALL & ~E_NOTICE; | |
219 | $debObj->debug_tpl = isset($smarty->debug_tpl) ? $smarty->debug_tpl : 'file:' . __DIR__ . '/../debug.tpl'; | |
220 | $debObj->registered_plugins = array(); | |
221 | $debObj->registered_resources = array(); | |
222 | $debObj->registered_filters = array(); | |
223 | $debObj->autoload_filters = array(); | |
224 | $debObj->default_modifiers = array(); | |
225 | $debObj->escape_html = true; | |
226 | $debObj->caching = false; | |
227 | $debObj->compile_id = null; | |
228 | $debObj->cache_id = null; | |
229 | // prepare information of assigned variables | |
230 | $ptr = self::get_debug_vars($obj); | |
2aa91ff2 S |
231 | $_assigned_vars = $ptr->tpl_vars; |
232 | ksort($_assigned_vars); | |
233 | $_config_vars = $ptr->config_vars; | |
234 | ksort($_config_vars); | |
cd8826ea S |
235 | $debugging = $smarty->debugging; |
236 | ||
237 | $_template = new Smarty_Internal_Template($debObj->debug_tpl, $debObj); | |
2aa91ff2 S |
238 | if ($obj instanceof Smarty_Internal_Template) { |
239 | $_template->assign('template_name', $obj->source->type . ':' . $obj->source->name); | |
240 | } | |
ccd27f54 S |
241 | if ($obj instanceof Smarty || $full) { |
242 | $_template->assign('template_data', self::$template_data[self::$index]); | |
2aa91ff2 S |
243 | } else { |
244 | $_template->assign('template_data', null); | |
245 | } | |
246 | $_template->assign('assigned_vars', $_assigned_vars); | |
247 | $_template->assign('config_vars', $_config_vars); | |
248 | $_template->assign('execution_time', microtime(true) - $smarty->start_time); | |
ccd27f54 S |
249 | $_template->assign('display_mode', $debugging == 2 || !$full); |
250 | $_template->assign('offset', self::$offset * 50); | |
2aa91ff2 | 251 | echo $_template->fetch(); |
ccd27f54 S |
252 | if (isset($full)) { |
253 | self::$index --; | |
254 | } | |
255 | if (!$full) { | |
256 | self::$index = $savedIndex; | |
257 | } | |
2aa91ff2 S |
258 | } |
259 | ||
260 | /** | |
261 | * Recursively gets variables from all template/data scopes | |
262 | * | |
263 | * @param Smarty_Internal_Template|Smarty_Data $obj object to debug | |
264 | * | |
265 | * @return StdClass | |
266 | */ | |
267 | public static function get_debug_vars($obj) | |
268 | { | |
ccd27f54 S |
269 | $config_vars = array(); |
270 | foreach ($obj->config_vars as $key => $var) { | |
271 | $config_vars[$key]['value'] = $var; | |
272 | if ($obj instanceof Smarty_Internal_Template) { | |
273 | $config_vars[$key]['scope'] = $obj->source->type . ':' . $obj->source->name; | |
274 | } elseif ($obj instanceof Smarty_Data) { | |
275 | $tpl_vars[$key]['scope'] = $obj->dataObjectName; | |
276 | } else { | |
277 | $config_vars[$key]['scope'] = 'Smarty object'; | |
278 | } | |
279 | } | |
2aa91ff2 S |
280 | $tpl_vars = array(); |
281 | foreach ($obj->tpl_vars as $key => $var) { | |
ccd27f54 S |
282 | foreach ($var as $varkey => $varvalue) { |
283 | if ($varkey == 'value') { | |
284 | $tpl_vars[$key][$varkey] = $varvalue; | |
285 | } else { | |
286 | if ($varkey == 'nocache') { | |
287 | if ($varvalue == true) { | |
288 | $tpl_vars[$key][$varkey] = $varvalue; | |
289 | } | |
290 | } else { | |
291 | if ($varkey != 'scope' || $varvalue !== 0) { | |
292 | $tpl_vars[$key]['attributes'][$varkey] = $varvalue; | |
293 | } | |
294 | } | |
295 | } | |
296 | } | |
2aa91ff2 | 297 | if ($obj instanceof Smarty_Internal_Template) { |
ccd27f54 | 298 | $tpl_vars[$key]['scope'] = $obj->source->type . ':' . $obj->source->name; |
2aa91ff2 | 299 | } elseif ($obj instanceof Smarty_Data) { |
ccd27f54 | 300 | $tpl_vars[$key]['scope'] = $obj->dataObjectName; |
2aa91ff2 | 301 | } else { |
ccd27f54 | 302 | $tpl_vars[$key]['scope'] = 'Smarty object'; |
2aa91ff2 S |
303 | } |
304 | } | |
305 | ||
306 | if (isset($obj->parent)) { | |
307 | $parent = self::get_debug_vars($obj->parent); | |
ccd27f54 S |
308 | foreach ($parent->tpl_vars as $name => $pvar) { |
309 | if (isset($tpl_vars[$name]) && $tpl_vars[$name]['value'] === $pvar['value']) { | |
310 | $tpl_vars[$name]['scope'] = $pvar['scope']; | |
311 | } | |
312 | } | |
2aa91ff2 | 313 | $tpl_vars = array_merge($parent->tpl_vars, $tpl_vars); |
ccd27f54 S |
314 | |
315 | foreach ($parent->config_vars as $name => $pvar) { | |
316 | if (isset($config_vars[$name]) && $config_vars[$name]['value'] === $pvar['value']) { | |
317 | $config_vars[$name]['scope'] = $pvar['scope']; | |
318 | } | |
319 | } | |
2aa91ff2 S |
320 | $config_vars = array_merge($parent->config_vars, $config_vars); |
321 | } else { | |
ccd27f54 S |
322 | foreach (Smarty::$global_tpl_vars as $key => $var) { |
323 | if (!array_key_exists($key, $tpl_vars)) { | |
324 | foreach ($var as $varkey => $varvalue) { | |
325 | if ($varkey == 'value') { | |
326 | $tpl_vars[$key][$varkey] = $varvalue; | |
327 | } else { | |
328 | if ($varkey == 'nocache') { | |
329 | if ($varvalue == true) { | |
330 | $tpl_vars[$key][$varkey] = $varvalue; | |
331 | } | |
332 | } else { | |
333 | if ($varkey != 'scope' || $varvalue !== 0) { | |
334 | $tpl_vars[$key]['attributes'][$varkey] = $varvalue; | |
335 | } | |
336 | } | |
337 | } | |
338 | } | |
339 | $tpl_vars[$key]['scope'] = 'Global'; | |
2aa91ff2 S |
340 | } |
341 | } | |
342 | } | |
343 | ||
344 | return (object) array('tpl_vars' => $tpl_vars, 'config_vars' => $config_vars); | |
345 | } | |
346 | ||
347 | /** | |
348 | * Return key into $template_data for template | |
349 | * | |
ccd27f54 | 350 | * @param \Smarty_Internal_Template $template template object |
2aa91ff2 S |
351 | * |
352 | * @return string key into $template_data | |
353 | */ | |
ccd27f54 | 354 | private static function get_key(Smarty_Internal_Template $template) |
2aa91ff2 S |
355 | { |
356 | static $_is_stringy = array('string' => true, 'eval' => true); | |
357 | // calculate Uid if not already done | |
358 | if ($template->source->uid == '') { | |
359 | $template->source->filepath; | |
360 | } | |
361 | $key = $template->source->uid; | |
ccd27f54 | 362 | if (isset(self::$template_data[self::$index][$key])) { |
2aa91ff2 S |
363 | return $key; |
364 | } else { | |
365 | if (isset($_is_stringy[$template->source->type])) { | |
ccd27f54 | 366 | self::$template_data[self::$index][$key]['name'] = '\'' . substr($template->source->name, 0, 25) . '...\''; |
2aa91ff2 | 367 | } else { |
ccd27f54 | 368 | self::$template_data[self::$index][$key]['name'] = $template->source->filepath; |
2aa91ff2 | 369 | } |
ccd27f54 S |
370 | self::$template_data[self::$index][$key]['compile_time'] = 0; |
371 | self::$template_data[self::$index][$key]['render_time'] = 0; | |
372 | self::$template_data[self::$index][$key]['cache_time'] = 0; | |
373 | self::$template_data[self::$index][$key]['total_time'] = 0; | |
2aa91ff2 S |
374 | |
375 | return $key; | |
376 | } | |
377 | } | |
ccd27f54 S |
378 | |
379 | /** | |
380 | * Ignore template | |
381 | * | |
382 | * @param \Smarty_Internal_Template $template | |
383 | */ | |
384 | public static function ignore(Smarty_Internal_Template $template) | |
385 | { | |
386 | // calculate Uid if not already done | |
387 | if ($template->source->uid == '') { | |
388 | $template->source->filepath; | |
389 | } | |
390 | self::$ignore_uid[$template->source->uid] = true; | |
391 | } | |
392 | ||
393 | /** | |
394 | * handle 'URL' debugging mode | |
395 | * | |
396 | * @param Smarty_Internal_Template $_template | |
397 | */ | |
398 | public static function debugUrl(Smarty_Internal_Template $_template) | |
399 | { | |
400 | if (isset($_SERVER['QUERY_STRING'])) { | |
401 | $_query_string = $_SERVER['QUERY_STRING']; | |
402 | } else { | |
403 | $_query_string = ''; | |
404 | } | |
405 | if (false !== strpos($_query_string, $_template->smarty->smarty_debug_id)) { | |
406 | if (false !== strpos($_query_string, $_template->smarty->smarty_debug_id . '=on')) { | |
407 | // enable debugging for this browser session | |
408 | setcookie('SMARTY_DEBUG', true); | |
409 | $_template->smarty->debugging = true; | |
410 | } elseif (false !== strpos($_query_string, $_template->smarty->smarty_debug_id . '=off')) { | |
411 | // disable debugging for this browser session | |
412 | setcookie('SMARTY_DEBUG', false); | |
413 | $_template->smarty->debugging = false; | |
414 | } else { | |
415 | // enable debugging for this page | |
416 | $_template->smarty->debugging = true; | |
417 | } | |
418 | } else { | |
419 | if (isset($_COOKIE['SMARTY_DEBUG'])) { | |
420 | $_template->smarty->debugging = true; | |
421 | } | |
422 | } | |
423 | } | |
2aa91ff2 | 424 | } |