View source
<?php
define('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', 2);
define('DEVEL_MIN_TEXTAREA', 50);
define('DEVEL_CURRENT_DRUPAL_VERSION', 5);
function devel_help($section) {
switch ($section) {
case 'admin/settings/devel':
return '<p>' . t('Helper functions, pages, and blocks to assist Drupal developers. The devel blocks can be managed via the <a href="@block">block administration</a> page.', array(
'@block' => url('admin/build/block'),
)) . '</p>';
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 documention.') . '</p>';
case 'devel/reinstall':
return '<p>' . t('Clicking a module\'s reinstall button will simulate uninstalling/installing a module. <code>hook_uninstall()</code> and <code>hook_install()</code> will be executed and the schema version number will be set to the most recent update number. You may have to manually clear out any existing tables first if the module doesn\'t implement <code>hook_uninstall()</code>.') . '</p>';
case 'devel/session':
return '<p>' . t('Here are the contents of your <code>$_SESSION</code> variable.') . '</p>';
case 'devel/variable':
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.drupal.org/api/HEAD/function/variable_get',
'@variable-set-doc' => 'http://api.drupal.org/api/HEAD/function/variable_set',
)) . '</p>';
}
}
function devel_menu($may_cache) {
$items = array();
if ($may_cache) {
$items[] = array(
'path' => 'devel/cache/clear',
'title' => t('Empty cache'),
'callback' => 'devel_cache_clear',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/rebuild_node_comment_statistics',
'title' => t('Rebuild node_comment_statistics table'),
'callback' => 'devel_rebuild_node_comment_statistics_page',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/queries',
'title' => t('Database queries'),
'callback' => 'devel_queries',
'access' => user_access('access devel information'),
);
$items[] = array(
'path' => 'devel/queries/empty',
'title' => t('Empty database queries'),
'callback' => 'devel_queries_empty',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/reference',
'title' => t('function reference'),
'callback' => 'devel_function_reference',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/reinstall',
'title' => t('Reinstall modules'),
'callback' => 'devel_reinstall',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
if (module_exists('menu')) {
$items[] = array(
'path' => 'devel/menu/reset',
'title' => t('Reset menus'),
'callback' => 'drupal_get_form',
'callback arguments' => 'devel_menu_reset_form',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
}
$items[] = array(
'path' => 'devel/php',
'title' => t('Execute PHP Code'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'devel_execute_form',
),
'access' => user_access('execute php code'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/variable',
'title' => t('Variable editor'),
'callback' => 'devel_variable_page',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/variable/edit',
'title' => t('Variable editor'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'devel_variable_edit',
),
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/variable/delete',
'title' => t('Variable editor'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'devel_variable_delete',
),
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/session',
'title' => t('Session viewer'),
'callback' => 'devel_session',
'access' => user_access('access devel information'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'devel/switch',
'title' => t('Switch user'),
'callback' => 'devel_switch_user',
'access' => user_access('switch users'),
'type' => MENU_CALLBACK,
);
$items[] = array(
'path' => 'admin/settings/devel',
'title' => t('Devel'),
'callback' => 'drupal_get_form',
'callback arguments' => array(
'devel_admin_settings',
),
'access' => user_access('administer site configuration'),
'type' => MENU_NORMAL_ITEM,
);
}
else {
has_krumo();
if (is_numeric(arg(1))) {
if (arg(0) == 'node') {
$items[] = array(
'path' => 'node/' . arg(1) . '/devel/load',
'title' => t('Dev load'),
'callback' => 'devel_load_object',
'callback arguments' => array(
'node',
arg(1),
),
'access' => user_access('access devel information'),
'type' => MENU_LOCAL_TASK,
);
$items[] = array(
'path' => 'node/' . arg(1) . '/devel/render',
'title' => t('Dev render'),
'callback' => 'devel_render_object',
'callback arguments' => array(
'node',
arg(1),
),
'access' => user_access('access devel information'),
'type' => MENU_LOCAL_TASK,
);
}
elseif (arg(0) == 'user') {
$items[] = array(
'path' => 'user/' . arg(1) . '/load',
'title' => t('Dev load'),
'callback' => 'devel_load_object',
'callback arguments' => array(
'user',
arg(1),
),
'access' => user_access('access devel information'),
'type' => MENU_LOCAL_TASK,
);
}
}
if (module_exists('views_ui')) {
$urls = views_get_all_urls();
foreach ($urls as $view_name => $url) {
$items[] = array(
'path' => "{$url}/devel/load",
'title' => t('Dev load'),
'callback' => 'devel_load_object',
'callback arguments' => array(
'view',
$view_name,
),
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK,
'weight' => 8,
);
$items[] = array(
'path' => "{$url}/devel/queries",
'title' => t('Dev queries'),
'callback' => 'devel_views_object',
'callback arguments' => array(
'queries',
$view_name,
),
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK,
'weight' => 9,
);
$items[] = array(
'path' => "{$url}/devel/items",
'title' => t('Dev items'),
'callback' => 'devel_views_object',
'callback arguments' => array(
'items',
$view_name,
),
'access' => user_access('administer views'),
'type' => MENU_LOCAL_TASK,
'weight' => 10,
);
}
}
if (user_access('access devel information')) {
drupal_add_css(drupal_get_path('module', 'devel') . '/devel.css');
drupal_add_js(drupal_get_path('module', 'devel') . '/devel.js');
$path = './' . drupal_get_path('module', 'devel') . '/FirePHPCore/lib/FirePHPCore/fb.php';
if (file_exists($path)) {
include_once $path;
}
}
}
return $items;
}
function dfb() {
if (function_exists('fb') && user_access('access devel information')) {
$args = func_get_args();
call_user_func_array('fb', $args);
}
}
function devel_views_object($type, $view_name) {
$view = views_get_view($view_name);
$return = views_build_view($type, $view);
return devel_print_object($return);
}
function devel_init() {
if (strstr($_SERVER['PHP_SELF'], 'update.php') || strstr($_GET['q'], 'autocomplete') || $_GET['q'] == 'admin/content/node-settings/rebuild' || $_GET['q'] == 'upload/js' || substr($_GET['q'], 0, strlen('system/files')) == 'system/files') {
}
else {
if (function_exists('drupal_set_content')) {
if (user_access('access devel information')) {
drupal_add_css(drupal_get_path('module', 'devel') . '/devel.css');
$handler = variable_get('devel_error_handler', DEVEL_ERROR_HANDLER_STANDARD);
switch ($handler) {
case DEVEL_ERROR_HANDLER_STANDARD:
break;
case DEVEL_ERROR_HANDLER_BACKTRACE:
set_error_handler('backtrace_error_handler');
has_krumo();
break;
case DEVEL_ERROR_HANDLER_NONE:
restore_error_handler();
break;
}
}
}
else {
drupal_load('module', 'user');
}
register_shutdown_function('devel_shutdown');
if (variable_get('dev_mem', 0) && function_exists('memory_get_usage')) {
global $memory_init;
$memory_init = memory_get_usage();
}
}
}
function has_krumo() {
@(include_once './' . drupal_get_path('module', 'devel') . '/krumo/class.krumo.php');
if (function_exists('krumo') && php_sapi_name() != 'cli') {
return TRUE;
}
else {
return FALSE;
}
}
function backtrace_error_handler($errno, $message, $filename, $line) {
if (error_reporting() == 0) {
return;
}
if ($errno & (E_ALL ^ E_NOTICE)) {
$types = array(
1 => 'error',
2 => 'warning',
4 => 'parse error',
8 => 'notice',
16 => 'core error',
32 => 'core warning',
64 => 'compile error',
128 => 'compile warning',
256 => 'user error',
512 => 'user warning',
1024 => 'user notice',
2048 => 'strict warning',
4096 => 'recoverable error',
8192 => 'deprecated',
16384 => 'user deprecated',
);
$entry = $types[$errno] . ': ' . $message . ' in ' . $filename . ' on line ' . $line . '.';
if (variable_get('error_level', 1) == 1) {
$backtrace = debug_backtrace();
foreach ($backtrace as $call) {
$nicetrace[$call['function']] = $call;
}
krumo($nicetrace);
}
watchdog('php', t('%message in %file on line %line.', array(
'%error' => $types[$errno],
'%message' => $message,
'%file' => $filename,
'%line' => $line,
)), WATCHDOG_ERROR);
}
}
function devel_perm() {
return array(
'access devel information',
'execute php code',
'switch users',
);
}
function devel_block($op = 'list', $delta = 0, $edit = array()) {
if ($op == 'list') {
$blocks[0]['info'] = t('Switch user');
$blocks[1]['info'] = t('Devel');
$blocks[2]['info'] = t('Execute PHP');
return $blocks;
}
else {
if ($op == 'configure' && $delta == 0) {
$form['devel_switch_user_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',
);
return $form;
}
else {
if ($op == 'save' && $delta == 0) {
variable_set('devel_switch_user_list_size', $edit['devel_switch_user_list_size']);
}
else {
if ($op == 'view') {
switch ($delta) {
case 0:
$block['subject'] = t('Switch user');
$links = devel_switch_user_list();
if (!empty($links)) {
$block['content'] = theme('item_list', $links);
$block['content'] .= drupal_get_form('devel_switch_user_form');
}
break;
case 1:
$links = array();
$block['subject'] = t('devel');
if (user_access('access devel information')) {
$links[] = l('Devel settings', 'admin/settings/devel', array(
'title' => t('Adjust module settings for devel module'),
));
$links[] = l('Empty cache', 'devel/cache/clear', array(
'title' => t('Clear the database cache tables which store page, menu, node, and variable caches.'),
), drupal_get_destination());
$links[] = l('Execute PHP Code', 'devel/php', array(
'title' => t('Execute some PHP code'),
));
$links[] = l('Run cron', 'admin/logs/status/run-cron', array(
'title' => t('Execute functions scheduled for cron runs.'),
), drupal_get_destination());
$links[] = l('Phpinfo()', 'admin/logs/status/php');
$links[] = l('Function reference', 'devel/reference', array(
'title' => t('View a list of currently defined user functions with documentation links'),
));
$links[] = l('Reinstall modules', 'devel/reinstall', array(
'title' => t('Re-run hook_install() for a given module'),
));
$links[] = l('Reset menus', 'devel/menu/reset', array(
'title' => t('Resets all menu items to their default settings'),
));
$links[] = l('Variable editor', 'devel/variable', array(
'title' => t('Edit and delete site variables'),
));
$links[] = l('Session viewer', 'devel/session', array(
'title' => t('List the contents of $_SESSION'),
));
}
if (function_exists('devel_node_access_perm') && user_access(DNA_ACCESS_VIEW)) {
$links[] = l('Node access summary', 'devel/node_access/summary');
}
if ($links) {
$block['content'] = theme('item_list', $links);
}
break;
case 2:
if (user_access('execute php code')) {
$block['subject'] = t('Execute php');
$block['content'] = drupal_get_form('devel_execute_form');
}
break;
}
return $block;
}
}
}
}
}
function devel_switch_user_list() {
$links = array();
if (user_access('switch users')) {
$list_size = variable_get('devel_switch_user_list_size', 10);
$dest = drupal_get_destination();
$roles = user_roles(1, 'switch users');
if (isset($roles[2])) {
$users = db_query_range("SELECT DISTINCT u.uid, u.name, u.access FROM {users} u WHERE u.uid > 0 ORDER BY u.access DESC", 0, $list_size);
}
else {
$where = array(
'u.uid = 1',
);
if (count($roles)) {
$where[] = 'r.rid IN (' . implode(',', array_keys($roles)) . ')';
}
$where_sql = implode(' OR ', $where);
$users = db_query_range("SELECT DISTINCT u.uid, u.name, u.access FROM {users} u LEFT JOIN {users_roles} r ON u.uid = r.uid WHERE {$where_sql} ORDER BY u.access DESC", 0, $list_size);
}
while ($user = db_fetch_object($users)) {
$links[$user->uid] = l(theme('placeholder', $user->name), 'devel/switch/' . $user->name, array(
'title' => t('This user can switch back.'),
), $dest, NULL, FALSE, TRUE);
}
$num_links = count($links);
if ($num_links < $list_size) {
$users = db_query_range('SELECT uid, name, access FROM {users} WHERE uid > 0 AND uid NOT IN (' . implode(',', array_keys($links)) . ') ORDER BY access DESC', 0, $list_size - $num_links);
while (($user = db_fetch_object($users)) && count($links) < $list_size) {
$links[$user->uid] = l($user->name, 'devel/switch/' . $user->name, array(
'title' => t('Caution: this user will be unable to switch back.'),
), $dest);
}
}
}
return $links;
}
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'),
);
return $form;
}
function devel_switch_user_form_validate($form_id, $form_values) {
if (!($account = user_load(array(
'name' => $form_values['username'],
)))) {
form_set_error('username', t('Username not found'));
}
}
function devel_switch_user_form_submit($form_id, $form_values) {
return 'devel/switch/' . $form_values['username'];
}
function devel_form_alter($form_id, &$form, $key_in = NULL) {
if (user_access('access devel information') && variable_get('devel_form_weights', 0)) {
$children = element_children($form);
if (empty($children)) {
if (isset($form['#type']) && !in_array($form['#type'], array(
'value',
'hidden',
))) {
if (!isset($form['#title'])) {
$form['#title'] = '';
}
$form['#title'] .= " (key={$key_in}, weight=" . (isset($form['#weight']) ? $form['#weight'] : 0) . ')';
}
}
else {
foreach (element_children($form) as $key) {
if (element_children($form[$key])) {
if (!isset($form[$key]['#title'])) {
$form[$key]['#title'] = '';
}
$form[$key]['#title'] .= " (key={$key}, weight=" . (isset($form[$key]['#weight']) ? $form[$key]['#weight'] : 0) . ')';
}
devel_form_alter($form_id, $form[$key], $key);
}
}
}
}
function devel_exit($destination = NULL) {
global $user;
if (isset($destination)) {
if (isset($user) && function_exists('user_access') && user_access('access devel information') && variable_get('devel_redirect_page', 0)) {
$output = t('<p>The user is being redirected to <a href="@destination">@destination</a>.</p>', array(
'@destination' => $destination,
));
print theme('page', $output);
drupal_page_footer();
exit;
}
else {
return;
}
}
}
function devel_shutdown() {
global $queries, $memory_init, $user;
$output = '';
if ($GLOBALS['devel_shutdown'] !== FALSE) {
if (function_exists('drupal_get_headers')) {
$headers = drupal_get_headers();
$formats = array(
'xml',
'javascript',
'json',
'plain',
'image',
'application',
'x-comma-separated-values',
);
foreach ($formats as $format) {
if (strstr($headers, $format)) {
return;
}
}
}
if (empty($_SERVER['REQUEST_METHOD'])) {
return;
}
if (isset($user) && user_access('access devel information')) {
list($counts, $query_summary) = devel_query_summary();
if (!variable_get('devel_query_display', 0) && variable_get('dev_timer', 0)) {
$output = '<div class="dev-timer">' . devel_timer() . ' ' . $query_summary . '</div>';
}
$sum = 0;
if (variable_get('devel_query_display', FALSE)) {
$output .= '<div class="dev-query">';
$output .= $query_summary;
if (function_exists('theme_table')) {
$txt .= t(' Queries taking longer than %threshold ms and queries executed more than once, are <span class="marker">highlighted</span>.', array(
'%threshold' => variable_get('devel_execution', 5),
));
if (variable_get('dev_timer', 0)) {
$txt .= devel_timer();
}
$output .= $txt . devel_query_table($queries, $counts);
}
else {
$output .= $txt;
ob_start();
dprint_r($queries);
$output .= ob_get_clean();
}
$output .= '</div>';
}
if (variable_get('dev_mem', FALSE) && function_exists('memory_get_usage')) {
$memory_shutdown = memory_get_usage();
$list = array();
foreach (array(
'devel_init()' => $memory_init,
'devel_shutdown()' => $memory_shutdown,
) as $type => $value) {
$list[] = t('Memory used at %type: %value MB', array(
'%type' => $type,
'%value' => round($value / 1024 / 1024, 2),
));
}
$output .= '<div class="dev-memory-usage"><h3>' . 'Memory usage:' . '</h3>' . theme('item_list', $list) . '</div>';
}
if ($output) {
print $output;
}
}
}
devel_store_queries();
}
function devel_store_queries() {
if (variable_get('devel_store_queries', 0) && rand(1, variable_get('devel_store_random', 1)) == 1) {
global $active_db, $queries;
$qids = array();
$values = array();
$fields = array();
setlocale(LC_NUMERIC, 'C');
foreach ($queries as $value) {
list($function, $query) = explode("\n", $value[0]);
$query = preg_replace(array(
"/'.*'/s",
"/\\d.*\\.\\d.*/",
"/\\d.*/",
), array(
"S",
"F",
"D",
), $query);
$hash = md5($function . $query);
if (!isset($qids[$hash])) {
$qids[$hash] = db_result(devel_db_query("SELECT qid FROM {devel_queries} WHERE hash = '%s'", $hash));
if (!$qids[$hash]) {
devel_db_query("INSERT INTO {devel_queries} (query, function, hash) VALUES ('%s', '%s', '%s')", $query, $function, $hash);
$qids[$hash] = mysql_insert_id();
}
}
$fields[] = "(%d, '%f')";
$values[] = $qids[$hash];
$values[] = $value[1];
}
if (count($fields)) {
devel_db_query('INSERT INTO {devel_times} (qid, time) VALUES ' . implode(',', $fields), $values);
}
}
}
function devel_query_summary() {
global $queries;
if (variable_get('dev_query', FALSE) && is_array($queries)) {
foreach ($queries as $query) {
$text[] = $query[0];
$sum += $query[1];
}
$counts = array_count_values($text);
return array(
$counts,
t_safe('Executed %queries queries in %time milliseconds.', array(
'%queries' => count($queries),
'%time' => round($sum * 1000, 2),
)),
);
}
}
function t_safe($string) {
$args = func_get_args();
return function_exists('t') ? call_user_func_array('t', $args) : call_user_func_array('strtr', $args);
}
function devel_function_reference() {
$functions = get_defined_functions();
$ufunctions = $functions['user'];
sort($ufunctions);
foreach ($ufunctions as $function) {
if (class_exists('ReflectionFunction')) {
$func = new ReflectionFunction($function);
$isNotCore = stristr($func
->getFileName(), realpath($_SERVER['DOCUMENT_ROOT'] . '/sites')) ? true : false;
}
if (!$isNotCore) {
$links[] = l($function, "http://api.drupal.org/api/function/{$function}/" . DEVEL_CURRENT_DRUPAL_VERSION);
}
}
return theme('item_list', $links);
}
function devel_db_query($query) {
global $active_db;
$args = func_get_args();
array_shift($args);
$query = db_prefix_tables($query);
if (isset($args[0]) and is_array($args[0])) {
$args = $args[0];
}
_db_query_callback($args, TRUE);
$query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
return mysql_query($query, $active_db);
}
function devel_is_compatible_optimizer() {
ob_start();
phpinfo();
$info = ob_get_contents();
ob_end_clean();
$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;
}
}
function devel_admin_settings() {
$form['queries'] = array(
'#type' => 'fieldset',
'#title' => t('Query log'),
);
$description = t("Collect query info. If disabled, no query log functionality will work.");
if (!devel_is_compatible_optimizer()) {
$description = t('You must disable or upgrade the php Zend Optimizer extension in order to enable this feature. The minimum required version is 3.2.8. Earlier versions of Zend Optimizer are <a href="!url">horribly buggy and segfault your Apache</a> ... ', array(
'!url' => url('http://drupal.org/node/126098'),
)) . $description;
}
$form['queries']['dev_query'] = array(
'#type' => 'checkbox',
'#title' => t('Collect query info'),
'#default_value' => variable_get('dev_query', 0),
'#description' => $description,
'#disabled' => !devel_is_compatible_optimizer() ? TRUE : FALSE,
);
$form['queries']['devel_query_display'] = array(
'#type' => 'checkbox',
'#title' => t('Display query log'),
'#default_value' => variable_get('devel_query_display', 0),
'#description' => t('Display a log of the database queries needed to generate the current page, and the execution time for each. Also, queries which are repeated during a single page view are summed in the # column, and printed in red since they are candidates for caching.'),
);
$form['queries']['devel_query_sort'] = array(
'#type' => 'radios',
'#title' => t('Sort query log'),
'#default_value' => variable_get('devel_query_sort', DEVEL_QUERY_SORT_BY_SOURCE),
'#options' => array(
t('by source'),
t('by duration'),
),
'#description' => t('The query table can be sorted in the order that the queries were executed or by descending duration.'),
);
$form['queries']['devel_execution'] = array(
'#type' => 'textfield',
'#title' => t('Slow query highlighting'),
'#default_value' => variable_get('devel_execution', 5),
'#size' => 4,
'#maxlength' => 4,
'#description' => t('Enter an integer in milliseconds. Any query which takes longer than this many milliseconds will be highlighted in the query log. This indicates a possibly inefficient query, or a candidate for caching.'),
);
$form['queries']['devel_store_queries'] = array(
'#type' => 'checkbox',
'#title' => t('Store executed queries'),
'#default_value' => variable_get('devel_store_queries', 0),
'#description' => t('Store statistics about executed queries. See the devel_x tables. This feature is currently only available for the MySQL database backend.'),
);
$form['queries']['devel_store_random'] = array(
'#type' => 'textfield',
'#title' => t('Sampling interval'),
'#default_value' => variable_get('devel_store_random', 1),
'#size' => 4,
'#description' => t('If storing query statistics, only store every nth page view. 1 means every page view, 2 every second, and so on.'),
);
$form['dev_timer'] = array(
'#type' => 'checkbox',
'#title' => t('Display page timer'),
'#default_value' => variable_get('dev_timer', 0),
'#description' => t('Display page execution time in the query log box.'),
);
$form['dev_mem'] = array(
'#type' => 'checkbox',
'#title' => t('Display memory usage'),
'#default_value' => variable_get('dev_mem', 0),
'#description' => t('Display how much memory is used to generate the current page. This will show memory usage when devel_init() is called and when devel_exit() is called. PHP must have been compiled with the <em>--enable-memory-limit</em> configuration option for this feature to work.'),
);
$form['devel_redirect_page'] = array(
'#type' => 'checkbox',
'#title' => t('Display redirection page'),
'#default_value' => variable_get('devel_redirect_page', 0),
'#description' => t('When a module executes drupal_goto(), the query log and other developer information is lost. Enabling this setting presents an intermediate page to developers so that the log can be examined before continuing to the destination page.'),
);
$form['devel_form_weights'] = array(
'#type' => 'checkbox',
'#title' => t('Display form element keys and weights'),
'#default_value' => variable_get('devel_form_weights', 0),
'#description' => t('Form element names are needed for performing themeing or altering a form. Their weights determine the position of the element. Enabling this setting will show these keys and weights beside each form item.'),
);
$form['devel_error_handler'] = array(
'#type' => 'radios',
'#title' => t('Error handler'),
'#default_value' => variable_get('devel_error_handler', DEVEL_ERROR_HANDLER_STANDARD),
'#options' => array(
DEVEL_ERROR_HANDLER_NONE => t('None'),
DEVEL_ERROR_HANDLER_STANDARD => t('Standard drupal'),
DEVEL_ERROR_HANDLER_BACKTRACE => t('Backtrace'),
),
'#description' => t('Choose an error handler for your site. <em>Backtrace</em> prints nice debug information when an error is noticed, and you <a href="@choose">choose to show errors on screen</a>. <strong>Backtrace requires the <a href="@krumo">krumo library</a></strong>. <em>None</em> is a good option when stepping through the site in your debugger.', array(
'@krumo' => url('http://krumo.sourceforge.net'),
'@choose' => url('admin/settings/error-reporting'),
)),
);
if (variable_get('smtp_library', '') != '' && variable_get('smtp_library', '') != drupal_get_filename('module', 'devel')) {
variable_set('devel_old_smtp_library', variable_get('smtp_library', ''));
}
$smtp_options = array(
'' => t('Default'),
drupal_get_filename('module', 'devel') => t('Log only'),
);
if (variable_get('devel_old_smtp_library', '') != '') {
$smtp_options[variable_get('devel_old_smtp_library', '')] = t('Other (!library)', array(
'!library' => variable_get('devel_old_smtp_library', ''),
));
}
$form['smtp_library'] = array(
'#type' => 'radios',
'#title' => t('SMTP library'),
'#options' => $smtp_options,
'#default_value' => variable_get('smtp_library', ''),
);
return system_settings_form($form);
}
function devel_cache_clear() {
drupal_clear_css_cache();
$core = array(
'cache',
'cache_filter',
'cache_menu',
'cache_page',
);
$alltables = array_merge($core, module_invoke_all('devel_caches'));
foreach ($alltables as $table) {
cache_clear_all('*', $table, TRUE);
}
drupal_set_message('Cache cleared.');
drupal_goto();
}
function devel_execute_form() {
$form['code'] = array(
'#type' => 'textarea',
'#title' => t('PHP code to execute'),
'#description' => t('Enter some code. Do not use <code><?php ?></code> tags.'),
);
$form['op'] = array(
'#type' => 'submit',
'#value' => t('Execute'),
);
$form['#redirect'] = FALSE;
$form['#skip_duplicate_check'] = TRUE;
return $form;
}
function devel_execute_form_submit($form_id, $form) {
ob_start();
print eval($form['code']);
dsm(ob_get_clean());
}
function devel_menu_reset_form() {
return confirm_form(array(), t('Are you sure you want to reset all menu items to their default settings?'), 'admin/build/menu', t('Any custom additions or changes to the menu will be lost.'), t('Reset all'), t('Cancel'));
}
function devel_menu_reset_form_submit() {
db_query('DELETE FROM {menu}');
$mid = module_invoke('menu', 'edit_item_save', array(
'title' => t('Primary links'),
'pid' => 0,
'type' => MENU_CUSTOM_MENU,
));
variable_set('menu_primary_menu', $mid);
variable_set('menu_secondary_menu', $mid);
drupal_set_message(t('The menu items have been reset to their default settings.'));
return 'admin/build/menu';
}
function devel_forms() {
$forms = array();
if (user_access('access devel information')) {
$modules = module_list();
foreach ($modules as $module) {
$forms['devel_reinstall_' . $module]['callback'] = 'devel_reinstall_form';
}
}
return $forms;
}
function devel_reinstall_form($module) {
$form = array(
'#base' => 'devel_reinstall',
'submit' => array(
'#type' => 'submit',
'#value' => t('Reinstall @name module', array(
'@name' => $module,
)),
),
);
return $form;
}
function devel_reinstall() {
$output = '';
$modules = module_list();
sort($modules);
foreach ($modules as $module) {
$output .= drupal_get_form('devel_reinstall_' . $module, $module);
}
drupal_set_message(t('Warning - will delete your module tables and variables.'), 'error');
return $output;
}
function devel_reinstall_submit($form_id, $form_values) {
include_once './includes/install.inc';
$module = str_replace('devel_reinstall_', '', $form_id);
module_load_install($module);
$versions = drupal_get_schema_versions($module);
drupal_set_installed_schema_version($module, $versions ? max($versions) : SCHEMA_INSTALLED);
module_invoke($module, 'uninstall');
module_invoke($module, 'install');
drupal_set_message(t('Reinstalled the %name module.', array(
'%name' => $module,
)));
}
function devel_variable_page() {
$output = drupal_get_form('devel_variable');
print theme('page', $output, FALSE);
}
function devel_variable() {
$header = array(
array(
'',
),
array(
'data' => t('Name'),
'field' => 'name',
'sort' => 'asc',
),
array(
'data' => t('Value'),
'field' => 'value',
),
array(
'data' => t('Length'),
'field' => 'length',
),
array(
'data' => t('Operations'),
),
);
switch ($GLOBALS['db_type']) {
case 'mssql':
$sql = "SELECT *, COL_LENGTH('{variable}', 'value') AS length FROM {variable}";
break;
default:
$sql = "SELECT *, LENGTH(value) AS length FROM {variable}";
break;
}
$result = db_query($sql . tablesort_sql($header));
while ($row = db_fetch_object($result)) {
$variables[$row->name] = '';
$form['name'][$row->name] = array(
'#value' => check_plain($row->name),
);
if (has_krumo()) {
$value = krumo_ob(variable_get($row->name, NULL));
}
else {
if (drupal_strlen($row->value) > 70) {
$value = check_plain(drupal_substr($row->value, 0, 65)) . '...';
}
else {
$value = check_plain($row->value);
}
}
$form[$row->name]['value'] = array(
'#value' => $value,
);
$form[$row->name]['length'] = array(
'#value' => $row->length,
);
$form[$row->name]['edit'] = array(
'#value' => l(t('edit'), "devel/variable/edit/{$row->name}"),
);
}
$form['variables'] = array(
'#type' => 'checkboxes',
'#options' => $variables,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Delete'),
);
return $form;
}
function theme_devel_variable($form) {
$children = element_children($form['name']);
foreach ($children as $key) {
$rows[] = array(
drupal_render($form['variables'][$key]),
drupal_render($form['name'][$key]),
drupal_render($form[$key]['value']),
drupal_render($form[$key]['length']),
drupal_render($form[$key]['edit']),
);
}
$header = array(
theme('table_select_header_cell'),
array(
'data' => t('Name'),
'field' => 'name',
'sort' => 'asc',
),
array(
'data' => t('Value'),
'field' => 'value',
),
array(
'data' => t('Length'),
'field' => 'length',
),
array(
'data' => t('Operations'),
'colspan' => 2,
),
);
$output = theme('table', $header, $rows);
$output .= drupal_render($form);
return $output;
}
function devel_variable_submit($form_id, $form_values) {
$deletes = array_filter($form_values['variables']);
array_walk($deletes, 'variable_del');
drupal_set_message(format_plural(count($deletes), 'one variable deleted', '@count variables deleted'));
}
function devel_variable_edit($name) {
$value = variable_get($name, 'not found');
$form['name'] = array(
'#type' => 'value',
'#value' => $name,
);
$form['value'] = array(
'#type' => 'item',
'#title' => t('Old value'),
'#value' => dpr($value, TRUE),
);
if (is_string($value) || is_numeric($value)) {
$form['new'] = array(
'#type' => 'textarea',
'#title' => t('New value'),
'#default_value' => $value,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
}
else {
$form['new'] = array(
'#type' => 'item',
'#title' => t('New value'),
'#value' => t('Sorry, complex variable types may not be edited yet. Use the <em>Execute PHP</em> block and the <a href="@variable-set-doc">variable_set()</a> function.', array(
'@variable-set-doc' => 'http://api.drupal.org/api/HEAD/function/variable_set',
)),
);
}
drupal_set_title(check_plain($name));
return $form;
}
function devel_variable_edit_submit($form_id, $form_values) {
variable_set($form_values['name'], $form_values['new']);
drupal_set_message(t('Saved new value for %name', array(
'%name' => $form_values['name'],
)));
return 'devel/variable';
}
function devel_session() {
global $user;
$output = kprint_r($_SESSION, TRUE);
$headers = array(
t('Session name'),
t('Session ID'),
);
$output .= theme('table', $headers, array(
array(
session_name(),
session_id(),
),
));
return $output;
}
function devel_switch_user($name = NULL) {
global $user;
static $orig_user = array();
if (isset($name)) {
$user = user_load(array(
'name' => $name,
));
}
else {
if (count($orig_user)) {
$user = array_shift($orig_user);
array_unshift($orig_user, $user);
}
else {
$orig_user[] = $user;
}
}
drupal_goto();
}
function devel_load_object($type, $id) {
$output = '';
switch ($type) {
case 'node':
$object = node_load($id);
drupal_set_title(check_plain($object->title));
break;
case 'user':
$object = user_load(array(
'uid' => $id,
));
drupal_set_title(check_plain($object->name));
break;
case 'view':
$object = views_get_view($id);
drupal_set_title(check_plain($object->name));
}
return devel_print_object($object);
}
function devel_render_object($type, $id) {
$output = '';
switch ($type) {
case 'node':
$object = node_build_content(node_load($id), FALSE, FALSE);
drupal_set_title(check_plain($object->title));
break;
case 'user':
break;
}
return devel_print_object($object);
}
function kdevel_print_object($object, $prefix = NULL) {
return has_krumo() ? krumo_ob($object) : devel_print_object($object, $prefix);
}
function krumo_ob($object) {
ob_start();
krumo($object);
$output = ob_get_contents();
ob_end_clean();
return $output;
}
function devel_print_object($object) {
if (is_array($object) || is_object($object)) {
foreach ($object as $field => $value) {
if (is_null($value)) {
$printed_value = 'NULL';
}
else {
if (is_array($value) || is_object($value)) {
ob_start();
print_r($value);
$printed_value = ob_get_clean();
$printed_value = '<pre>' . check_plain($printed_value) . '</pre>';
}
else {
$printed_value = check_plain($value);
}
}
$output .= theme('box', $field, $printed_value);
}
}
else {
$output .= theme('box', 'Value', check_plain($object));
}
return $output;
}
function devel_query_table($queries, $counts) {
$header = array(
'ms',
'#',
'where',
'query',
);
$i = 0;
foreach ($queries as $query) {
$ar = explode("\n", $query[0]);
$function = array_shift($ar);
$count = isset($counts[$query[0]]) ? $counts[$query[0]] : 0;
$query[0] = join(' ', $ar);
$diff = round($query[1] * 1000, 2);
if ($diff > variable_get('devel_execution', 5)) {
$cell[$i][] = array(
'data' => $diff,
'class' => 'marker',
);
}
else {
$cell[$i][] = $diff;
}
if ($count > 1) {
$cell[$i][] = array(
'data' => $count,
'class' => 'marker',
);
}
else {
$cell[$i][] = $count;
}
$cell[$i][] = l($function, "http://api.drupal.org/api/HEAD/function/{$function}");
$cell[$i][] = check_plain($query[0]);
$i++;
unset($diff, $count);
}
if (variable_get('devel_query_sort', DEVEL_QUERY_SORT_BY_SOURCE)) {
usort($cell, '_devel_table_sort');
}
return theme('table', $header, $cell);
}
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;
}
function devel_timer() {
$time = timer_read('page');
return t(' Page execution time was %time ms.', array(
'%time' => $time,
));
}
function dargs($always = TRUE) {
static $printed;
if ($always || !$printed) {
$bt = debug_backtrace();
dsm($bt[1]['args']);
$printed = TRUE;
}
}
function dd($data, $label = NULL) {
return drupal_debug($data, $label);
}
function drupal_debug($data, $label = NULL) {
ob_start();
print_r($data);
$string = ob_get_clean();
if ($label) {
$out = $label . ': ' . $string;
}
else {
$out = $string;
}
$out .= "\n";
$file = file_directory_temp() . '/drupal_debug.txt';
if (file_put_contents($file, $out, FILE_APPEND) === FALSE) {
drupal_set_message(t('The file could not be written.'), 'error');
return FALSE;
}
}
function dpm($input, $name = NULL) {
if (user_access('access devel information')) {
$export = kprint_r($input, TRUE, $name);
drupal_set_message($export);
}
}
function dvm($input, $name = NULL) {
if (user_access('access devel information')) {
$export = dprint_r($input, TRUE, $name, 'var_dump', FALSE);
drupal_set_message($export);
}
}
function dsm($input, $name = NULL) {
dpm($input, $name);
}
function dpr($input, $return = FALSE, $name = NULL) {
return dprint_r($input, $return, $name);
}
function kpr($input, $return = FALSE, $name = NULL) {
return kprint_r($input, $return, $name);
}
function dvr($input, $return = FALSE, $name = NULL) {
return dprint_r($input, $return, $name, 'var_dump', FALSE);
}
function kprint_r($input, $return = FALSE, $name = NULL, $function = 'print_r') {
if (has_krumo()) {
if (user_access('access devel information')) {
return $return ? (isset($name) ? $name . ' => ' : '') . krumo_ob($input) : krumo($input);
}
}
else {
return dprint_r($input, $return, $name, $function);
}
}
function dprint_r($input, $return = FALSE, $name = NULL, $function = 'print_r', $check = TRUE) {
if (user_access('access devel information')) {
if ($name) {
$name .= ' => ';
}
ob_start();
$function($input);
$output = ob_get_clean();
if ($check) {
$output = check_plain($output);
}
if (count($input, COUNT_RECURSIVE) > DEVEL_MIN_TEXTAREA) {
if (has_krumo()) {
$printed_value = krumo_ob($input);
}
else {
$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;
}
}
}
function ddebug_backtrace() {
if (user_access('access devel information')) {
$trace = debug_backtrace();
array_shift($trace);
foreach ($trace as $key => $value) {
$rich_trace[$value['function']] = $value;
}
if (has_krumo()) {
print krumo($rich_trace);
}
else {
dprint_r($rich_trace);
}
}
}
function db_queryd($query) {
$args = func_get_args();
array_shift($args);
$query = db_prefix_tables($query);
if (isset($args[0]) and is_array($args[0])) {
$args = $args[0];
}
_db_query_callback($args, TRUE);
$query = preg_replace_callback(DB_QUERY_REGEXP, '_db_query_callback', $query);
return _db_query($query, 1);
}
if (variable_get('smtp_library', '') == drupal_get_filename('module', 'devel')) {
function drupal_mail_wrapper($mailkey, $to, $subject, $body, $from, $headers) {
$mimeheaders = array();
foreach ($headers as $name => $value) {
$mimeheaders[] = check_plain($name . ': ' . mime_header_encode($value));
}
watchdog('devel', t('Mail sent:<br />Key: %mailkey<br />To: %to<br />From: %from<br />Subject: %subject<br />Body: %body<br /><br />Additional headers: !header', array(
'%mailkey' => $mailkey,
'%to' => $to,
'%from' => $from,
'%subject' => $subject,
'%body' => $body,
'!header' => implode("<br />", $mimeheaders),
)));
return TRUE;
}
}
function devel_queries() {
$header = array(
array(
'data' => t('Total (ms)'),
'field' => 'total_time',
'sort' => 'desc',
),
array(
'data' => t('Average (ms)'),
'field' => 'average',
'sort' => 'desc',
),
array(
'data' => t('Std deviation (ms)'),
),
array(
'data' => t('Count'),
'field' => 'count',
),
array(
'data' => t('Function'),
'field' => 'q.function',
),
array(
'data' => t('Query'),
'field' => 'q.query',
),
);
$result = pager_query('SELECT q.qid, q.query, q.function, t.*, COUNT(t.qid) AS count, SUM(t.time) AS total_time, AVG(t.time) AS average, STDDEV(t.time) AS stddev FROM {devel_queries} q INNER JOIN {devel_times} t ON q.qid = t.qid GROUP BY t.qid ' . tablesort_sql($header), 30, 0, 'SELECT COUNT(qid) FROM {devel_queries}');
while ($log = db_fetch_object($result)) {
$rows[] = array(
round($log->total_time * 1000, 3),
round($log->average * 1000, 3),
round($log->stddev * 1000, 3),
$log->count,
$log->function,
check_plain($log->query),
);
}
drupal_set_title(check_plain($node->title));
$output = theme('table', $header, $rows);
$output .= theme('pager', NULL, 30, 0);
$output .= l(t('Delete collected query statistics'), 'devel/queries/empty');
print theme('page', $output, FALSE);
}
function devel_queries_empty() {
db_query('DELETE FROM {devel_queries}');
db_query('DELETE FROM {devel_times}');
drupal_set_message(t('Stored query statistics deleted.'));
drupal_goto('devel/queries');
}
function devel_rebuild_node_comment_statistics_page() {
devel_rebuild_node_comment_statistics();
drupal_set_message('node_comment_statistics table has been rebuilt.');
drupal_goto('admin');
}
function devel_rebuild_node_comment_statistics() {
$sql = "DELETE FROM {node_comment_statistics}";
db_query($sql);
$sql = "INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) (select nid, c.timestamp, name, uid, comment_count FROM {comments} c INNER JOIN (SELECT MAX(timestamp) AS timestamp, COUNT(*) AS comment_count FROM {comments} WHERE status=%d GROUP BY nid) as c2 ON c.timestamp=c2.timestamp)";
db_query($sql, COMMENT_PUBLISHED);
db_query_temporary("SELECT n.nid, n.changed, n.uid FROM {node} n LEFT JOIN {node_comment_statistics} c ON n.nid = c.nid WHERE c.comment_count IS NULL", 'missing_nids');
db_query("INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) SELECT n.nid, n.changed, NULL, n.uid, 0 FROM missing_nids n");
}
function sequence_reset($table, $column) {
$max = db_result(db_query("SELECT MAX({$column}) FROM {$table}"));
$max = $max ? $max + 1 : 2;
db_query("UPDATE {sequences} SET id = {$max} WHERE name='{$table}_{$column}'");
}
function devel_table_keys($tables, $verb = 'ENABLE') {
foreach ($tables as $table) {
db_query("ALTER TABLE {$table} {$verb} KEYS");
}
}
function wget($url, $file) {
if (file_exists($file)) {
return;
}
print "get: {$url}\n";
$ch = curl_init($url);
$fp = fopen($file, "w");
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
fclose($fp);
}