| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154 | <?php/** * @file * This module holds functions useful for Drupal development. * Please contribute! */// Suggested profiling and stacktrace library from http://www.xdebug.org/index.phpdefine('DEVEL_QUERY_SORT_BY_SOURCE', 0);define('DEVEL_QUERY_SORT_BY_DURATION', 1);define('DEVEL_ERROR_HANDLER_NONE', 0);define('DEVEL_ERROR_HANDLER_STANDARD', 1);define('DEVEL_ERROR_HANDLER_BACKTRACE_KRUMO', 2);define('DEVEL_ERROR_HANDLER_BACKTRACE_DPM', 4);define('DEVEL_MIN_TEXTAREA', 50);/** * Implements hook_help(). */function devel_help($section) {  switch ($section) {    case 'devel/reference':      return '<p>' . t('This is a list of defined user functions that generated this current request lifecycle. Click on a function name to view its documentation.') . '</p>';    case 'devel/session':      return '<p>' . t('Here are the contents of your <code>$_SESSION</code> variable.') . '</p>';    case 'devel/variable':      $api = variable_get('devel_api_url', 'api.drupal.org');      return '<p>' . t('This is a list of the variables and their values currently stored in variables table and the <code>$conf</code> array of your settings.php file. These variables are usually accessed with <a href="@variable-get-doc">variable_get()</a> and <a href="@variable-set-doc">variable_set()</a>. Variables that are too long can slow down your pages.', array('@variable-get-doc' => "http://$api/api/HEAD/function/variable_get", '@variable-set-doc' => "http://$api/api/HEAD/function/variable_set")) . '</p>';    case 'devel/reinstall':      return t('Warning - will delete your module tables and variables.');  }}/** * Implements hook_modules_installed(). * * @see devel_install() */function devel_modules_installed($modules) {  if (in_array('menu', $modules)) {    $menu = array(      'menu_name' => 'devel',      'title' => t('Development'),      'description' => t('Development link'),    );    menu_save($menu);  }}/** * Implements hook_menu(). */function devel_menu() {  // Note: we can't dynamically append destination to querystring.  // Do so at theme layer. Fix in D7?  $items['devel/cache/clear'] = array(    'title' => 'Clear cache',    'page callback' => 'devel_cache_clear',    'description' => 'Clear the CSS cache and all database cache tables which store page, node, theme and variable caches.',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/reference'] = array(    'title' => 'Function reference',    'description' => 'View a list of currently defined user functions with documentation links.',    'page callback' => 'devel_function_reference',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/reinstall'] = array(    'title' => 'Reinstall modules',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_reinstall'),    'description' => 'Run hook_uninstall() and then hook_install() for a given module.',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/menu/reset'] = array(    'title' => 'Rebuild menus',    'description' => 'Rebuild menu based on hook_menu() and revert any custom changes. All menu items return to their default settings.',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_menu_rebuild'),    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/menu/item'] = array(    'title' => 'Menu item',    'description' => 'Details about a given menu item.',    'page callback' => 'devel_menu_item',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/variable'] = array(    'title' => 'Variable editor',    'description' => 'Edit and delete site variables.',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_variable_form'),    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  // We don't want the abbreviated version provided by status report.  $items['devel/phpinfo'] = array(    'title' => 'PHPinfo()',    'description' => 'View your server\'s PHP configuration',    'page callback' => 'devel_phpinfo',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/php'] = array(    'title' => 'Execute PHP Code',    'description' => 'Execute some PHP code',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_execute_form'),    'access arguments' => array('execute php code'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/theme/registry'] = array(    'title' => 'Theme registry',    'description' => 'View a list of available theme functions across the whole site.',    'page callback' => 'devel_theme_registry',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/entity/info'] = array(    'title' => 'Entity info',    'description' => 'View entity information across the whole site.',    'page callback' => 'devel_entity_info_page',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/field/info'] = array(    'title' => 'Field info',    'description' => 'View fields information across the whole site.',    'page callback' => 'devel_field_info_page',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/elements'] = array(    'title' => 'Hook_elements()',    'description' => 'View the active form/render elements for this site.',    'page callback' => 'devel_elements_page',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/variable/edit/%'] = array(    'title' => 'Variable editor',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_variable_edit', 3),    'access arguments' => array('access devel information'),    'type' => MENU_CALLBACK,    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/session'] = array(    'title' => 'Session viewer',    'description' => 'List the contents of $_SESSION.',    'page callback' => 'devel_session',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/switch'] = array(    'title' => 'Switch user',    'page callback' => 'devel_switch_user',    'access callback' => '_devel_switch_user_access',    'access arguments' => array(2),    'type' => MENU_CALLBACK,    'file' => 'devel.pages.inc',    'menu_name' => 'devel',  );  $items['devel/explain'] = array(    'title' => 'Explain query',    'page callback' => 'devel_querylog_explain',    'description' => 'Run an EXPLAIN on a given query. Used by query log',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'type' => MENU_CALLBACK,  );  $items['devel/arguments'] = array(    'title' => 'Arguments query',    'page callback' => 'devel_querylog_arguments',    'description' => 'Return a given query, with arguments instead of placeholders. Used by query log',    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'type' => MENU_CALLBACK,  );  $items['devel/run-cron'] = array(    'title' => 'Run cron',    'page callback' => 'system_run_cron',    'access arguments' => array('administer site configuration'),    'file' => 'system.admin.inc',    'file path' => drupal_get_path('module', 'system'),    'menu_name' => 'devel',  );  // Duplicate path in 2 different menus. See http://drupal.org/node/601788.  $items['devel/settings'] = array(    'title' => 'Devel settings',    'description' => 'Helper functions, pages, and blocks to assist Drupal developers. The devel blocks can be managed via the <a href="' . url('admin/structure/block') . '">block administration</a> page.',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_admin_settings'),    'access arguments' => array('administer site configuration'),    'file' => 'devel.admin.inc',    'menu_name' => 'devel',  );  $items['admin/config/development/devel'] = array(    'title' => 'Devel settings',    'description' => 'Helper functions, pages, and blocks to assist Drupal developers. The devel blocks can be managed via the <a href="' . url('admin/structure/block') . '">block administration</a> page.',    'page callback' => 'drupal_get_form',    'page arguments' => array('devel_admin_settings'),    'file' => 'devel.admin.inc',    'access arguments' => array('administer site configuration'),  );  $items['node/%node/devel'] = array(    'title' => 'Devel',    'page callback' => 'devel_load_object',    'page arguments' => array('node', 1),    'access arguments' => array('access devel information'),    'type' => MENU_LOCAL_TASK,    'file' => 'devel.pages.inc',    'weight' => 100,  );  $items['node/%node/devel/load'] = array(    'title' => 'Load',    'type' => MENU_DEFAULT_LOCAL_TASK,  );  $items['node/%node/devel/render'] = array(    'title' => 'Render',    'page callback' => 'devel_render_object',    'page arguments' => array('node', 1),    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'type' => MENU_LOCAL_TASK,    'weight' => 100,  );  $items['comment/%comment/devel'] = array(    'title' => 'Devel',    'page callback' => 'devel_load_object',    'page arguments' => array('comment', 1),    'access arguments' => array('access devel information'),    'type' => MENU_LOCAL_TASK,    'file' => 'devel.pages.inc',    'weight' => 100,  );  $items['comment/%comment/devel/load'] = array(    'title' => 'Load',    'type' => MENU_DEFAULT_LOCAL_TASK,  );  $items['comment/%comment/devel/render'] = array(    'title' => 'Render',    'page callback' => 'devel_render_object',    'page arguments' => array('comment', 1),    'access arguments' => array('access devel information'),    'type' => MENU_LOCAL_TASK,    'file' => 'devel.pages.inc',    'weight' => 100,  );  $items['user/%user/devel'] = array(    'title' => 'Devel',    'page callback' => 'devel_load_object',    'page arguments' => array('user', 1),    'access arguments' => array('access devel information'),    'type' => MENU_LOCAL_TASK,    'file' => 'devel.pages.inc',    'weight' => 100,  );  $items['user/%user/devel/load'] = array(    'title' => 'Load',    'type' => MENU_DEFAULT_LOCAL_TASK,  );  $items['user/%user/devel/render'] = array(    'title' => 'Render',    'page callback' => 'devel_render_object',    'page arguments' => array('user', 1),    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'type' => MENU_LOCAL_TASK,    'weight' => 100,  );  $items['taxonomy/term/%taxonomy_term/devel'] = array(    'title' => 'Devel',    'page callback' => 'devel_load_object',    'page arguments' => array('taxonomy_term', 2, 'term'),    'access arguments' => array('access devel information'),    'file' => 'devel.pages.inc',    'type' => MENU_LOCAL_TASK,    'weight' => 100,  );  $items['taxonomy/term/%taxonomy_term/devel/load'] = array(    'title' => 'Load',    'type' => MENU_DEFAULT_LOCAL_TASK,  );  $items['taxonomy/term/%taxonomy_term/devel/render'] = array(    'title' => 'Render',    'page callback' => 'devel_render_object',    'page arguments' => array('taxonomy_term', 2, 'term'),    'access arguments' => array('access devel information'),    'type' => MENU_LOCAL_TASK,    'file' => 'devel.pages.inc',    'weight' => 100,  );  return $items;}/** * Menu item access callback - check permission and token for Switch User. */function _devel_switch_user_access($name) {  // Suppress notices when on other pages when menu system still checks access.  return user_access('switch users') && drupal_valid_token(@$_GET['token'], "devel/switch/$name|" . @$_GET['destination'], TRUE);}/** * Implements hook_admin_paths(). */function devel_admin_paths() {  $paths = array(    'devel/*' => TRUE,    'node/*/devel' => TRUE,    'node/*/devel/*' => TRUE,    'comment/*/devel' => TRUE,    'comment/*/devel/*' => TRUE,    'user/*/devel' => TRUE,    'user/*/devel/*' => TRUE,    'taxonomy/term/*/devel' => TRUE,    'taxonomy/term/*/devel/*' => TRUE,  );  return $paths;}/** * Returns destinations. */function devel_menu_need_destination() {  return array('devel/cache/clear', 'devel/reinstall', 'devel/menu/reset',    'devel/variable', 'admin/reports/status/run-cron');}/** * Implements hook_menu_link_alter(). * * Flag this link as needing alter at display time. * This is more robust than setting alter in hook_menu(). * @see devel_translated_menu_link_alter() * **/function devel_menu_link_alter(&$item) {  if (in_array($item['link_path'], devel_menu_need_destination()) || $item['link_path'] == 'devel/menu/item') {    $item['options']['alter'] = TRUE;  }}/** * Implements hook_translated_menu_item_alter(). * * Append dynamic querystring 'destination' to several of our own menu items. **/function devel_translated_menu_link_alter(&$item) {  if (in_array($item['href'], devel_menu_need_destination())) {    $item['localized_options']['query'] = drupal_get_destination();  }  elseif ($item['href'] == 'devel/menu/item') {    $item['localized_options']['query'] = array('path' => $_GET['q']);  }}/** * Implements hook_theme(). */function devel_theme() {  return array(    'devel_querylog' => array(      'variables' => array('header' => array(), 'rows' => array()),    ),    'devel_querylog_row' => array(      'variables' => array('row' => array()),    ),  );}/** * Implements hook_init(). */function devel_init() {  if (!devel_silent()) {    if (user_access('access devel information')) {      devel_set_handler(devel_get_handlers());      // We want to include the class early so that anyone may call krumo()      // as needed. See http://krumo.sourceforge.net/      has_krumo();      // See http://www.firephp.org/HQ/Install.htm      $path = NULL;      if ((@include_once 'fb.php') || (@include_once 'FirePHPCore/fb.php')) {        // FirePHPCore is in include_path. Probably a PEAR installation.        $path = '';      }      elseif (module_exists('libraries')) {        // Support Libraries API - http://drupal.org/project/libraries        $firephp_path = libraries_get_path('FirePHPCore');        $firephp_path = ($firephp_path ? $firephp_path . '/lib/FirePHPCore/' : '');        $chromephp_path = libraries_get_path('chromephp');      }      else {        $firephp_path = './' . drupal_get_path('module', 'devel') . '/FirePHPCore/lib/FirePHPCore/';        $chromephp_path = './' . drupal_get_path('module', 'devel') . '/chromephp';      }      // Include FirePHP if it exists.      if (!empty($firephp_path) && file_exists($firephp_path . 'fb.php')) {        include_once $firephp_path . 'fb.php';        include_once $firephp_path . 'FirePHP.class.php';      }      // Include ChromePHP if it exists.      if (!empty($chromephp_path) && file_exists($chromephp_path .= '/ChromePhp.php')) {        include_once $chromephp_path;      }      // Add CSS for query log if should be displayed.      if (variable_get('devel_query_display', 0)) {        drupal_add_css(drupal_get_path('module', 'devel') . '/devel.css');        drupal_add_js(drupal_get_path('module', 'devel') . '/devel.js');      }    }  }  if (variable_get('devel_rebuild_theme_registry', FALSE)) {    drupal_theme_rebuild();    if (flood_is_allowed('devel_rebuild_registry_warning', 1)) {      flood_register_event('devel_rebuild_registry_warning');      if (!devel_silent() && user_access('access devel information')) {        drupal_set_message(t('The theme registry is being rebuilt on every request. Remember to <a href="!url">turn off</a> this feature on production websites.', array("!url" => url('admin/config/development/devel'))));      }    }  }}/** * Sets message. */function devel_set_message($msg, $type = NULL) {  $function  = function_exists('drush_log') ? 'drush_log' : 'drupal_set_message';  $function($msg, $type);  }/** * Returns boolean. No need for cache here. */function has_krumo() {  @include_once DRUPAL_ROOT . '/' . drupal_get_path('module', 'devel') . '/krumo/class.krumo.php';  if (function_exists('krumo') && !drupal_is_cli()) {    drupal_add_js(drupal_get_path('module', 'devel') . '/devel_krumo_path.js');    return TRUE;  }  return FALSE;}/** * Decides whether or not to print a debug variable using krumo(). * * @param array|object $input *   The value to check. * * @return boolean */function merits_krumo($input) {  return (is_object($input) || is_array($input)) && has_krumo() && variable_get('devel_krumo_skin', '') != 'disabled';}/** * Calls the http://www.firephp.org/ fb() function if it is found. */function dfb() {  if (function_exists('fb') && user_access('access devel information') && !headers_sent()) {    $args = func_get_args();    call_user_func_array('fb', $args);  }}/** * Calls dfb() to output a backtrace. */function dfbt($label) {  dfb($label, FirePHP::TRACE);}/** * Wrapper for ChromePHP Class log method. */function dcp() {  if (class_exists('ChromePhp', FALSE) && user_access('access devel information')) {    $args = func_get_args();    call_user_func_array(array('ChromePhp', 'log'), $args);  }}/** * Implements hook_watchdog(). */function devel_watchdog(array $log_entry) {  if (class_exists('FirePHP', FALSE) && !drupal_is_cli()) {    switch ($log_entry['severity']) {      case WATCHDOG_EMERGENCY:      case WATCHDOG_ALERT:      case WATCHDOG_CRITICAL:      case WATCHDOG_ERROR:        $type = FirePHP::ERROR;        break;      case WATCHDOG_WARNING:        $type = FirePHP::WARN;        break;      case WATCHDOG_NOTICE:      case WATCHDOG_INFO:        $type = FirePHP::INFO;        break;      case WATCHDOG_DEBUG:      default:        $type = FirePHP::LOG;    }  }  else {    $type = 'watchdog';  }  $function = function_exists('decode_entities') ? 'decode_entities' : 'html_entity_decode';  $watchdog = array(    'type' => $log_entry['type'],    'message' => $function(strtr($log_entry['message'], (array) $log_entry['variables'])),  );  if (isset($log_entry['link'])) {    $watchdog['link'] = $log_entry['link'];  }  dfb($watchdog, $type);}/** * Gets error handlers. */function devel_get_handlers() {  $error_handlers = variable_get('devel_error_handlers', array(DEVEL_ERROR_HANDLER_STANDARD => DEVEL_ERROR_HANDLER_STANDARD));  if (!empty($error_handlers)) {    unset($error_handlers[DEVEL_ERROR_HANDLER_NONE]);  }  return $error_handlers;}/** * Sets a new error handler or restores the prior one. */function devel_set_handler($handlers) {  if (empty($handlers)) {    restore_error_handler();  }  elseif (count($handlers) == 1 && isset($handlers[DEVEL_ERROR_HANDLER_STANDARD])) {    // Do nothing.  }  else {    if (has_krumo()) {      set_error_handler('backtrace_error_handler');    }  }}/** * Checks whether Devel may be active. */function devel_silent() {  // isset($_GET['q']) is needed when calling the front page. q is not set.  // Don't interfere with private files/images.  return    function_exists('drupal_is_cli') && drupal_is_cli() ||    (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'ApacheBench') !== FALSE) ||    !empty($_REQUEST['XDEBUG_PROFILE']) ||    isset($GLOBALS['devel_shutdown']) ||    strstr($_SERVER['PHP_SELF'], 'update.php') ||    (isset($_GET['q']) && (      in_array($_GET['q'], array('admin/content/node-settings/rebuild')) ||      substr($_GET['q'], 0, strlen('system/files')) == 'system/files' ||      substr($_GET['q'], 0, strlen('batch')) == 'batch' ||      substr($_GET['q'], 0, strlen('file/ajax')) == 'file/ajax')    );}/** * Enables xhprof. */function devel_xhprof_enable() {  if (devel_xhprof_is_enabled()) {    if ($path = variable_get('devel_xhprof_directory', '')) {      include_once $path . '/xhprof_lib/utils/xhprof_lib.php';      include_once $path . '/xhprof_lib/utils/xhprof_runs.php';      // @todo: consider a variable per-flag instead.      xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);    }  }}/** * Checks if xhprof is enabled. */function devel_xhprof_is_enabled() {  return extension_loaded('xhprof') && variable_get('devel_xhprof_enabled', FALSE);}/** * Implements hook_boot(). * * Runs even for cached pages. */function devel_boot() {  // Initialize XHProf.  devel_xhprof_enable();  if (!devel_silent()) {    if (variable_get('devel_memory', 0)) {      global $memory_init;      $memory_init = memory_get_usage();    }    if (devel_query_enabled()) {      @include_once DRUPAL_ROOT . '/includes/database/log.inc';      Database::startLog('devel');;    }  }  // We need user_access() in the shutdown function. make sure it gets loaded.  // Also prime the drupal_get_filename() static with user.module's location to  // avoid a stray query.  drupal_get_filename('module', 'user', 'modules/user/user.module');  drupal_load('module', 'user');  drupal_register_shutdown_function('devel_shutdown');}/** * Displays backtrace showing the route of calls to the current error. * * @param int $error_level *   The level of the error raised. * @param string $message *   The error message. * @param string $filename *   The filename that the error was raised in. * @param int $line *   The line number the error was raised at. * @param array $context *   An array that points to the active symbol table at the point the error *   occurred. */function backtrace_error_handler($error_level, $message, $filename, $line, $context) {  // Hide stack trace and parameters from unqualified users.  if (!user_access('access devel information')) {    // Do what core does in bootstrap.inc and errors.inc.    // (We need to duplicate the core code here rather than calling it    // to avoid having the backtrace_error_handler() on top of the call stack.)    require_once DRUPAL_ROOT . '/includes/errors.inc';    if ($error_level & error_reporting()) {      $types = drupal_error_levels();      list($severity_msg, $severity_level) = $types[$error_level];      $backtrace = debug_backtrace();      $caller = _drupal_get_last_caller($backtrace);      if (!function_exists('filter_xss_admin')) {        require_once DRUPAL_ROOT . '/includes/common.inc';      }      // We treat recoverable errors as fatal.      _drupal_log_error(array(        '%type' => isset($types[$error_level]) ? $severity_msg : 'Unknown error',        // The standard PHP error handler considers that the error messages        // are HTML. We mimick this behavior here.        '!message' => filter_xss_admin($message),        '%function' => $caller['function'],        '%file' => $caller['file'],        '%line' => $caller['line'],        'severity_level' => $severity_level,      ), $error_level == E_RECOVERABLE_ERROR);    }    return;  }  // Don't respond to the error if it was suppressed with a '@'  if (error_reporting() == 0) {    return;  }  // Don't respond to warning caused by ourselves.  if (preg_match('#Cannot modify header information - headers already sent by \\([^\\)]*[/\\\\]devel[/\\\\]#', $message)) {    return;  }  if ($error_level & error_reporting()) {    // Only write each distinct NOTICE message once, as repeats do not give any    // further information and can choke the page output.    if ($error_level == E_NOTICE) {      static $written = array();      if (!empty($written[$line][$filename][$message])) {        return;      }      $written[$line][$filename][$message] = TRUE;    }    require_once DRUPAL_ROOT . '/includes/errors.inc';    $types = drupal_error_levels();    $type = $types[$error_level];    $backtrace = debug_backtrace();    $variables = array(      '%error' => $type[0],      '%message' => $message,      '%function' => $backtrace[1]['function'] . '()',      '%file' => $filename,      '%line' => $line,    );    $msg = t('%error: %message in %function (line %line of %file).', $variables);    // Show message if error_level is ERROR_REPORTING_DISPLAY_SOME or higher.    // (This is Drupal's error_level, which is different from $error_level,    // and we purposely ignore the difference between _SOME and _ALL,    // see #970688!)    if (variable_get('error_level', 1) >= 1) {      $error_handlers = devel_get_handlers();      if (!empty($error_handlers[DEVEL_ERROR_HANDLER_STANDARD])) {        drupal_set_message($msg, ($type[1] <= WATCHDOG_ERROR ? 'error' : 'warning'));      }      if (!empty($error_handlers[DEVEL_ERROR_HANDLER_BACKTRACE_KRUMO])) {        print $msg . " =>\n";        ddebug_backtrace(FALSE, 1);      }      if (!empty($error_handlers[DEVEL_ERROR_HANDLER_BACKTRACE_DPM])) {        dpm(ddebug_backtrace(TRUE, 1), $msg, 'warning');      }    }    $watchdog = 'watchdog';    $watchdog('php', $msg, array(), $type[1]);  }}/** * Implements hook_permission(). */function devel_permission() {  return array(    'access devel information' => array(      'description' => t('View developer output like variable printouts, query log, etc.'),      'title' => t('Access developer information'),      'restrict access' => TRUE,    ),    'execute php code' => array(      'title' => t('Execute PHP code'),      'description' => t('Run arbitrary PHP from a block.'),      'restrict access' => TRUE,    ),    'switch users' => array(      'title' => t('Switch users'),      'description' => t('Become any user on the site with just a click.'),      'restrict access' => TRUE,    ),  );}/** * Implements hook_block_info(). */function devel_block_info() {  $blocks['execute_php'] = array(    'info' => t('Execute PHP'),    'cache' => DRUPAL_NO_CACHE,  );  $blocks['switch_user'] = array(    'info' => t('Switch user'),    'cache' => DRUPAL_NO_CACHE,  );  return $blocks;}/** * Implements hook_block_configure(). */function devel_block_configure($delta) {  if ($delta == 'switch_user') {    $form['list_size'] = array(      '#type' => 'textfield',      '#title' => t('Number of users to display in the list'),      '#default_value' => variable_get('devel_switch_user_list_size', 10),      '#size' => '3',      '#maxlength' => '4',    );    $form['include_anon'] = array(      '#type' => 'checkbox',      '#title' => t('Include %anonymous', array('%anonymous' => format_username(drupal_anonymous_user()))),      '#default_value' => variable_get('devel_switch_user_include_anon', FALSE),    );    $form['show_form'] = array(      '#type' => 'checkbox',      '#title' => t('Allow entering any user name'),      '#default_value' => variable_get('devel_switch_user_show_form', TRUE),    );    return $form;  }}/** * Implements hook_block_save(). */function devel_block_save($delta, $edit = array()) {  if ($delta == 'switch_user') {    variable_set('devel_switch_user_list_size', $edit['list_size']);    variable_set('devel_switch_user_include_anon', $edit['include_anon']);    variable_set('devel_switch_user_show_form', $edit['show_form']);  }}/** * Implements hook_block_view(). */function devel_block_view($delta) {  $block = array();  switch ($delta) {    case 'switch_user':      $block = devel_block_switch_user();      break;    case 'execute_php':      if (user_access('execute php code')) {        $block['content'] = drupal_get_form('devel_execute_block_form');      }      break;  }  return $block;}/** * Provides the Switch user block. */function devel_block_switch_user() {  $links = devel_switch_user_list();  if (!empty($links) || user_access('switch users')) {    drupal_add_css(drupal_get_path('module', 'devel') . '/devel.css');    $block['subject'] = t('Switch user');    $build['devel_links'] = array('#theme' => 'links', '#links' => $links);    if (variable_get('devel_switch_user_show_form', TRUE)) {      $build['devel_form'] = drupal_get_form('devel_switch_user_form');    }    $block['content'] = $build;    return $block;  }}/** * Provides the Switch user list. */function devel_switch_user_list() {  global $user;  $links = array();  if (user_access('switch users')) {    $list_size = variable_get('devel_switch_user_list_size', 10);    if ($include_anon = variable_get('devel_switch_user_include_anon', FALSE)) {      --$list_size;    }    $dest = drupal_get_destination();    // Try to find at least $list_size users that can switch.    // Inactive users are omitted from all of the following db selects.    $roles = user_roles(TRUE, 'switch users');    $query = db_select('users', 'u');    $query->addField('u', 'uid');    $query->addField('u', 'access');    $query->distinct();    $query->condition('u.uid', 0, '>');    $query->condition('u.status', 0, '>');    $query->orderBy('u.access', 'DESC');    $query->range(0, $list_size);    if (!isset($roles[DRUPAL_AUTHENTICATED_RID])) {      $query->leftJoin('users_roles', 'r', 'u.uid = r.uid');      $or_condition = db_or();      $or_condition->condition('u.uid', 1);      if (!empty($roles)) {        $or_condition->condition('r.rid', array_keys($roles), 'IN');      }      $query->condition($or_condition);    }    $uids = $query->execute()->fetchCol();    $accounts = user_load_multiple($uids);    foreach ($accounts as $account) {      $path = 'devel/switch/' . $account->name;      $links[$account->uid] = array(        'title' => drupal_placeholder(format_username($account)),        'href' => $path,        'query' => $dest + array('token' => drupal_get_token($path . '|' . $dest['destination'])),        'attributes' => array('title' => t('This user can switch back.')),        'html' => TRUE,        'last_access' => $account->access,      );    }    $num_links = count($links);    if ($num_links < $list_size) {      // If we don't have enough, add distinct uids until we hit $list_size.      $uids = db_query_range('SELECT uid FROM {users} WHERE uid > 0 AND uid NOT IN (:uids) AND status > 0 ORDER BY access DESC', 0, $list_size - $num_links, array(':uids' => array_keys($links)))->fetchCol();      $accounts = user_load_multiple($uids);      foreach ($accounts as $account) {        $path = 'devel/switch/' . $account->name;        $links[$account->uid] = array(          'title' => format_username($account),          'href' => $path,          'query' => $dest + array('token' => drupal_get_token($path . '|' . $dest['destination'])),          'attributes' => array('title' => t('Caution: this user will be unable to switch back.')),          'last_access' => $account->access,        );      }      uasort($links, '_devel_switch_user_list_cmp');    }    if ($include_anon) {      $path = 'devel/switch';      $link = array(        'title' => format_username(drupal_anonymous_user()),        'href' => $path,        'query' => $dest + array('token' => drupal_get_token($path . '/|' . $dest['destination'])),        'attributes' => array('title' => t('Caution: the anonymous user will be unable to switch back.')),      );      if (user_access('switch users', drupal_anonymous_user())) {        $link['title'] = drupal_placeholder($link['title']);        $link['attributes'] = array('title' => t('This user can switch back.'));        $link['html'] = TRUE;      }      $links[] = $link;    }  }  if (array_key_exists($user->uid, $links)) {    $links[$user->uid]['title'] = '<strong>' . $links[$user->uid]['title'] . '</strong>';  }  return $links;}/** * Comparison helper function for uasort() in devel_switch_user_list(). * * Sorts the Switch User links by the user's last access timestamp. */function _devel_switch_user_list_cmp($a, $b) {  return $b['last_access'] - $a['last_access'];}/** * Provides the Switch user form. */function devel_switch_user_form() {  $form['username'] = array(    '#type' => 'textfield',    '#description' => t('Enter username'),    '#autocomplete_path' => 'user/autocomplete',    '#maxlength' => USERNAME_MAX_LENGTH,    '#size' => 16,  );  $form['submit'] = array(    '#type' => 'submit',    '#value' => t('Switch'),  );  $form['#attributes'] = array('class' => array('clearfix'));  return $form;}/** * Provides the devel docs form. */function devel_doc_function_form() {  $version = devel_get_core_version(VERSION);  $form['function'] = array(    '#type' => 'textfield',    '#description' => t('Enter function name for api lookup'),    '#size' => 16,    '#maxlength' => 255,  );  $form['version'] = array('#type' => 'value', '#value' => $version);  $form['submit_button'] = array(    '#type' => 'submit',    '#value' => t('Submit'),  );  return $form;}/** * Submit handler for the API lookup form. */function devel_doc_function_form_submit($form, &$form_state) {  $version = $form_state['values']['version'];  $function = $form_state['values']['function'];  $api = variable_get('devel_api_url', 'api.drupal.org');  $form_state['redirect'] = "http://$api/api/function/$function/$version";}/** * Validate handler for the Switch user form. */function devel_switch_user_form_validate($form, &$form_state) {  if (!$account = user_load_by_name($form_state['values']['username'])) {    form_set_error('username', t('Username not found'));  }}/** * Submit handler for the Switch user form. */function devel_switch_user_form_submit($form, &$form_state) {  $path = 'devel/switch/' . $form_state['values']['username'];  $form_state['redirect'] = array(    $path,    array(      'query' => array(        'destination' => '',        'token' => drupal_get_token($path . '|'),    )));}/** * Implements hook_drupal_goto_alter(). */function devel_drupal_goto_alter($path, $options, $http_response_code) {  global $user;  if (isset($path) && !devel_silent()) {    // The page we are leaving is a drupal_goto(). Present a redirection page    // so that the developer can see the intermediate query log.    // We don't want to load user module here, so keep function_exists() call.    if (isset($user) && function_exists('user_access') && user_access('access devel information') && variable_get('devel_redirect_page', 0)) {      $destination = function_exists('url') ? url($path, $options) : $path;      $output = t_safe('<p>The user is being redirected to <a href="@destination">@destination</a>.</p>', array('@destination' => $destination));      drupal_deliver_page($output);      // Don't allow the automatic redirect to happen.      exit();    }    else {      $GLOBALS['devel_redirecting'] = TRUE;    }  }}/** * Implements hook_library_alter(). */function devel_library_alter(&$libraries, $module) {  // Use an uncompressed version of jQuery for debugging.  if ($module === 'system' && variable_get('devel_use_uncompressed_jquery', FALSE) && isset($libraries['jquery'])) {    // Make sure we're not changing the jQuery version used on the site.    if (version_compare($libraries['jquery']['version'], '1.4.4', '=')) {      $libraries['jquery']['js'] = array(        drupal_get_path('module', 'devel') . '/jquery-1.4.4-uncompressed.js' => array('weight' => JS_LIBRARY - 20),      );    }    else {      if (!devel_silent() && user_access('access devel information')) {        drupal_set_message(t('jQuery could not be replaced with an uncompressed version of 1.4.4, because jQuery @version is running on the site.', array('@version' => $libraries['jquery']['version'])));      }    }  }}/** * Runs on shutdown to clean up and display developer information. * * devel_boot() registers this function as a shutdown function. * The bulk of the work is done in devel_shutdown_real(). */function devel_shutdown() {  // Register the real shutdown function so it runs after other shutdown  // functions.  drupal_register_shutdown_function('devel_shutdown_real');  global $devel_run_id;  $devel_run_id = devel_xhprof_is_enabled() ? devel_shutdown_xhprof() : NULL;  if ($devel_run_id && function_exists('drush_log')) {    drush_log('xhprof link: ' . devel_xhprof_link($devel_run_id, 'url'), 'notice');  }}/** * Implements hook_page_alter(). */function devel_page_alter($page) {  if (variable_get('devel_page_alter', FALSE) && user_access('access devel information')) {    dpm($page, 'page');  }}/** * Implements hook_ajax_render_alter(). * * Disables our footer stuff based on ajax response. * * AJAX render reponses sometimes are sent as text/html. We have to catch them * here and disable our footer stuff. */function devel_ajax_render_alter() {  $GLOBALS['devel_shutdown'] = FALSE;}/** * Runs on shutdown to display developer information in the footer. * * devel_shutdown() registers this function as a shutdown function. */function devel_shutdown_real() {  global $user;  $output = $txt = '';  // Set $GLOBALS['devel_shutdown'] = FALSE in order to supress the  // devel footer for a page.  Not necessary if your page outputs any  // of the Content-type http headers tested below (e.g. text/xml,  // text/javascript, etc).  This is is advised where applicable.  if (!devel_silent() && !isset($GLOBALS['devel_shutdown']) && !isset($GLOBALS['devel_redirecting'])) {    // Try not to break non html pages.    if (function_exists('drupal_get_http_header')) {      $header = drupal_get_http_header('content-type');      if ($header) {        $formats = array('xml', 'javascript', 'json', 'plain', 'image',          'application', 'csv', 'x-comma-separated-values');        foreach ($formats as $format) {          if (strstr($header, $format)) {            return;          }        }      }    }    if (isset($user) && user_access('access devel information')) {      $queries = (devel_query_enabled() ? Database::getLog('devel', 'default') : NULL);      $output .= devel_shutdown_summary($queries);      $output .= devel_shutdown_query($queries);    }    if ($output) {      // TODO: gzip this text if we are sending a gzip page.      // See drupal_page_header().      // For some reason, this is not actually printing for cached pages even      // though it gets executed and $output looks good.      print $output;    }  }}/** * Returns the rendered shutdown summary. */function devel_shutdown_summary($queries) {  $sum = 0;  $output = '';  list($counts, $query_summary) = devel_query_summary($queries);  if (variable_get('devel_query_display', FALSE)) {    // Query log on.    $output .= $query_summary;    $output .= t_safe(' Queries exceeding @threshold ms are <span class="marker">highlighted</span>.', array('@threshold' => variable_get('devel_execution', 5)));  }  if (variable_get('dev_timer', 0)) {    $output .= devel_timer();  }  if (devel_xhprof_is_enabled()) {    $output .= ' ' . devel_xhprof_link($GLOBALS['devel_run_id']);  }  $output .= devel_shutdown_memory();  if ($output) {    return '<div class="dev-query">' . $output . '</div>';  }}/** * Returns the XHProf run ID. */function devel_shutdown_xhprof() {  // Namespace for your application.  $namespace = variable_get('site_name', '');  $xhprof_data = xhprof_disable();  $xhprof_runs = new XHProfRuns_Default();  return $xhprof_runs->save_run($xhprof_data, $namespace);}/** * Returns the XHProf link. */function devel_xhprof_link($run_id, $type = 'link') {  // @todo: render results from within Drupal.  $xhprof_url = variable_get('devel_xhprof_url', '');  // Namespace for your application.  $namespace = variable_get('site_name', '');  if ($xhprof_url) {    $url = $xhprof_url . '/index.php?run=' . urlencode($run_id) . '&source=' . urlencode($namespace);    return $type == 'url' ? $url : t('<a href="@xhprof">XHProf output</a>. ', array('@xhprof' => $url));  }}/** * Returns the rendered memory usage. */function devel_shutdown_memory() {  global $memory_init;  if (variable_get('devel_memory', FALSE)) {    $memory_shutdown = memory_get_usage();    $args = array(      '@memory_boot' => round($memory_init / 1024 / 1024, 2),      '@memory_shutdown' => round($memory_shutdown / 1024 / 1024, 2),      '@memory_peak' => round(memory_get_peak_usage(TRUE) / 1024 / 1024, 2)    );    $msg = '<span class="dev-memory-usages"> Memory used at: devel_boot()=<strong>@memory_boot</strong> MB, devel_shutdown()=<strong>@memory_shutdown</strong> MB, PHP peak=<strong>@memory_peak</strong> MB.</span>';    // theme() may not be available. not t() either.    return t_safe($msg, $args);  }}/** * Returns the rendered query log. */function devel_shutdown_query($queries) {  if (!empty($queries)) {    if (function_exists('theme_get_registry') && theme_get_registry()) {      // Safe to call theme('table).      list($counts, $query_summary) = devel_query_summary($queries);      $output = devel_query_table($queries, $counts);      // Save all queries to a file in temp dir. Retrieved via AJAX.      devel_query_put_contents($queries);    }    else {      $output = '</div>' . dprint_r($queries, TRUE);    }    return $output;  }}/** * Writes the variables information to a file. * * It will be retrieved on demand via AJAX. */function devel_query_put_contents($queries) {  $request_id = mt_rand(1, 1000000);  $path = "temporary://devel_querylog";  // Create the devel_querylog within the temp folder, if needed.  file_prepare_directory($path, FILE_CREATE_DIRECTORY);  // Occassionally wipe the querylog dir so that files don't accumulate.  if (mt_rand(1, 1000) == 401) {    devel_empty_dir($path);  }  $path .= "/$request_id.txt";  $path = file_stream_wrapper_uri_normalize($path);  // Save queries as a json array. Suppress errors due to recursion ()  file_put_contents($path, @json_encode($queries));  $settings['devel'] = array(    // A random string that is sent to the browser.    // It enables the AJAX to retrieve queries from this request.    'request_id' => $request_id,  );  print '<script type="text/javascript">jQuery.extend(Drupal.settings, ' . json_encode($settings) . ");</script>\n";}/** * Returns whether query logging is enabled. */function devel_query_enabled() {  return method_exists('Database', 'getLog') && variable_get('devel_query_display', FALSE);}/** * Returns the query summary. */function devel_query_summary($queries) {  if (variable_get('devel_query_display', FALSE) && is_array($queries)) {    $sum = 0;    foreach ($queries as $query) {      $text[] = $query['query'];      $sum += $query['time'];    }    $counts = array_count_values($text);    return array(      $counts,      t_safe('Executed @queries queries in @time ms.',      array('@queries' => count($queries), '@time' => round($sum * 1000, 2))),    );  }}/** * Devel's t_safe() function. */function t_safe($string, $args) {  // get_t() caused problems here with the theme registry after changing on  // admin/build/modules. The theme_get_registry() call is needed!  if (function_exists('t') && function_exists('theme_get_registry')) {    theme_get_registry();    return t($string, $args);  }  else {    strtr($string, $args);  }}/** * Returns the core version. */function devel_get_core_version($version) {  $version_parts = explode('.', $version);  // Map from 4.7.10 -> 4.7  if ($version_parts[0] < 5) {    return $version_parts[0] . '.' . $version_parts[1];  }  // Map from 5.5 -> 5 or 6.0-beta2 -> 6  else {    return $version_parts[0];  }}/** * Returns whether the optimizer is compatible. */function devel_is_compatible_optimizer() {  // See http://drupal.org/node/126098.  ob_start();  phpinfo();  $info = ob_get_contents();  ob_end_clean();  // Match the Zend Optimizer version in the phpinfo information.  $found = preg_match('/Zend Optimizer v([0-9])\.([0-9])\.([0-9])/', $info, $matches);  if ($matches) {    $major = $matches[1];    $minor = $matches[2];    $build = $matches[3];    if ($major >= 3) {      if ($minor >= 3) {        return TRUE;      }      elseif ($minor == 2 && $build >= 8) {        return TRUE;      }      else {        return FALSE;      }    }    else {      return FALSE;    }  }  else {    return TRUE;  }}/** * Generates the execute block form. */function devel_execute_block_form() {  $form['execute'] = array(    '#type' => 'fieldset',    '#title' => t('Execute PHP Code'),    '#collapsible' => TRUE,    '#collapsed' => (!isset($_SESSION['devel_execute_code'])),  );  $form['#submit'] = array('devel_execute_form_submit');  return array_merge_recursive($form, devel_execute_form());}/** * Generates the execute form. */function devel_execute_form() {  $form['execute']['code'] = array(    '#type' => 'textarea',    '#title' => t('PHP code to execute'),    '#description' => t('Enter some code. Do not use <code><?php ?></code> tags.'),    '#default_value' => (isset($_SESSION['devel_execute_code']) ? $_SESSION['devel_execute_code'] : ''),    '#rows' => 20,  );  $form['execute']['op'] = array('#type' => 'submit', '#value' => t('Execute'));  $form['#redirect'] = FALSE;  if (isset($_SESSION['devel_execute_code'])) {    unset($_SESSION['devel_execute_code']);  }  return $form;}/** * Processes PHP execute form submissions. */function devel_execute_form_submit($form, &$form_state) {  ob_start();  print eval($form_state['values']['code']);  $_SESSION['devel_execute_code'] = $form_state['values']['code'];  dsm(ob_get_clean());}/** * Switches to a different user. * * We don't call session_save_session() because we really want to change users. * Usually unsafe! * * @param string $name *   The username to switch to, or NULL to log out. */function devel_switch_user($name = NULL) {  global $user;  if ($user->uid) {    module_invoke_all('user_logout', $user);  }  if (isset($name) && $account = user_load_by_name($name)) {    $old_uid = $user->uid;    $user = $account;    $user->timestamp = time() - 9999;    if (!$old_uid) {      // Switch from anonymous to authorized.      drupal_session_regenerate();    }    $edit = array();    user_module_invoke('login', $edit, $user);  }  elseif ($user->uid) {    session_destroy();  }  drupal_goto();}/** * Prints an object using either Krumo (if installed) or devel_print_object(). * * @param array|object $object *   An array or object to print. * @param string $prefix *   Prefix for output items. */function kdevel_print_object($object, $prefix = NULL) {  return has_krumo() ? krumo_ob($object) : devel_print_object($object, $prefix);}/** * Saves krumo html using output buffering. */function krumo_ob($object) {  ob_start();  krumo($object);  $output = ob_get_contents();  ob_end_clean();  return $output;}/** * Displays an object or array. * * @param array|object $object *   The object or array to display. * @param string $prefix *   Prefix for the output items (example "$node->", "$user->", "$"). * @param boolean $header *   Set to FALSE to suppress the output of the h3 tag. */function devel_print_object($object, $prefix = NULL, $header = TRUE) {  drupal_add_css(drupal_get_path('module', 'devel') . '/devel.css');  $output = '<div class="devel-obj-output">';  if ($header) {    $output .= '<h3>' . t('Display of !type !obj', array(      '!type' => str_replace(array('$', '->'), '', $prefix),      '!obj' => gettype($object),    )    ) . '</h3>';  }  $output .= _devel_print_object($object, $prefix);  $output .= '</div>';  return $output;}/** * Returns formatted listing for an array or object. * * Recursive (and therefore magical) function goes through an array or object * and returns a nicely formatted listing of its contents. * * @param array|object $obj *   Array or object to recurse through. * @param string $prefix *   Prefix for the output items (example "$node->", "$user->", "$"). * @param string $parents *   Used by recursion. * @param boolean $object *   Used by recursion. * * @return string *   Formatted html. * * @todo *   currently there are problems sending an array with a varname */function _devel_print_object($obj, $prefix = NULL, $parents = NULL, $object = FALSE) {  static $root_type, $out_format;  // TODO: support objects with references. See http://drupal.org/node/234581.  if (isset($obj->view)) {    return;  }  if (!isset($root_type)) {    $root_type = gettype($obj);    if ($root_type == 'object') {      $object = TRUE;    }  }  if (is_object($obj)) {    $obj = (array) $obj;  }  if (is_array($obj)) {    $output = "<dl>\n";    foreach ($obj as $field => $value) {      if ($field === 'devel_flag_reference') {        continue;      }      if (!is_null($parents)) {        if ($object) {          $field = $parents . '->' . $field;        }        else {          if (is_int($field)) {            $field = $parents . '[' . $field . ']';          }          else {            $field = $parents . '[\'' . $field . '\']';          }        }      }      $type = gettype($value);      $show_summary = TRUE;      $summary = NULL;      if ($show_summary) {        switch ($type) {          case 'string':          case 'float':          case 'integer':            if (strlen($value) == 0) {              $summary = t("{empty}");            }            elseif (strlen($value) < 40) {              $summary = htmlspecialchars($value);            }            else {              $summary = format_plural(drupal_strlen($value), '1 character', '@count characters');            }            break;          case 'array':          case 'object':            $summary = format_plural(count((array) $value), '1 element', '@count elements');            break;          case 'boolean':            $summary = $value ? t('TRUE') : t('FALSE');            break;        }      }      if (!is_null($summary)) {        $typesum = '(' . $type . ', <em>' . $summary . '</em>)';      }      else {        $typesum = '(' . $type . ')';      }      $output .= '<span class="devel-attr">';      $output .= "<dt><span class=\"field\">{$prefix}{$field}</span> $typesum</dt>\n";      $output .= "<dd>\n";      // Check for references.      if (is_array($value) && isset($value['devel_flag_reference'])) {        $value['devel_flag_reference'] = TRUE;      }      // Check for references to prevent errors from recursions.      if (is_array($value) && isset($value['devel_flag_reference']) && !$value['devel_flag_reference']) {        $value['devel_flag_reference'] = FALSE;        $output .= _devel_print_object($value, $prefix, $field);      }      elseif (is_object($value)) {        $value->devel_flag_reference = FALSE;        $output .= _devel_print_object((array) $value, $prefix, $field, TRUE);      }      else {        $value = is_bool($value) ? ($value ? 'TRUE' : 'FALSE') : $value;        $output .= htmlspecialchars(print_r($value, TRUE)) . "\n";      }      $output .= "</dd></span>\n";    }    $output .= "</dl>\n";  }  return $output;}/** * Shows all the queries for the page. * * Adds a table at the bottom of the page cataloguing data on all the database * queries that were made to generate the page. */function devel_query_table($queries, $counts) {  $version = devel_get_core_version(VERSION);  $header = array('ms', '#', 'where', 'ops', 'query', 'target');  $i = 0;  $api = variable_get('devel_api_url', 'api.drupal.org');  foreach ($queries as $query) {    $function = !empty($query['caller']['class']) ? $query['caller']['class'] . '::' : '';    $function .= $query['caller']['function'];    $count = isset($counts[$query['query']]) ? $counts[$query['query']] : 0;    $diff = round($query['time'] * 1000, 2);    if ($diff > variable_get('devel_execution', 5)) {      $cell[$i][] = array('data' => $diff, 'class' => 'marker');    }    else {      $cell[$i][] = $diff;    }    $cell[$i][] = $count;    $cell[$i][] = l($function, "http://$api/api/function/$function/$version");    $ops[] = l(t('P'), '', array(      'attributes' => array(        'title' => 'Show placeholders',        'class' => array('dev-placeholders'),        'qid' => $i,    )));    $ops[] = l(t('A'), '', array(        'attributes' => array(          'title' => 'Show arguments',          'class' => array('dev-arguments'),          'qid' => $i,    )));    // EXPLAIN only valid for select queries.    if (strpos($query['query'], 'UPDATE') === FALSE && strpos($query['query'], 'INSERT') === FALSE && strpos($query['query'], 'DELETE') === FALSE) {      $ops[] = l(t('E'), '', array(        'attributes' => array(          'title' => 'Show EXPLAIN',          'class' => array('dev-explain'),          'qid' => $i,      )));    }    $cell[$i][] = implode(' ', $ops);    // 3 divs for each variation of the query. Last 2 are hidden by default.    $placeholders = '<div class="dev-placeholders">' . check_plain($query['query']) . "</div>\n";    $args = '<div class="dev-arguments" style="display: none;"></div>' . "\n";    $explain = '<div class="dev-explain" style="display: none;"></div>' . "\n";    $cell[$i][] = array(      'id' => "devel-query-$i",      'data' => $placeholders . $args . $explain,    );    $cell[$i][] = $query['target'];    $i++;    unset($diff, $count, $ops);  }  if (variable_get('devel_query_sort', DEVEL_QUERY_SORT_BY_SOURCE)) {    usort($cell, '_devel_table_sort');  }  return theme('devel_querylog', array('header' => $header, 'rows' => $cell));}/** * Themes devel's querylog row. */function theme_devel_querylog_row($variables) {  $row = $variables['row'];  $i = 0;  $output = '';  foreach ($row as $cell) {    $i++;    if (is_array($cell)) {      $data = !empty($cell['data']) ? $cell['data'] : '';      unset($cell['data']);      $attr = $cell;    }    else {      $data = $cell;      $attr = array();    }    if (!empty($attr['class'])) {      $attr['class'] .= " cell cell-$i";    }    else {      $attr['class'] = "cell cell-$i";    }    $attr = drupal_attributes($attr);    $output .= "<div $attr>$data</div>";  }  return $output;}/** * Themes devel's querylog. */function theme_devel_querylog($variables) {  $header = $variables['header'];  $rows = $variables['rows'];  $output = '';  if (!empty($header)) {    $output .= "<div class='devel-querylog devel-querylog-header clear-block'>";    $output .= theme('devel_querylog_row', array('row' => $header));    $output .= "</div>";  }  if (!empty($rows)) {    $i = 0;    foreach ($rows as $row) {      $i++;      $zebra = ($i % 2) == 0 ? 'even' : 'odd';      $output .= "<div class='devel-querylog devel-querylog-$zebra clear-block'>";      $output .= theme('devel_querylog_row', array('row' => $row));      $output .= "</div>";    }  }  return $output;}/** * Devel's table sort. */function _devel_table_sort($a, $b) {  $a = is_array($a[0]) ? $a[0]['data'] : $a[0];  $b = is_array($b[0]) ? $b[0]['data'] : $b[0];  if ($a < $b) {    return 1;  }  if ($a > $b) {    return -1;  }  return 0;}/** * Displays page execution time at the bottom of the page. */function devel_timer() {  $time = timer_read('page');  return t_safe(' Page execution time was @time ms.', array('@time' => $time));}/** * An alias for drupal_debug(). */function dd($data, $label = NULL) {  return drupal_debug($data, $label);}/** * Logs a variable to a drupal_debug.txt in the site's temp directory. * * @param mixed $data *   The variable to log to the drupal_debug.txt log file. * @param string $label *   (optional) If set, a label to output before $data in the log file. * * @return void|false *   Empty if successful, FALSE if the log file could not be written. * * @see dd() * @see http://drupal.org/node/314112 */function drupal_debug($data, $label = NULL) {  $out = ($label ? $label . ': ' : '') . print_r($data, TRUE) . "\n";  // The temp directory does vary across multiple simpletest instances.  $file = file_directory_temp() . '/drupal_debug.txt';  if (file_put_contents($file, $out, FILE_APPEND) === FALSE) {    drupal_set_message(t('Devel was unable to write to %file.', array('%file' => $file)), 'error');    return FALSE;  }}/** * Prints the arguments passed into the current function. */function dargs($always = TRUE) {  static $printed;  if ($always || !$printed) {    $bt = debug_backtrace();    print kdevel_print_object($bt[1]['args']);    $printed = TRUE;  }}/** * Prints a SQL string from a DBTNG Select object. Includes quoted arguments. * * Includes quoted arguments. * * @param object $query *   An object that implements the SelectQueryInterface interface. * @param string $return *   Whether to return the string. Default is FALSE, meaning to print it *   and return $query instead. * @param string $name *   Optional name for identifying the output. * @return object|string *   The $query object, or the query string if $return was TRUE. */function dpq($query, $return = FALSE, $name = NULL) {  if (user_access('access devel information')) {    if (method_exists($query, 'preExecute')) {      $query->preExecute();    }    $sql = (string) $query;    $quoted = array();    $connection = Database::getConnection();    foreach ((array) $query->arguments() as $key => $val) {      $quoted[$key] = $connection->quote($val);    }    $sql = strtr($sql, $quoted);    if ($return) {      return $sql;    }    dpm($sql, $name);  }  return ($return ? NULL : $query);}/** * Prints a variable to the 'message' area of the page. * * Uses drupal_set_message(). * * @param $input *   An arbitrary value to output. * @param string $name *   Optional name for identifying the output. * @param string $type *   Optional message type for drupal_set_message(), defaults to 'status'. * * @return input *   The unaltered input value. */function dpm($input, $name = NULL, $type = 'status') {  if (user_access('access devel information')) {    $export = kprint_r($input, TRUE, $name);    drupal_set_message($export, $type);  }  return $input;}/** * Displays a drupal_var_export() variable to the 'message' area of the page. * * Uses drupal_set_message(). * * @param $input *   An arbitrary value to output. * @param string $name *   Optional name for identifying the output. * * @return input *   The unaltered input value. */function dvm($input, $name = NULL) {  if (user_access('access devel information')) {    $export = dprint_r($input, TRUE, $name, 'drupal_var_export', FALSE);    drupal_set_message($export);  }  return $input;}/** * Legacy function that was poorly named. * * Use dpm() instead, since the 'p' maps to 'print_r'. */function dsm($input, $name = NULL) {  return dpm($input, $name);}/** * An alias for dprint_r(). Saves carpal tunnel syndrome. */function dpr($input, $return = FALSE, $name = NULL) {  return dprint_r($input, $return, $name);}/** * An alias for kprint_r(). Saves carpal tunnel syndrome. */function kpr($input, $return = FALSE, $name = NULL) {  return kprint_r($input, $return, $name);}/** * Like dpr(), but uses drupal_var_export() instead. */function dvr($input, $return = FALSE, $name = NULL) {  return dprint_r($input, $return, $name, 'drupal_var_export', FALSE);}/** * Krumo print. */function kprint_r($input, $return = FALSE, $name = NULL, $function = 'print_r') {  // We do not want to krumo() strings and integers and such.  if (merits_krumo($input)) {    if (user_access('access devel information')) {      return $return ? (isset($name) ? $name . ' => ' : '') . krumo_ob($input) : krumo($input);    }  }  else {    return dprint_r($input, $return, $name, $function);  }}/** * Pretty-print a variable to the browser (no krumo). * * Displays only for users with proper permissions. If * you want a string returned instead of a print, use the 2nd param. */function dprint_r($input, $return = FALSE, $name = NULL, $function = 'print_r', $check= TRUE) {  if (user_access('access devel information')) {    if ($name) {      $name .= ' => ';    }    if ($function == 'drupal_var_export') {      include_once DRUPAL_ROOT . '/includes/utility.inc';      $output = drupal_var_export($input);    }    else {      ob_start();      $function($input);      $output = ob_get_clean();    }    if ($check) {      $output = check_plain($output);    }    if (count($input, COUNT_RECURSIVE) > DEVEL_MIN_TEXTAREA) {      // Don't use fapi here because sometimes fapi will not be loaded.      $printed_value = "<textarea rows=30 style=\"width: 100%;\">\n" . $name . $output . '</textarea>';    }    else {      $printed_value = '<pre>' . $name . $output . '</pre>';    }    if ($return) {      return $printed_value;    }    else {      print $printed_value;    }  }}/** * Prints a renderable array element to the screen using kprint_r(). * * #pre_render and/or #post_render pass-through callback for kprint_r(). * * @todo Investigate appending to #suffix. * @todo Investigate label derived from #id, #title, #name, and #theme. */function devel_render() {  $args = func_get_args();  // #pre_render and #post_render pass the rendered $element as last argument.  kprint_r(end($args));  // #pre_render and #post_render expect the first argument to be returned.  return reset($args);}/** * Prints the function call stack. * * @param $return *   Pass TRUE to return the formatted backtrace rather than displaying it in *   the browser via kprint_r(). * @param $pop *   How many items to pop from the top of the stack; useful when calling from *   an error handler. * @param $options *   Options to pass on to PHP's debug_backtrace(), depending on your PHP *   version. * * @return string|NULL *   The formatted backtrace, if requested, or NULL. * * @see http://php.net/manual/en/function.debug-backtrace.php */function ddebug_backtrace($return = FALSE, $pop = 0, $options = TRUE) {  if (user_access('access devel information')) {    $backtrace = debug_backtrace($options);    while ($pop-- > 0) {      array_shift($backtrace);    }    $counter = count($backtrace);    $path = $backtrace[$counter - 1]['file'];    $path = substr($path, 0, strlen($path) - 10);    $paths[$path] = strlen($path) + 1;    $paths[DRUPAL_ROOT] = strlen(DRUPAL_ROOT) + 1;    $nbsp = "\xC2\xA0";    // Show message if error_level is ERROR_REPORTING_DISPLAY_SOME or higher.    // (This is Drupal's error_level, which is different from $error_level,    // and we purposely ignore the difference between _SOME and _ALL,    // see #970688!)    if (variable_get('error_level', 1) >= 1) {      while (!empty($backtrace)) {        $call = array();        if (isset($backtrace[0]['file'])) {          $call['file'] = $backtrace[0]['file'];          foreach ($paths as $path => $len) {            if (strpos($backtrace[0]['file'], $path) === 0) {              $call['file'] = substr($backtrace[0]['file'], $len);            }          }          $call['file'] .= ':' . $backtrace[0]['line'];        }        if (isset($backtrace[1])) {          if (isset($backtrace[1]['class'])) {            $function = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()';          }          else {            $function = $backtrace[1]['function'] . '()';          }          $backtrace[1] += array('args' => array());          $call['args'] = $backtrace[1]['args'];        }        else {          $function = 'main()';          $call['args'] = $_GET;        }        $nicetrace[($counter <= 10 ? $nbsp : '') . --$counter . ': ' . $function] = $call;        array_shift($backtrace);      }      if ($return) {        return $nicetrace;      }      kprint_r($nicetrace);    }  }}/** * Deletes all files in a dir. */function devel_empty_dir($dir) {  foreach (new DirectoryIterator($dir) as $file_info) {    if ($file_info->isFile()) {      unlink($file_info->getPathname());    }  }}/* * Migration-related functions. *//** * Regenerates the data in node_comment_statistics table. * Technique - http://www.artfulsoftware.com/infotree/queries.php?&bw=1280#101 * * @return void */function devel_rebuild_node_comment_statistics() {  // Empty table.  db_truncate('node_comment_statistics')->execute();  // TODO: DBTNG. Ignore keyword is Mysql only? Is only used in the rare case  // when two comments on the same node share same timestamp.  $sql = "    INSERT IGNORE INTO {node_comment_statistics} (nid, cid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) (      SELECT c.nid, c.cid, c.created, c.name, c.uid, c2.comment_count FROM {comment} c      JOIN (        SELECT c.nid, MAX(c.created) AS created, COUNT(*) AS comment_count FROM {comment} c WHERE status = 1 GROUP BY c.nid      ) AS c2 ON c.nid = c2.nid AND c.created = c2.created    )";  db_query($sql, array(':published' => COMMENT_PUBLISHED));  // Insert records into the node_comment_statistics for nodes that are missing.  $query = db_select('node', 'n');  $query->leftJoin('node_comment_statistics', 'ncs', 'ncs.nid = n.nid');  $query->addField('n', 'changed', 'last_comment_timestamp');  $query->addField('n', 'uid', 'last_comment_uid');  $query->addField('n', 'nid');  $query->addExpression('0', 'comment_count');  $query->addExpression('NULL', 'last_comment_name');  $query->isNull('ncs.comment_count');  db_insert('node_comment_statistics', array('return' => Database::RETURN_NULL))    ->from($query)    ->execute();}/** * Implements hook_form_alter(). * * Adds mouse-over hints on the Permissions page to display * language-independent machine names and module base names. */function devel_form_user_admin_permissions_alter(&$form, &$form_state) {  if (user_access('access devel information') && variable_get('devel_raw_names', FALSE)) {    foreach ($form['permission'] as $perm => $data) {      if (is_numeric($perm)) {        $form['permission'][$perm]['#markup'] = '<span title="' . $form['permission'][$perm]['#id'] . '">' . $form['permission'][$perm]['#markup'] . '</span>';      }      else {        $form['permission'][$perm]['#markup'] = '<span title="' . check_plain($perm) . '">' . $form['permission'][$perm]['#markup'] . '</span>';      }    }  }}/** * Implements hook_form_alter(). * * Adds mouse-over hints on the Modules page to display module base names. */function devel_form_system_modules_alter(&$form, &$form_state) {  if (user_access('access devel information') && variable_get('devel_raw_names', FALSE) && isset($form['modules']) && is_array($form['modules'])) {    foreach (element_children($form['modules']) as $key) {      if (isset($form['modules'][$key]['name']['#markup'])) {        $form['modules'][$key]['name']['#markup'] = '<span title="' . $key . '">' . $form['modules'][$key]['name']['#markup'] . '</span>';      }      elseif (is_array($form['modules'][$key])) {        foreach (element_children($form['modules'][$key]) as $key2) {          if (isset($form['modules'][$key][$key2]['name']['#markup'])) {            $form['modules'][$key][$key2]['name']['#markup'] = '<span title="' . $key2 . '">' . $form['modules'][$key][$key2]['name']['#markup'] . '</span>';          }        }      }    }  }}
 |