'. t('The sitedoc module allows a site admin to gather extensive information about their site. It may be printed or archived for configuration/change management purposes. It may also be used to add "fancy" and up-to-date information to other site documentation, such as a succession plan.') .'
'; break; case 'admin/settings/sitedoc/archive': $output = ''. t('The Site Documentation module may be run via Cron and the output HTML file archived to disk for future review. The options chosen on the main settings page will govern the data collected and reported.') .'
'; break; case 'admin/settings/sitedoc': $output = ''. t("The Site Documentation module's data collection and output is governed by these settings. Indented options are in effect only if the parent item is selected.") .'
'; } return $output; } /** * Implementation of hook_perm(). */ function sitedoc_perm() { return array('view site documentation'); } /** * Implementation of hook_menu(). */ function sitedoc_menu() { $items = array(); $items['admin/build/sitedoc'] = array( 'title' => 'Site documentation', 'description' => 'Show site documentation', 'page callback' => 'sitedoc_list', 'access arguments' => array('view site documentation'), ); $items['admin/settings/sitedoc'] = array( 'title' => 'Site documentation', 'description' => 'Set how Site Documentation works', 'page callback' => 'sitedoc_settings_page', 'access arguments' => array('view site documentation'), 'file' => 'sitedoc.admin.inc', ); $items['admin/settings/sitedoc/report'] = array( 'title' => 'Report', 'description' => 'Report settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('sitedoc_settings_form'), 'access arguments' => array('view site documentation'), 'type' => MENU_DEFAULT_LOCAL_TASK, 'file' => 'sitedoc.admin.inc', ); $items['admin/settings/sitedoc/archive'] = array( 'title' => 'Archive', 'access arguments' => array('view site documentation'), 'page callback' => 'drupal_get_form', 'page arguments' => array('sitedoc_archive_form'), 'description' => 'Set how Site Documentation archive works', 'weight' => 2, 'type' => MENU_LOCAL_TASK, 'file' => 'sitedoc.admin.inc', ); $items['admin/build/sitedoc_node_access_view'] = array( 'title' => 'Site documentation node access list', 'page callback' => 'sitedoc_node_access_view', 'page arguments' => array(arg(3)), 'access arguments' => array('view site documentation'), 'type' => MENU_CALLBACK, ); $items['sitedoc/vocabulary'] = array( 'title' => 'Site Documentation Term Count by Type', 'page callback' => 'sitedoc_term_count_by_type', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK ); $items['sitedoc/phpinfo'] = array( 'title' => 'Site Documentation PHP Information', 'page callback' => 'sitedoc_phpinfo', 'access arguments' => array('view site documentation'), 'type' => MENU_CALLBACK ); $items['sitedoc/table'] = array( 'title' => 'Table Contents', 'page callback' => 'sitedoc_show_table', 'access arguments' => array('view site documentation'), 'type' => MENU_CALLBACK ); return $items; } /** * Implementation of hook_init(). */ function sitedoc_init() { drupal_add_css(drupal_get_path('module', 'sitedoc') .'/sitedoc.css'); } /** * Implementation of hook_enable(). * * Set the default parameters. This is an easy way to reset the deaults - disable and re-enable. * * Parameters: None. * * Return: None. */ function sitedoc_enable() { $sitedoc_settings = array( 'drupal_section' => TRUE, 'kill_cron' => 0, /* kill long-running cron */ 'table_section' => TRUE, 'show_indexes' => FALSE, /* use SHOW INDEX on the tables */ 'optimize_tables' => FALSE, /* use OPTIMIZE to release overhead */ 'node_section' => FALSE, /* not on because of expense */ 'include_comment_count' => FALSE, /* comment count on nodes */ 'include_node_access' => FALSE, /* node access summary */ 'node_show_size' => 99999, /* show nodes exceeding x KB */ 'node_max_size' => 50, /* warn if nodes exceeding x KB */ 'module_section' => TRUE, 'module_suppress' => FALSE, /* exclude disabled modules */ 'module_sort_order' => 0, /* package, project, module */ 'content_section' => TRUE, 'vocabulary_section' => TRUE, 'orphan_term_node' => FALSE, /* not on to allow control */ 'delete_orphan_term_nodes' => FALSE, /* do not delete orphans */ 'theme_section' => TRUE, 'variables_section' => FALSE, /* not on because of expense */ 'block_section' => TRUE, 'block_warn' => TRUE, /* warn on missing theme */ 'block_delete' => FALSE, /* delete those orphan blocks */ 'roles_section' => TRUE, 'role_users' => TRUE, /* list users in roles */ 'role_perms_list' => FALSE, /* do role permissions as stream */ 'contacts_section' => TRUE, 'profile_fields_section' => FALSE, /* not on because of interest */ 'url_alias_section' => FALSE, /* not on because of expense */ 'input_format_section' => FALSE, /* not on because probably not wanted */ // Archive options 'archive_frequency' => 0, /* don't run */ 'archive_directory' => 'sitedoc', /* archive directory within file setting */ ); variable_set('sitedoc_settings', $sitedoc_settings); } /***********************/ /** main function **/ /***********************/ function sitedoc_list() { // Retrieve the settings and check if they have been settings page. $sitedoc_settings = variable_get('sitedoc_settings', array()); if ($sitedoc_settings == array()) { return t('It appears that you have not been to "administer >> site configuration" to set the Site Documentation settings. ') . l(t('Click here to do so.'), 'admin/settings/sitedoc'); } // Insert a wrapper division and a link back to the settings page. $output = ''. t('No orphan term_nodes found.') .'
'), '#value' => $orphans, ); $output .= theme('fieldset', $fieldset); } $output .= "'. t('No boxes found.') .'
'), ); $output .= theme('fieldset', $fieldset); $output .= "'. t('No profile fields found.') .'
'), ); $output .= theme('fieldset', $fieldset); $output .= "'."\n";
$output .= ''. t('Overview') ."\n"; $database_type = $db_types[$GLOBALS['db_type']]; $database_version = db_version(); $rows[] = array(t('Database type'), isset($database_type) ? $database_type : t('Unknown')); $vers = isset($database_version) ? $database_version : t('Unknown'); $rows[] = array(t('Version'), l($vers, 'admin/reportsstatus/sql')); $db = parse_url($db_url); // Don't show password $db['pass'] = str_repeat('•', strlen($db['pass'])); $dbrows = array(); foreach ($db as $key => $value) { $dbrows[] = array($key, $value); } $rows[] = array(t('Database URL'), theme('table', NULL, $dbrows)); $rows[] = array(t('Base URL'), $base_url); $rows[] = array(t('Database prefix'), empty($db_prefix) ? '- none -' : $db_prefix); $grants = db_result(db_query('SHOW GRANTS')); $privileges = trim(str_replace('GRANT', ' ', substr($grants, 0, strpos($grants, ' ON')))); $rows[] = array(t('Privileges'), $privileges); $output .= theme('table', $header, $rows) ."\n"; $output .= " | \n";
// Check if we have a version of MySql that supports the variable and status checks
// TODO: Can Postgres do something similar?
if (('MySQL' == $database_type && version_compare($database_version, '4.1.0', '>=')) || 'MySQLi' == $database_type) {
// The next two things are done as lists to
// a) simplify building the query,
// b) create the possibility of future settings page selection.
// Get selected variables from the database.
$variables_list = array(
'character_set_database',
'character_set_results',
'collation_connection',
'collation_database',
'collation_server',
'have_dynamic_loading',
'have_innodb',
'have_isam',
'have_query_cache',
'have_raid',
'max_connections',
'query_cache_size',
'query_cache_type',
);
$output .= _sitedoc_dbvars_list('VARIABLES', t('Selected Variables'), $variables_list, $database_version);
// Get selected status information from the database.
$variables_list = array(
'Qcache_free_memory',
'Qcache_hits',
'Qcache_not_cached',
'Qcache_queries_in_cache',
'Max_used_connections',
'Threads_running',
'Threads_cached',
'Threads_connected',
'Threads_created',
);
$output .= _sitedoc_dbvars_list('STATUS', t('Selected Status'), $variables_list, $database_version);
$output .= "
| '. t('Table') .' | ' .''. t('Engine') .' | ' .''. t('Version') .' | ' .''. t('Row Format') .' | ' .''. t('Rows') .' | ' .''. t('Data Length') .' | ' .''. t('Index Length') .' | ' .''. t('Overhead') .' | ' .''. t('Operation') .' | ' .'|||
|---|---|---|---|---|---|---|---|---|---|---|---|
| '. $table['Name'] .' | ' .''. $table['Engine'] .' | ' .''. $table['Version'] .' | ' .''. $table['Row_format'] .' | ' .''. $r .' | ' .''. $d .' | ' .''. $i .' | ' .''. ($table['Data_free'] ? $o : '') .' | ' .''. l(t('Show contents'), 'sitedoc/table/'. $table['Name'], array('title' => t("Display the contents of the '@table' table.", array('@table' => $table['Name'])))) .' | ' . (empty($table['Comment']) ? NULL : '|||
| '. t('Indexes') .': | '. _sitedoc_show_index($table['Name']) .' | '; } $statrpt .= '||||||||||
| ' .' | ---------- | ' .'---------- | ' .'---------- | ' .'---------- | ' .'|||||||
| total | ' .''. number_format($row_count) .' | ' .''. number_format($datalen) .' | ' .''. number_format($indexlen) .' | ' .''. number_format($overhead) .' | ' .'|||||||
"; $fieldset = array( '#title' => t('Table Status'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#value' => $statrpt, ); $output .= theme('fieldset', $fieldset); $totsize = $datalen + $indexlen; $kb = $totsize / 1024; $mb = $kb / 1024; $gb = $mb / 1024; $units = 'KB'; $howmany = $kb; if ($mb >= 1) { if ($gb >= 1) { $units = 'GB'; $howmany = $gb; } else { $units = 'MB'; $howmany = $mb; } } $output .= t('Total database size is !num !unit', array('!num' => sprintf('%.1f', $howmany), '!unit' => $units)) .'
'; drupal_set_message(t('!count tables found in !db.', array('!count' => $rows, '!db' => $actdb)), 'status'); return $output ."\n"; } /* * Helper function to show the index structure of a database table. */ function _sitedoc_show_index($table_name) { $output = null; $index_list = db_query('SHOW INDEX FROM '. $table_name); $indices = array(); $header = array(t('Key Name'), t('Columns'), t('Collation'), t('Cardinality')); while ($index = db_fetch_array($index_list)) { if ($index['Seq_in_index'] == 1) { $indices[$index['Key_name']] = array( 'name' => $index['Column_name'] . ($index['Sub_part'] ? ' ('. $index['Sub_part'] .')' : null), 'collation' => $index['Collation'], 'count' => $index['Cardinality'], ); } else { $indices[$index['Key_name']]['name'] .= ', '. $index['Column_name'] . ($index['Sub_part'] ? ' ('. $index['Sub_part'] .')' : null); } } if (count($indices)) { $rows = array(); foreach ($indices as $key_name => $values) { $rows[] = array($key_name, $values['name'], array('data' => $values['collation'], 'align' => 'center'), array('data' => $values['count'], 'align' => 'center') ); } return theme('table', $header, $rows); } else { return 'No index found. '. _sitedoc_img_warning(); } } /** * Helper function for database variable list */ function _sitedoc_dbvars_list($type, $title, $variables_list, $db_vers) { if (count($variables_list)) { $rows = array(); $output .= ''. t('Click on a column title to sort by that column.') .'
'. t('!count disabled modules excluded.', array('!count' => $disabled_count)) .'
'; } return $output ."\n"; } /** * Produce the Themes lists * * Parameters: * Which type of row to return * theme - get themes list * * Return: HTML string */ function sitedoc_get_system($type=null) { if (!$type) { return ''. t('No system table type specified.') .'
'; } $status = array('Disabled', 'Enabled'); $string = ucfirst(strtolower($type)); // This ORDER BY makes the list come out by directory the entry comes from. $result = db_query('SELECT s.name, s.filename, s.status FROM {system} s WHERE s.type=\'%s\' ORDER BY s.status DESC, s.name ASC', $type); $header = array($string, t('Path'), t('Status')); $rows = array(); while ($mod = db_fetch_array($result)) { $rows[] = array( ucfirst($mod['name']), $mod['filename'], $status[$mod['status']], ); } if (!empty($rows)) { drupal_set_message(t('!rows !type found.', array('!rows' => count($rows), '!type' => $string)), 'status'); $output .= theme('table', $header, $rows); } else { $output .= t('No entries found! Very curious.'); } return $output ."\n"; } /** * Produce the blocks list * * Parameters: * $warn - TRUE / FALSE to produce orphan warning message. * $delete - TRUE / FALSE to delete orphans. * * Return: HTML string */ function sitedoc_get_blocks($warn=TRUE, $delete=FALSE) { $status = array(); $status = array(t('disabled'), t('enabled')); $viz = array(t('Show except'), t('Show only'), t('Php')); $del = NULL; // Check if the table is missing an index. $indexes = db_fetch_array(db_query('SHOW INDEX FROM {blocks}')); if ($indexes == FALSE) { $index_msg = ' '. t('Performance may be improved by adding an index. See this discussion.', array('!url' => 'http://drupal.org/node/164532')); $msg_level = 'warning'; } else { $index_msg = NULL; $msg_level = 'status'; } // Get blocks from the Blocks table. $result = db_query('SELECT b.module, b.delta, b.theme, b.status, b.weight, b.region, b.custom, b.throttle, b.visibility, b.pages, b.title FROM {blocks} b ORDER BY b.theme, b.module, b.delta'); $header = array( t('Theme'), t('Module'), array('data' => t('Delta'), 'align' => 'center'), t('Name') .' /'. $del .'
'; } return $output ."\n"; } /** * Produce the boxes (manual blocks, additional data) list. * * Parameters: * $warn - TRUE / FALSE to produce orphan warning message. * $delete - TRUE / FALSE to delete orphans. * * Return: HTML string */ function sitedoc_get_boxes($warn=TRUE, $delete=FALSE) { $result = db_query('SELECT * FROM {boxes} b'); $output = NULL; $orphans = FALSE; $header = array( array('data' => 'Bid', 'class' => 'sitedoc_right'), t('Box Name'), array('data' => t('Format'), 'class' => 'sitedoc_right'), t('Body'), ); $rows = array(); while ($box = db_fetch_array($result)) { $info = $box['info']; $check_block = db_result(db_query_range("SELECT COUNT(theme) FROM {blocks} WHERE module='block' AND delta=%d", $box['bid'], 0, 1)); if ($check_block == 0) { $orphans = TRUE; $info .= 'Taxonomy'. t(' module not enabled') .'
'; } $hier = array(t('Disabled'), t('Single'), t('Multiple')); $vocabularies = taxonomy_get_vocabularies(); $rows = array(); $header = array( t('Name (vid)'), t('Content Types'), t('Description'), t('Help'), t('Hierarchy'), t('Terms'), t('Module'), t('Weight'), ); foreach ($vocabularies as $vocabulary) { $types = array(); foreach ($vocabulary->nodes as $type) { $types[] = $type; } $t = array(); if ($vocabulary->relations) { $t[] = t('related'); } if ($vocabulary->multiple) { $t[] = t('multi-select'); } if ($vocabulary->required) { $t[] = t('required'); } if ($vocabulary->tags) { $t[] = t('free-tag'); } $rows[] = array( 'name' => check_plain($vocabulary->name) .' ('. $vocabulary->vid .')', 'type' => implode(', ', $types), $vocabulary->description . _terms_list($vocabulary->vid), /* subroutine gets terms */ $vocabulary->help ? t('yes') : t('no'), $hier[$vocabulary->hierarchy], implode(', ', $t), $vocabulary->module, $vocabulary->weight, ); } $output .= theme('table', $header, $rows); return $output ."\n"; } // Helper function to get vocabulary term info. function _terms_list($vid) { $items = array(); $thead = array( t('Term (tid)'), array('data' => t('Count'), 'class' => 'sitedoc_right'), t('Description'), ); $terms = taxonomy_get_tree($vid); foreach ( $terms as $term ) { // This query should be very fast and includes unpublished nodes. $count = db_result(db_query('SELECT COUNT(nid) FROM {term_node} WHERE tid=%d', $term->tid)); // Don't show terms with 0 count. if ($count) { $items[] = array( $term->name .' ('. $term->tid .')', array('data' => $count, 'class' => 'sitedoc_right'), $term->description); } } return "\n". theme('table', $thead, $items); } /** * Produce a table of taxonomy term usage by content type. * This function is available only as a callable function; * it is not called within this module. * * Parameters: * vid - the vocabulary id to show. * * Return: HTML string */ function sitedoc_term_count_by_type($vid) { $vocab = taxonomy_vocabulary_load($vid); if (!$vocab->name) { drupal_set_message(t('Vocabulary not found.'), 'error'); return t('Vocabulary not found.'); } $output = 'Taxonomy'. t(' module not enabled') .'
'; } $tn = db_result(db_query('SELECT COUNT(DISTINCT(tn.nid)) FROM {term_node} tn')); $n = db_result(db_query('SELECT COUNT(DISTINCT(n.nid)) FROM {node} n')); if ($tn > $n) { drupal_set_message(t('There are !tn term_nodes but only !n nodes.', array('!tn' => $tn, '!n' => $n)), 'error'); } else { return ''. t('No orphan term_nodes found.') .'
'; } $header = array('nid', 'tid', 'term', 'vocab'); $rows = array(); $del = NULL; $result = db_query('SELECT tn.nid, tn.tid FROM {term_node} tn LEFT JOIN {node} n ON tn.nid=n.nid WHERE ISNULL(n.title) ORDER BY tn.nid, tn.tid'); while ($tn = db_fetch_array($result)) { $term = taxonomy_get_term($tn['tid']); $vocab = taxonomy_vocabulary_load($tn['tid']); $delsql .= 'DELETE FROM {term_node} WHERE term_node.nid='. $tn['nid'] .' AND term_node.tid='. $tn['tid']; if ($delete_orphans) { db_query($delsql); drupal_set_message(t('Deleted term_node ') .'nid='. $tn['nid'] .', tid='. $tn['tid'], 'status'); } else { $del .= $delsql; } $rows[] = array($tn['nid'], $tn['tid'], $term->name, $vocab->name, $del); } $output = theme('table', $header, $rows); if (!$delete_orphans) { $output .= $del; } return $output ."\n"; } /** * Produce the node summary. * * Parameters: * TRUE - include comments count. * FALSE - don't include comments count. * * Return: HTML string */ function sitedoc_node_summary($comment=FALSE, $show_size=99999, $max_size=99999) { $sql = "SELECT n.nid, n.title, n.type, n.status, n.promote, n.moderate, n.sticky, length(body) AS node_len"; if ($comment) { $sql .= ", c.comment_count"; } $sql .= " FROM {node} n LEFT JOIN {node_revisions} nr ON nr.vid=n.vid"; if ($comment) { $sql .= " LEFT JOIN {node_comment_statistics} c ON c.nid=n.nid"; } $result = db_query($sql); $counters = array(); $types = array(); $weight_detected = FALSE; $toobig = 0; $biggies = array(); while ($node = db_fetch_object($result)) { $node_kb = $node->node_len / 1024; if ($node_kb >= $show_size) { $biggies[] = array( l($node->title, 'node/'. $node->nid .'/edit'), array('data' => number_format($node_kb, 2), 'align' => 'center')); } /* end if show size */ if ($node_kb >= $max_size) { ++$toobig; } if (!in_array($node->type, $types)) { $types[] = $node->type; } $counters[$node->type]['type'] ++; if ($node->status) { ++$counters[$node->type]['published']; } if ($node->promote) { ++$counters[$node->type]['promoted']; } if ($node->moderate) { ++$counters[$node->type]['moderated']; } if ($comment) { $counters[$node->type]['comments'] += $node->comment_count; } /* check if the weight module algorithm is in use */ if ($node->sticky > 1 || $node->sticky < 0) { _decode_sticky($node); if (!$weight_detected) { $weight_detected = TRUE; drupal_set_message(t('Weight-encoded in sticky field has been detected.'), 'status'); } } else { $node->weight = 0; /* set unweighted if not */ } if ($node->sticky) { ++$counters[$node->type]['sticky']; } if ($node->weight <> 0) { ++$counters[$node->type]['weight']; } } /* end while fetch */ ksort($types); $header = array( t('Type'), array('data' => t('Count'), 'class' => 'sitedoc_right'), array('data' => t('Published'), 'class' => 'sitedoc_right'), array('data' => t('Promoted'), 'class' => 'sitedoc_right'), array('data' => t('Sticky'), 'class' => 'sitedoc_right'), array('data' => t('Weighted'), 'class' => 'sitedoc_right'), array('data' => t('Moderated'), 'class' => 'sitedoc_right'), $comment ? array('data' => t('Comments'), 'class' => 'sitedoc_right') : NULL, ); $rows = array(); $tot = 0; $pub = 0; $pro = 0; $sti = 0; $mod = 0; foreach ($types as $type) { $rows[] = array( $type, array('data' => $counters[$type]['type'], 'class' => 'sitedoc_right'), array('data' => $counters[$type]['published'], 'class' => 'sitedoc_right'), array('data' => $counters[$type]['promoted'], 'class' => 'sitedoc_right'), array('data' => $counters[$type]['sticky'], 'class' => 'sitedoc_right'), array('data' => $counters[$type]['weight'], 'class' => 'sitedoc_right'), array('data' => $counters[$type]['moderated'], 'class' => 'sitedoc_right'), $comment ? array('data' => $counters[$type]['comments'], 'class' => 'sitedoc_right') : NULL, ); $tot += $counters[$type]['type']; $pub += $counters[$type]['published']; $pro += $counters[$type]['promoted']; $sti += $counters[$type]['sticky']; $wei += $counters[$type]['weight']; $mod += $counters[$type]['moderated']; $com += $counters[$type]['comments']; } /* end foreach type */ $rows[] = array( '', array('data' => '------', 'class' => 'sitedoc_right'), array('data' => '------', 'class' => 'sitedoc_right'), array('data' => '------', 'class' => 'sitedoc_right'), array('data' => '------', 'class' => 'sitedoc_right'), array('data' => '------', 'class' => 'sitedoc_right'), array('data' => '------', 'class' => 'sitedoc_right'), $comment ? array('data' => '------', 'class' => 'sitedoc_right') : NULL, ); $rows[] = array( ''. t('total') .'', array('data' => $tot, 'class' => 'sitedoc_right'), array('data' => $pub, 'class' => 'sitedoc_right'), array('data' => $pro, 'class' => 'sitedoc_right'), array('data' => $sti, 'class' => 'sitedoc_right'), array('data' => $wei, 'class' => 'sitedoc_right'), array('data' => $mod, 'class' => 'sitedoc_right'), $comment ? array('data' => $com, 'class' => 'sitedoc_right') : NULL, ); drupal_set_message(t('!count nodes found.', array('!count' => $tot)), 'status'); $output .= theme('table', $header, $rows); if ($toobig) { $output .= ''. _sitedoc_img_warning() .' '. t('!count nodes exceed !size KB.', array('!count' => $toobig, '!size' => $max_size)) .'
'; } else { $output .= ''. _sitedoc_img_ok() .' ' . t('No nodes exceed !size KB.', array('!size' => $max_size)) .'
'; } if (!empty($biggies)) { $big_head = array(t('Title'), t('Length (KB)')); $fieldset = array( '#title' => t('Large Nodes'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#value' => theme('table', $big_head, $biggies), ); $output .= theme('fieldset', $fieldset); } return $output ."\n"; } // Helper module in case weight module algorithm is used. function _decode_sticky(&$node) { $sticky = $node->sticky; /* save value */ $node->sticky = ($sticky > 0) ? 1 : 0; $node->weight = ($sticky > 0) ? 100 - $sticky : -100 - $sticky; return; } /** * Produce the node access summary. * * Parameters: * None * * Return: HTML string. */ function sitedoc_node_access() { // How many nodes are not represented in the node_access table. $result = db_fetch_object(db_query('SELECT COUNT(n.nid) as num_nodes FROM {node} n LEFT JOIN {node_access} na ON n.nid = na.nid WHERE na.nid IS NULL')); if ($num = $result->num_nodes) { $output .= ''. _sitedoc_img_warning() .' ' . t('You have !num nodes in your node table which are not represented in your node_access table. If you have an access control module installed, these nodes may be hidden from all users. This could be caused by publishing nodes before enabling the access control module. If this is the case, manually updating each node should add it to the node_access table and fix the problem. Click here to !rebuild.', array('!num' => l($num, 'admin/build/sitedoc_node_access_view/'), '!rebuild' => l(t('rebuild permissions'), 'admin/content/node-settings/rebuild'))) ."
\n"; } else { $output .= ''. _sitedoc_img_ok() . t('All nodes are represented in the node_access table.') ."
\n"; } /* end else */ // Warn user if they have any entries that could grant access to all nodes. $rows = array(); $result = db_query('SELECT DISTINCT na.realm FROM {node_access} na WHERE na.nid=0 AND na.gid=0'); while ($row = db_fetch_object($result)) { $rows[] = $row->realm; } if (!empty($rows)) { $output .= ''. t('Your node_access table contains entries (!r) that may be granting all users access to all nodes. Depending on which access control module(s) you use, you may want to delete these entries. If you are not using an access control module, you should probably leave these entries as is.', array('!r' => implode(', ', $rows))) ."
\n"; } $headers = array(t('realm')); $rows = array(); // A similar warning to the one above, but slightly more specific. $result = db_query('SELECT DISTINCT(na.realm) FROM {node_access} na WHERE na.nid=0 AND na.gid<>0'); while ($row = db_fetch_object($result)) { $rows[] = array($row->realm); } /* end while */ if (!empty($rows)) { $output .= ''. t('Your node_access table contains entries that may be granting some users access to all nodes. This may be normal, depending on which access control module(s) you use.') ."
\n"; $output .= theme('table', $header, $rows); } /* end all nodes */ $header = array(t('Realm'), t('Nodes'), t('Notes')); $rows = array(); // Count nodes by realm. $result = db_query('SELECT DISTINCT na.realm, COUNT(DISTINCT na.nid) as node_count FROM {node_access} na GROUP BY na.realm'); $all = FALSE; while ($row = db_fetch_object($result)) { if ($row->realm == 'all') { $all = TRUE; $realm_type = t('Public nodes'); $caption = t('This realm grants all users access to some specific nodes. If some of your content is available to the public, this may be normal.'); } else { $realm_type = t('Private nodes'); $caption = t('This realm grants limited access to some specific nodes.'); } $rows[] = array($row->realm, l($row->node_count, 'admin/build/sitedoc_node_access_view/'. $row->realm) .' '. $realm_type, $caption); } /* end while */ if ($all && !empty($rows)) { $output .= theme('table', $header, $rows); } return $output ."\n"; } /** * Menu call back to produce a list of nodes within a given access realm. * * parameters: * realm name * * returns: * HTML string */ function sitedoc_node_access_view($realm=NULL) { $rows = array(); $header = array( t('Type'), t('Title') .' '. t('click to edit') .'', ); $sql = 'SELECT DISTINCT(n.nid), n.type, n.title FROM {node} n LEFT JOIN {node_access} na ON n.nid = na.nid WHERE na.realm '; $count = 'SELECT COUNT(DISTINCT(n.nid)) FROM {node} n LEFT JOIN {node_access} na ON n.nid = na.nid WHERE na.realm '; if (is_null($realm)) { $output .= 'Contact'. t(' module not enabled') .'
'; } $sql = 'SELECT * FROM {contact} c ORDER BY c.selected DESC, c.cid ASC'; $result = db_query($sql); $header = array( array('data' => 'Cid', 'class' => 'sitedoc_right'), t('Category'), t('Recipients'), array('data' => t('Weight'), 'class' => 'sitedoc_right'), array('data' => t('Selected'), 'align' => 'center'), ); $rows = array(); while ($contact = db_fetch_object($result)) { $recips = explode(',', $contact->recipients); if (count($recips) > 1) { $recip_list = theme('item_list', $recips); } else { $recip_list = $contact->recipients; } $rows[] = array( array('data' => $contact->cid, 'class' => 'sitedoc_right'), $contact->category, $recip_list, array('data' => $contact->weight, 'class' => 'sitedoc_right'), array('data' => $contact->selected ? 'yes' : 'no', 'align' => 'center'), ); } /* end while role */ $howmany = count($rows); if ($howmany > 0) { drupal_set_message(t('!count Contacts found.', array('!count' => $howmany)), 'status'); $output = theme('table', $header, $rows); } return $output ."\n"; } /** * Produce the user profile fields list. * * Parameters: * string - limits the list to only this category * * Return: HTML string */ function sitedoc_profile_fields() { if (!module_exists('profile')) { return 'Profile '. t('module not enabled') .'
'; } $output = NULL; // Allow an optional param to limit the display to a specific category. if (func_num_args() > 0) { $category = func_get_arg(0); } $no_yes = array(t('No'), t('Yes')); $viz = array(t('Hidden'), t('Private'), t('Profile'), t('Public')); // This is to save display space. $short_type = array( 'textfield' => t('Text'), 'textarea' => t('Area'), 'URL' => t('URL'), 'checkbox' => t('Check'), 'selection' => t('select'), 'list' => t('Free'), 'date' => t('Date'), ); $header = array( array('data' => t('Fid'), 'class' => 'sitedoc_right'), t('Title'), t('Name'), t('Explanation'), t('Page'), t('Type'), array('data' => t('Weight'), 'class' => 'sitedoc_right'), array('data' => t('Visiblity'), 'align' => 'center'), array('data' => t('Required'), 'align' => 'center'), array('data' => t('Register'), 'align' => 'center'), array('data' => t('Auto complete'), 'align' => 'center'), t('Options'), ); if ($category) { $where = " WHERE p.category='$category'"; } else { $where = ' '; } $result = db_query('SELECT * FROM {profile_fields} p'. $where .' ORDER BY p.category, p.weight, p.name'); $save_cat = ''; while ($field = db_fetch_object($result)) { if ($field->category <> $save_cat) { // Flush previous rows, if any. if (!empty($save_cat)) { $output .= theme('table', $header, $rows); } $output .= 'Path '. t('module not enabled') .'
'; } $output = NULL; $rows = array(); $last_src = NULL; $problems = 0; // For reverse checking. $node_alias = array(); $header = array( array('data' => t('pid'), 'class' => 'sitedoc_right'), t('Source'), t('Destination'), t('Notes'), t('Operation'), ); $result = db_query('SELECT u.pid, u.src, u.dst FROM {url_alias} u ORDER BY u.src, u.dst'); while ($path = db_fetch_object($result)) { $notes = array(); $ops = array(); if ($last_src == $path->src) { $notes[] = t('duplicate source'); } else { $last_src = $path->src; } // Ignore "special" paths. if (substr($path->src, 0, 1) != '<') { $p = explode('/', $path->src); $edit = 'edit'; // So pseudo HTML shows (like| ". t('Format') .' | ' .''. t('Name') .' | ' .''. t('Roles') .' | ' .''. t('Cache') .' | ' .''. t('Filters') .' | ' ."\n||||||
|---|---|---|---|---|---|---|---|---|---|---|
| ". t('Name (Module, Delta)') .' | '. t('No Cache') .' | '. t('Weight') .' |
|---|---|---|
| '. ucwords($filter_list[$module][$delta]['name']) .' ('. ucwords($module) .', '. $delta .') | ' .''. (module_invoke($module, 'filter', 'no cache', $delta, $format) ? 'True' : null) .' | ' .''. $filter['weight'] .' | ' .'
| '. $delta .' | '. $name .' | '. $values['desc'] .' |