| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Implementation of hook_menu(). 5 */ 6 function devel_themer_menu() { 7 $items = array(); 8 9 $items['admin/settings/devel_themer'] = array( 10 'title' => 'Theme Developer', 11 'description' => 'Display or hide the textual template log', 12 'page callback' => 'drupal_get_form', 13 'page arguments' => array('devel_themer_admin_settings'), 14 'access arguments' => array('administer site configuration'), 15 'type' => MENU_NORMAL_ITEM, 16 ); 17 $items['devel_themer/variables'] = array( 18 'title' => 'Theme Development AJAX variables', 19 'page callback' => 'devel_themer_ajax_variables', 20 'access callback' => 'devel_themer_user_access', 21 'type' => MENU_CALLBACK, 22 ); 23 $items['devel/devel_themer'] = array( 24 'title callback' => 'devel_themer_set_menu_text', 25 'description' => 'Quickly enable or disable theme developer module.', 26 'page callback' => 'devel_themer_toggle', 27 'access arguments' => array('access devel information'), 28 'menu_name' => 'devel', 29 // Have a weight other than zero here, so that the item does not flip around 30 // position depending on the text of the link. Most of the other links are weight zero. 31 // The link can easily be moved to another position via admin -> menu 32 'weight' => 5, 33 ); 34 return $items; 35 } 36 37 /** 38 * Helper function to set the menu link text. 39 */ 40 function devel_themer_set_menu_text() { 41 return devel_themer_enabled() ? t('Disable Theme Developer') : t('Enable Theme Developer'); 42 } 43 44 /** 45 * Implementation of hook_menu_link_alter(). 46 * Flag this link as needing alter at display time. This is more robust than setting 47 * alter in hook_menu(). See devel_themer_translated_menu_link_alter(). 48 * 49 */ 50 function devel_themer_menu_link_alter(&$item, $menu) { 51 if ($item['link_path'] == 'devel/devel_themer') { 52 $item['options']['alter'] = TRUE; 53 } 54 } 55 56 /** 57 * Implementation of hook_translated_menu_item_alter(). 58 * Append dynamic querystring 'destination' to our own menu item. 59 * 60 */ 61 function devel_themer_translated_menu_link_alter(&$item) { 62 if ($item['href'] == 'devel/devel_themer') { 63 $item['localized_options']['query'] = drupal_get_destination(); 64 } 65 } 66 67 /** 68 * A menu callback used by popup to retrieve variables from cache for a recent page. 69 * 70 * @param $request_id 71 * A unique key that is sent to the browser in Drupal.Settings.devel_themer_request_id 72 * @param $call 73 * The theme call for which you wish to retrieve variables. 74 * @return string 75 * A chunk of HTML with the devel_print_object() rendering of the variables. 76 */ 77 function devel_themer_ajax_variables($request_id, $call) { 78 $file = file_directory_temp(). "/devel_themer_$request_id"; 79 if ($data = unserialize(file_get_contents($file))) { 80 $variables = $data[$call]['variables']; 81 if (has_krumo()) { 82 print krumo_ob($variables); 83 } 84 elseif ($data[$call]['type'] == 'func') { 85 print devel_print_object($variables, NULL, FALSE); 86 } 87 else { 88 print devel_print_object($variables, '$', FALSE); 89 } 90 } 91 else { 92 print 'Ajax variables file not found. -'. check_plain($file); 93 } 94 $GLOBALS['devel_shutdown'] = FALSE; 95 return; 96 } 97 98 /** 99 * Toggle the Devel Themer. 100 * This is called from the Devel menu link. 101 * 102 * @return void 103 */ 104 function devel_themer_toggle() { 105 if (devel_themer_enabled()) { 106 devel_themer_enabled(FALSE); 107 drupal_set_message(t('Devel Themer module is now disabled.')); 108 } 109 else { 110 devel_themer_enabled(TRUE); 111 drupal_set_message(t('Devel Themer module is now enabled. Tick the "themer info" box to display theme information.')); 112 } 113 drupal_goto(); 114 } 115 116 /** 117 * Set and/or return the status of Devel Themer. 118 * @param 119 * $enable - TRUE to enable the themer. 120 * FALSE to disable the themer. 121 * NULL to leave it unchanged. 122 * 123 * @return 124 * TRUE if themer is enabled, FALSE if not. 125 */ 126 function devel_themer_enabled($enable = NULL) { 127 if (!is_null($enable)) { 128 variable_set('devel_themer_enabled', (bool)$enable); 129 } 130 return variable_get('devel_themer_enabled', TRUE); 131 } 132 133 function devel_themer_admin_settings() { 134 $form['devel_themer_log'] = array('#type' => 'checkbox', 135 '#title' => t('Display theme log'), 136 '#default_value' => variable_get('devel_themer_log', FALSE), 137 '#description' => t('Display the list of theme templates and theme functions which could have been be used for a given page. The one that was actually used is bolded. This is the same data as the represented in the popup, but all calls are listed in chronological order and can alternately be sorted by time.'), 138 ); 139 return system_settings_form($form); 140 } 141 142 /** 143 * Implementation of hook_perm(). 144 */ 145 function devel_themer_perm() { 146 return array('access devel theme information'); 147 } 148 149 function devel_themer_init() { 150 if (devel_themer_enabled() && devel_themer_user_access()) { 151 $path = drupal_get_path('module', 'devel_themer'); 152 $path_to_devel = drupal_get_path('module', 'devel'); 153 // we inject our HTML after page has loaded we have to add this manually. 154 if (has_krumo()) { 155 drupal_add_js($path_to_devel. '/krumo/krumo.js'); 156 drupal_add_css($path_to_devel. '/krumo/skins/default/skin.css'); 157 } 158 drupal_add_css($path .'/devel_themer.css'); 159 drupal_add_js($path .'/devel_themer.js'); 160 161 // The order these last two are loaded is important. 162 if (module_exists('jquery_ui')) 163 { 164 jquery_ui_add('ui.core'); 165 // Early versions of jquery_ui still need ui.mouse included. 166 $jquery_version = explode(".",jquery_ui_get_version()); 167 if ($jquery_version[0] < 1 || ($jquery_version[0] == 1 && $jquery_version[1] < 5)) { 168 jquery_ui_add('ui.mouse'); 169 } 170 jquery_ui_add('ui.draggable'); 171 } 172 else 173 { 174 drupal_add_js($path_to_devel .'/ui.mouse.js'); 175 drupal_add_js($path_to_devel .'/ui.draggable.js'); 176 } 177 178 // This needs to happen after all the other CSS. 179 drupal_set_html_head('<!--[if IE]> 180 <link href="' . base_path() . $path .'/devel_themer_ie_fix.css" rel="stylesheet" type="text/css" media="screen" /> 181 <![endif]-->'); 182 devel_themer_popup(); 183 184 if (!devel_silent() && variable_get('devel_themer_log', FALSE)) { 185 register_shutdown_function('devel_themer_shutdown'); 186 } 187 } 188 } 189 190 function devel_themer_shutdown() { 191 print devel_themer_log(); 192 } 193 194 /** 195 * An implementation of hook_theme_registry_alter() 196 * Iterate over theme registry, injecting our catch function into every theme call, including template calls. 197 * The catch function logs theme calls and performs divine nastiness. 198 * 199 * @return void 200 **/ 201 function devel_themer_theme_registry_alter($theme_registry) { 202 foreach ($theme_registry as $hook => $data) { 203 if (isset($theme_registry[$hook]['function'])) { 204 // If the hook is a function, store it so it can be run after it has been intercepted. 205 // This does not apply to template calls. 206 $theme_registry[$hook]['devel_function_intercept'] = $theme_registry[$hook]['function']; 207 } 208 // Add our catch function to intercept functions as well as templates. 209 $theme_registry[$hook]['function'] = 'devel_themer_catch_function'; 210 } 211 } 212 213 /** 214 * Show all theme templates and functions that could have been used on this page. 215 **/ 216 function devel_themer_log() { 217 if (isset($GLOBALS['devel_theme_calls'])) { 218 foreach ($GLOBALS['devel_theme_calls'] as $counter => $call) { 219 // Sometimes $call is a string. Not sure why. 220 if (is_array($call)) { 221 $id = "devel_theme_log_link_$counter"; 222 $marker = "<div id=\"$id\" class=\"devel_theme_log_link\"></div>\n"; 223 224 $used = $call['used']; 225 if ($call['type'] == 'func') { 226 $name = $call['name']. '()'; 227 foreach ($call['candidates'] as $item) { 228 if ($item == $used) { 229 $items[] = "<strong>$used</strong>"; 230 } 231 else { 232 $items[] = $item; 233 } 234 } 235 } 236 else { 237 $name = $call['name']; 238 foreach ($call['candidates'] as $item) { 239 if ($item == basename($used)) { 240 $items[] = "<strong>$used</strong>"; 241 } 242 else { 243 $items[] = $item; 244 } 245 } 246 } 247 $rows[] = array($call['duration'], $marker. $name, implode(', ', $items)); 248 unset($items); 249 } 250 } 251 $header = array('Duration (ms)', 'Template/Function', "Candidate template files or function names"); 252 $output = theme('table', $header, $rows); 253 return $output; 254 } 255 } 256 257 // Would be nice if theme() broke this into separate function so we don't copy logic here. this one is better - has cache 258 function devel_themer_get_extension() { 259 global $theme_engine; 260 static $extension = NULL; 261 262 if (!$extension) { 263 $extension_function = $theme_engine .'_extension'; 264 if (function_exists($extension_function)) { 265 $extension = $extension_function(); 266 } 267 else { 268 $extension = '.tpl.php'; 269 } 270 } 271 return $extension; 272 } 273 274 /** 275 * Intercepts all theme calls (including templates), adds to template log, and dispatches to original theme function. 276 * This function gets injected into theme registry in devel_themer_theme_registry_alter(). 277 */ 278 function devel_themer_catch_function() { 279 $args = func_get_args(); 280 281 // Get the hook argument passed to theme() by stepping through the backtrace 282 // to the closest entry of theme() being called, and get its first argument. 283 $trace = debug_backtrace(); 284 foreach ($trace as $trace_entry) { 285 if ($trace_entry['function'] == 'theme') { 286 $hook = $trace_entry['args'][0]; 287 break; 288 } 289 } 290 array_unshift($args, $hook); 291 292 $counter = devel_counter(); 293 $timer_name = "thmr_$counter"; 294 timer_start($timer_name); 295 296 // The twin of theme(). All rendering done through here. 297 list($return, $meta) = call_user_func_array('devel_themer_theme_twin', $args); 298 $time = timer_stop($timer_name); 299 300 $skip_calls = array('hidden', 'form_element', 'placeholder'); 301 if (devel_themer_enabled() && !empty($return) && !is_array($return) && !is_object($return) && devel_themer_user_access()) { 302 list($prefix, $suffix) = devel_theme_call_marker($hook, $counter, 'func'); 303 $start_return = substr($return, 0, 31); 304 $start_prefix = substr($prefix, 0, 31); 305 306 if ($start_return != $start_prefix && !in_array($hook, $skip_calls) && empty($GLOBALS['devel_themer_stop'])) { 307 if ($hook == 'page') { 308 $GLOBALS['devel_theme_calls']['page_id'] = $counter; 309 // Stop logging theme calls after we see theme('page'). This prevents 310 // needless logging of devel module's query log, for example. Other modules may set this global as needed. 311 $GLOBALS['devel_themer_stop'] = TRUE; 312 } 313 else { 314 $output = variable_get('devel_themer_no_whitespace', FALSE) ? ($prefix . $return . $suffix) : ($prefix. "\n ". $return. $suffix. "\n"); 315 } 316 317 if ($meta['type'] == 'func') { 318 $name = $meta['used']; 319 $used = $meta['used']; 320 if (empty($meta['wildcards'])) { 321 $meta['wildcards'][$hook] = ''; 322 } 323 $candidates = devel_themer_ancestry(array_reverse(array_keys($meta['wildcards']))); 324 if (empty($meta['variables'])) { 325 $variables = array(); 326 } 327 } 328 else { 329 $name = $hook; 330 if (empty($suggestions)) { 331 array_unshift($meta['suggestions'], $meta['used']); 332 } 333 $candidates = array_reverse(array_map('devel_themer_append_extension', $meta['suggestions'])); 334 $used = $meta['template_file']; 335 } 336 337 $key = "thmr_$counter"; 338 // This variable gets sent to the browser in Drupal.settings. 339 $GLOBALS['devel_theme_calls'][$key] = array( 340 'name' => $name, 341 'type' => $meta['type'], 342 'duration' => $time['time'], 343 'used' => $used, 344 'candidates' => $candidates, 345 'preprocessors' => isset($meta['preprocessors']) ? $meta['preprocessors'] : array(), 346 ); 347 348 // This variable gets serialized and cached on the server. 349 $GLOBALS['devel_themer_server'][$key] = array( 350 'variables' => $meta['variables'], 351 'type' => $meta['type'], 352 ); 353 } 354 else { 355 $output = $return; 356 } 357 } 358 359 return isset($output) ? $output : $return; 360 } 361 362 function devel_themer_append_extension($string) { 363 return $string. devel_themer_get_extension(); 364 } 365 366 /** 367 * For given theme *function* call, return the ancestry of function names which could have handled the call. 368 * This mimics the way the theme registry is built. 369 * 370 * @param array 371 * A list of theme calls. 372 * @return array() 373 * An array of function names. 374 **/ 375 function devel_themer_ancestry($calls) { 376 global $theme, $theme_engine, $base_theme_info; 377 static $prefixes; 378 if (!isset($prefixes)) { 379 $prefixes[] = 'theme'; 380 if (isset($base_theme_info)) { 381 foreach ($base_theme_info as $base) { 382 $prefixes[] = $base->name; 383 } 384 } 385 $prefixes[] = $theme_engine; 386 $prefixes[] = $theme; 387 $prefixes = array_filter($prefixes); 388 } 389 390 foreach ($calls as $call) { 391 foreach ($prefixes as $prefix) { 392 $candidates[] = $prefix. '_'. $call; 393 } 394 } 395 return array_reverse($candidates); 396 } 397 398 /** 399 * An unfortunate copy/paste of theme(). This one is called by the devel_themer_catch_function() 400 * and processes all theme calls but gives us info about the candidates, timings, etc. Without this twin, 401 * it was impossible to capture calls to module owned templates (e.g. user_profile) and awkward to determine 402 * which template was finally called and how long it took. 403 * 404 * @return array 405 * A two element array. First element contains the HTML from the theme call. The second contains 406 * a metadata array about the call. 407 * 408 **/ 409 function devel_themer_theme_twin() { 410 $args = func_get_args(); 411 $hook = array_shift($args); 412 413 static $hooks = NULL; 414 if (!isset($hooks)) { 415 init_theme(); 416 $hooks = theme_get_registry(); 417 } 418 419 // Gather all possible wildcard functions. 420 $meta['wildcards'] = array(); 421 if (is_array($hook)) { 422 foreach ($hook as $candidate) { 423 $meta['wildcards'][$candidate] = FALSE; 424 if (isset($hooks[$candidate])) { 425 $meta['wildcards'][$candidate] = TRUE; 426 break; 427 } 428 } 429 $hook = $candidate; 430 } 431 432 // This should not be needed but some users are getting errors. See http://drupal.org/node/209929 433 if (!isset($hooks[$hook])) { 434 return array('', $meta); 435 } 436 437 $info = $hooks[$hook]; 438 $meta['hook'] = $hook; 439 $meta['path'] = $info['theme path']; 440 441 // Include a file if the theme function or preprocess function is held elsewhere. 442 if (!empty($info['include files'])) { 443 foreach ($info['include files'] as $include_file) { 444 include_once($include_file); 445 } 446 } 447 448 // Handle compatibility with theme_registry_alters to prevent failures. 449 if (!empty($info['file'])) { 450 static $included_files = array(); 451 $include_file = $info['file']; 452 if (!empty($info['path'])) { 453 $include_file = $info['path'] .'/'. $include_file; 454 } 455 456 if (empty($included_files[$include_file])) { 457 // Statically cache files we've already tried to include so we don't 458 // run unnecessary file_exists calls. 459 $included_files[$include_file] = TRUE; 460 if (file_exists('./'. $include_file)) { 461 include_once('./'. $include_file); 462 } 463 } 464 } 465 466 if (isset($info['devel_function_intercept'])) { 467 // The theme call is a function. 468 $output = call_user_func_array($info['devel_function_intercept'], $args); 469 $meta['type'] = 'func'; 470 $meta['used'] = $info['devel_function_intercept']; 471 // Try to populate the keys of $args with variable names. Works on PHP5+. 472 if (!empty($args) && class_exists('ReflectionFunction')) { 473 $reflect = new ReflectionFunction($info['devel_function_intercept']); 474 $params = $reflect->getParameters(); 475 for ($i=0; $i < count($args); $i++) { 476 // The implementation of the theme function may recieve less parameters than were passed to it. 477 if ($i < count($params)) { 478 $meta['variables'][$params[$i]->getName()] = $args[$i]; 479 } 480 else { 481 // @TODO: Consider informing theme developers of theme functions that accept less parameters 482 // than are passed to them. This could be disabled by default, with an option to 483 // enable at admin/settings/devel_themer. Given this is a theme developer module 484 // used by implementors of theme override functions, it would probably be a useful 485 // default feature. 486 $meta['variables'][] = $args[$i]; 487 } 488 } 489 } 490 else { 491 $meta['variables'] = $args; 492 } 493 } 494 else { 495 // The theme call is a template. 496 $meta['type'] = 'tpl'; 497 $meta['used'] = str_replace($info['theme path'] .'/', '', $info['template']); 498 $variables = array( 499 'template_files' => array() 500 ); 501 if (!empty($info['arguments'])) { 502 $count = 0; 503 foreach ($info['arguments'] as $name => $default) { 504 $variables[$name] = isset($args[$count]) ? $args[$count] : $default; 505 $count++; 506 } 507 } 508 509 // default render function and extension. 510 $render_function = 'theme_render_template'; 511 $extension = '.tpl.php'; 512 513 // Run through the theme engine variables, if necessary 514 global $theme_engine; 515 if (isset($theme_engine)) { 516 // If theme or theme engine is implementing this, it may have 517 // a different extension and a different renderer. 518 if ($info['type'] != 'module') { 519 if (function_exists($theme_engine .'_render_template')) { 520 $render_function = $theme_engine .'_render_template'; 521 } 522 $extension_function = $theme_engine .'_extension'; 523 if (function_exists($extension_function)) { 524 $extension = $extension_function(); 525 } 526 } 527 } 528 529 if (isset($info['preprocess functions']) && is_array($info['preprocess functions'])) { 530 // This construct ensures that we can keep a reference through 531 // call_user_func_array. 532 $args = array(&$variables, $hook); 533 foreach ($info['preprocess functions'] as $preprocess_function) { 534 if (function_exists($preprocess_function)) { 535 call_user_func_array($preprocess_function, $args); 536 } 537 } 538 } 539 540 // Get suggestions for alternate templates out of the variables 541 // that were set. This lets us dynamically choose a template 542 // from a list. The order is FILO, so this array is ordered from 543 // least appropriate first to most appropriate last. 544 $suggestions = array(); 545 546 if (isset($variables['template_files'])) { 547 $suggestions = $variables['template_files']; 548 } 549 if (isset($variables['template_file'])) { 550 $suggestions[] = $variables['template_file']; 551 } 552 553 if ($suggestions) { 554 $template_file = drupal_discover_template($info['theme paths'], $suggestions, $extension); 555 } 556 557 if (empty($template_file)) { 558 $template_file = $info['template'] . $extension; 559 if (isset($info['path'])) { 560 $template_file = $info['path'] .'/'. $template_file; 561 } 562 } 563 $output = $render_function($template_file, $variables); 564 $meta['suggestions'] = $suggestions; 565 $meta['template_file'] = $template_file; 566 $meta['variables'] = $variables; 567 $meta['preprocessors'] = $info['preprocess functions']; 568 } 569 570 return array($output, $meta); 571 } 572 573 // We save the huge js array here instead of hook_footer so we can catch theme('page') 574 function devel_themer_exit($destination = NULL) { 575 if (!isset($destination) && !empty($GLOBALS['devel_theme_calls']) && $_SERVER['REQUEST_METHOD'] != 'POST') { 576 // A random string that is sent to the browser. It enables the popup to retrieve params/variables from this request. 577 $request_id = uniqid(rand()); 578 // Write the variables information to the a file. It will be retrieved on demand via AJAX. 579 // We used to write this to DB but was getting 'Warning: Got a packet bigger than 'max_allowed_packet' bytes' 580 // Writing to temp dir means we don't worry about folder existence/perms and cleanup is free. 581 devel_put_contents(file_directory_temp(). "/devel_themer_$request_id", serialize($GLOBALS['devel_themer_server'])); 582 583 $GLOBALS['devel_theme_calls']['request_id'] = $request_id; 584 $GLOBALS['devel_theme_calls']['devel_themer_uri'] = url("devel_themer/variables/$request_id"); 585 print '<script type="text/javascript">jQuery.extend(Drupal.settings, '. drupal_to_js($GLOBALS['devel_theme_calls']) .");</script>\n"; 586 } 587 } 588 589 function devel_theme_call_marker($name, $counter, $type) { 590 $id = "thmr_". $counter; 591 return array("<span id=\"$id\" class=\"thmr_call\">", "</span>\n"); 592 } 593 594 // just hand out next counter, or return current value 595 function devel_counter($increment = TRUE) { 596 static $counter = 0; 597 if ($increment) { 598 $counter++; 599 } 600 return $counter; 601 } 602 603 /** 604 * Return the popup template 605 * placed here for easy editing 606 */ 607 function devel_themer_popup() { 608 $majorver = substr(VERSION, 0, strpos(VERSION, '.')); 609 610 // add translatable strings 611 drupal_add_js(array('thmrStrings' => 612 array( 613 'themer_info' => t('Themer info'), 614 'toggle_throbber' => ' <img src="'. base_path() . drupal_get_path('module', 'devel'). '/loader-little.gif' .'" alt="'. t('loading') .'" class="throbber" width="16" height="16" style="display:none" />', 615 'parents' => t('Parents: '), 616 'function_called' => t('Function called: '), 617 'template_called' => t('Theme hook called: '), 618 'candidate_files' => t('Candidate template files: '), 619 'preprocessors' => t('Preprocess functions: '), 620 'candidate_functions' => t('Candidate function names: '), 621 'drupal_api_docs' => t('link to Drupal API documentation'), 622 'source_link_title' => t('link to source code'), 623 'function_arguments' => t('Function Arguments'), 624 'template_variables' => t('Template Variables'), 625 'file_used' => t('File used: '), 626 'duration' => t('Duration: '), 627 'api_site' => variable_get('devel_api_site', 'http://api.drupal.org/'), 628 'drupal_version' => $majorver, 629 'source_link' => url('devel/source', array('query' => array('file' => ''))), 630 )) 631 , 'setting'); 632 633 $title = t('Drupal Themer Information'); 634 $intro = t('Click on any element to see information about the Drupal theme function or template that created it.'); 635 636 $popup = <<<EOT 637 <div id="themer-fixeder"> 638 <div id="themer-relativer"> 639 <div id="themer-popup"> 640 <div class="topper"> 641 <span class="close">X</span> $title 642 </div> 643 <div id="parents" class="row"> 644 645 </div> 646 <div class="info row"> 647 <div class="starter">$intro</div> 648 <dl> 649 <dt class="key-type"> 650 651 </dt> 652 <dd class="key"> 653 654 </dd> 655 <div class="used"> 656 </div> 657 <dt class="candidates-type"> 658 659 </dt> 660 <dd class="candidates"> 661 662 </dd> 663 664 <dt class="preprocessors-type"> 665 666 </dt> 667 <dd class="preprocessors"> 668 669 </dd> 670 671 <div class="duration"></div> 672 </dl> 673 </div><!-- /info --> 674 <div class="attributes row"> 675 676 </div><!-- /attributes --> 677 </div><!-- /themer-popup --> 678 </div> 679 </div> 680 EOT; 681 682 drupal_add_js(array('thmr_popup' => $popup), 'setting'); 683 } 684 685 // Temporary - for D6 only since we support PHP4 686 function devel_put_contents($n, $d, $flag = false) { 687 if (function_exists('file_put_contents')){ 688 file_put_contents($n, $d, $flag); 689 } else { 690 $mode = ($flag == FILE_APPEND || strtoupper($flag) == 'FILE_APPEND') ? 'a' : 'w'; 691 $f = @fopen($n, $mode); 692 if ($f === false) { 693 return 0; 694 } else { 695 if (is_array($d)) $d = implode($d); 696 fwrite($f, $d); 697 fclose($f); 698 } 699 } 700 } 701 702 /** 703 * Clean up the files we dropped in the temp dir in devel_themer_exit(). 704 * 705 * Limitation: one more devel_themer_exit() will run after this function is 706 * called and drop one more file, since hook_exit() is called after the normal 707 * page cycle. 708 * 709 * @return 710 * void. 711 */ 712 function devel_themer_cleanup() { 713 foreach (array_keys(file_scan_directory(file_directory_temp(), 'devel_themer_*', array('.', '..', 'CVS'), 0, FALSE)) as $file) { 714 file_delete($file); 715 } 716 } 717 718 /** 719 * Implement hook_cron() for periodic cleanup. 720 * 721 * @return 722 * void. 723 */ 724 function devel_themer_cron() { 725 devel_themer_cleanup(); 726 } 727 728 /** 729 * Determine whether the user has permission to access the information provided by this module. 730 * 731 * @param $account 732 * (optional) The account to check, if not given use currently logged in user. 733 * 734 * @return 735 * Boolean TRUE if the user has permission to access the information provided 736 * by this module. 737 * 738 * @see user_access() 739 */ 740 function devel_themer_user_access($account = NULL) { 741 // Users with access to devel information from the devel module should 742 // automatically get access to the theme information as well. 743 return (user_access('access devel information', $account) || user_access('access devel theme information', $account)); 744 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |