? .DS_Store
? statistics_00.patch
? modules/.DS_Store
? sites/.DS_Store
? sites/default/files
? sites/default/settings.php
Index: includes/common.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/common.inc,v
retrieving revision 1.855
diff -u -p -r1.855 common.inc
--- includes/common.inc	22 Jan 2009 05:01:39 -0000	1.855
+++ includes/common.inc	22 Jan 2009 23:35:55 -0000
@@ -3468,6 +3468,10 @@ function drupal_common_theme() {
       'arguments' => array('form' => NULL),
     ),
     // from menu.inc
+    'menu_list' => array(
+      'arguments' => array('items' => array(), 'class' => NULL),
+    ),
+
     'menu_item_link' => array(
       'arguments' => array('item' => NULL),
     ),
Index: includes/menu.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/menu.inc,v
retrieving revision 1.310
diff -u -p -r1.310 menu.inc
--- includes/menu.inc	4 Jan 2009 20:04:32 -0000	1.310
+++ includes/menu.inc	22 Jan 2009 23:35:55 -0000
@@ -1222,6 +1222,49 @@ function _menu_tree_data($result, $paren
 }
 
 /**
+ * List a menu item's children.
+ *
+ * @param $class
+ *   A class that is passed on to theme_menu_list().
+ *
+ * @return string
+ */
+function menu_list($class) {
+  $item = menu_get_item();
+  $items = system_admin_menu_block($item);
+  // Bypass the listing if only one child is available.
+  if (count($items) == 1) {
+    $item = array_shift($items);
+    drupal_goto($item['href']);
+  }
+  return theme('menu_list', $items, $class);
+}
+
+/**
+ * Theme a list of menu items.
+ *
+ * @param $items
+ *   The items as returned from system_admin_menu_block().
+ * @param $class
+ *   A CSS class that is applied to the list.
+ *
+ * @return string
+ */
+function theme_menu_list($items, $class) {
+  $output = '';
+
+  if ($items) {
+    $output = '<dl class="' . $class . '-menu-list">';
+    foreach ($items as $item) {
+      $output .= '<dt>' . l($item['title'], $item['href'], $item['localized_options']) . '</dt>';
+      $output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>';
+    }
+    $output .= '</dl>';
+  }
+  return $output;
+}
+
+/**
  * Generate the HTML output for a single menu link.
  *
  * @ingroup themeable
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1018
diff -u -p -r1.1018 node.module
--- modules/node/node.module	22 Jan 2009 12:46:06 -0000	1.1018
+++ modules/node/node.module	22 Jan 2009 23:35:57 -0000
@@ -117,10 +117,6 @@ function node_theme() {
       'arguments' => array('form' => NULL),
       'file' => 'node.admin.inc',
     ),
-    'node_add_list' => array(
-      'arguments' => array('content' => NULL),
-      'file' => 'node.pages.inc',
-    ),
     'node_form' => array(
       'arguments' => array('form' => NULL),
       'file' => 'node.pages.inc',
@@ -1656,7 +1652,8 @@ function node_menu() {
   );
   $items['node/add'] = array(
     'title' => 'Create content',
-    'page callback' => 'node_add_page',
+    'page callback' => 'menu_list',
+    'page arguments' => array('node-add'),
     'access callback' => '_node_add_access',
     'weight' => 1,
   );
Index: modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.50
diff -u -p -r1.50 node.pages.inc
--- modules/node/node.pages.inc	22 Jan 2009 12:04:27 -0000	1.50
+++ modules/node/node.pages.inc	22 Jan 2009 23:35:57 -0000
@@ -15,37 +15,6 @@ function node_page_edit($node) {
   return drupal_get_form($node->type . '_node_form', $node);
 }
 
-function node_add_page() {
-  $item = menu_get_item();
-  $content = system_admin_menu_block($item);
-  // Bypass the node/add listing if only one content type is available.
-  if (count($content) == 1) {
-    $item = array_shift($content);
-    drupal_goto($item['href']);
-  }
-  return theme('node_add_list', $content);
-}
-
-/**
- * Display the list of available node types for node creation.
- *
- * @ingroup themeable
- */
-function theme_node_add_list($content) {
-  $output = '';
-
-  if ($content) {
-    $output = '<dl class="node-type-list">';
-    foreach ($content as $item) {
-      $output .= '<dt>' . l($item['title'], $item['href'], $item['localized_options']) . '</dt>';
-      $output .= '<dd>' . filter_xss_admin($item['description']) . '</dd>';
-    }
-    $output .= '</dl>';
-  }
-  return $output;
-}
-
-
 /**
  * Present a node submission form or a set of links to such forms.
  */
Index: modules/statistics/statistics.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.admin.inc,v
retrieving revision 1.17
diff -u -p -r1.17 statistics.admin.inc
--- modules/statistics/statistics.admin.inc	22 Jan 2009 12:01:24 -0000	1.17
+++ modules/statistics/statistics.admin.inc	22 Jan 2009 23:35:57 -0000
@@ -7,174 +7,6 @@
  */
 
 /**
- * Menu callback; presents the "recent hits" page.
- */
-function statistics_recent_hits() {
-  $header = array(
-    array('data' => t('Timestamp'), 'field' => 'a.timestamp', 'sort' => 'desc'),
-    array('data' => t('Page'), 'field' => 'a.path'),
-    array('data' => t('User'), 'field' => 'u.name'),
-    array('data' => t('Operations'))
-  );
-
-  $sql = 'SELECT a.aid, a.path, a.title, a.uid, u.name, a.timestamp FROM {accesslog} a LEFT JOIN {users} u ON u.uid = a.uid' . tablesort_sql($header);
-
-  $result = pager_query($sql, 30);
-  $rows = array();
-  while ($log = db_fetch_object($result)) {
-    $rows[] = array(
-      array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
-      _statistics_format_item($log->title, $log->path),
-      theme('username', $log),
-      l(t('details'), "admin/reports/access/$log->aid"));
-  }
-
-  if (empty($rows)) {
-    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 4));
-  }
-
-  $output = theme('table', $header, $rows);
-  $output .= theme('pager', NULL, 30, 0);
-  return $output;
-}
-
-/**
- * Menu callback; presents the "top pages" page.
- */
-function statistics_top_pages() {
-  // MAX(title) avoids having empty node titles which otherwise causes duplicates in the top pages list
-  $sql = "SELECT COUNT(path) AS hits, path, MAX(title) AS title, AVG(timer) AS average_time, SUM(timer) AS total_time FROM {accesslog} GROUP BY path";
-  $sql_cnt = "SELECT COUNT(DISTINCT(path)) FROM {accesslog}";
-
-  $header = array(
-    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
-    array('data' => t('Page'), 'field' => 'path'),
-    array('data' => t('Average page generation time'), 'field' => 'average_time'),
-    array('data' => t('Total page generation time'), 'field' => 'total_time')
-  );
-  $sql .= tablesort_sql($header);
-  $result = pager_query($sql, 30, 0, $sql_cnt);
-
-  $rows = array();
-  while ($page = db_fetch_object($result)) {
-    $rows[] = array($page->hits, _statistics_format_item($page->title, $page->path), t('%time ms', array('%time' => round($page->average_time))), format_interval(round($page->total_time / 1000)));
-  }
-
-  if (empty($rows)) {
-    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 4));
-  }
-
-  drupal_set_title(t('Top pages in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
-  $output = theme('table', $header, $rows);
-  $output .= theme('pager', NULL, 30, 0);
-  return $output;
-}
-
-/**
- * Menu callback; presents the "top visitors" page.
- */
-function statistics_top_visitors() {
-
-  $header = array(
-    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
-    array('data' => t('Visitor'), 'field' => 'u.name'),
-    array('data' => t('Total page generation time'), 'field' => 'total'),
-    array('data' => user_access('block IP addresses') ? t('Operations') : '', 'colspan' => 2),
-  );
-
-  $sql = "SELECT COUNT(a.uid) AS hits, a.uid, u.name, a.hostname, SUM(a.timer) AS total, bl.iid FROM {accesslog} a LEFT JOIN {blocked_ips} bl ON a.hostname = bl.ip LEFT JOIN {users} u ON a.uid = u.uid GROUP BY a.hostname, a.uid, u.name, bl.iid" . tablesort_sql($header);
-  $sql_cnt = "SELECT COUNT(DISTINCT(CONCAT(CAST(uid AS char), hostname))) FROM {accesslog}";
-  $result = pager_query($sql, 30, 0, $sql_cnt);
-
-  $rows = array();
-  while ($account = db_fetch_object($result)) {
-    $qs = drupal_get_destination();
-    $ban_link =  $account->iid ? l(t('unblock IP address'), "admin/settings/ip-blocking/delete/$account->iid", array('query' => $qs)) : l(t('block IP address'), "admin/settings/ip-blocking/$account->hostname", array('query' => $qs));
-    $rows[] = array($account->hits, ($account->uid ? theme('username', $account) : $account->hostname), format_interval(round($account->total / 1000)), (user_access('block IP addresses') && !$account->uid) ? $ban_link : '');
-  }
-
-  if (empty($rows)) {
-    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 4));
-  }
-
-  drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
-  $output = theme('table', $header, $rows);
-  $output .= theme('pager', NULL, 30, 0);
-  return $output;
-}
-
-/**
- * Menu callback; presents the "referrer" page.
- */
-function statistics_top_referrers() {
-  $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE :host AND url <> '' GROUP BY url";
-  $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE :host";
-  drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
-
-  $header = array(
-    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
-    array('data' => t('Url'), 'field' => 'url'),
-    array('data' => t('Last visit'), 'field' => 'last'),
-  );
-
-  $query .= tablesort_sql($header);
-  $result = pager_query($query, 30, 0, $query_cnt, array(':host' => '%'. $_SERVER['HTTP_HOST'] .'%'));
-
-  $rows = array();
-  while ($referrer = db_fetch_object($result)) {
-    $rows[] = array($referrer->hits, _statistics_link($referrer->url), t('@time ago', array('@time' => format_interval(REQUEST_TIME - $referrer->last))));
-  }
-
-  if (empty($rows)) {
-    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 3));
-  }
-
-  $output = theme('table', $header, $rows);
-  $output .= theme('pager', NULL, 30, 0);
-  return $output;
-}
-
-/**
- * Menu callback; Displays recent page accesses.
- */
-function statistics_access_log($aid) {
-  $result = db_query('SELECT a.*, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE aid = %d', $aid);
-  if ($access = db_fetch_object($result)) {
-    $rows[] = array(
-      array('data' => t('URL'), 'header' => TRUE),
-      l(url($access->path, array('absolute' => TRUE)), $access->path)
-    );
-    // It is safe to avoid filtering $access->title through check_plain because
-    // it comes from drupal_get_title().
-    $rows[] = array(
-      array('data' => t('Title'), 'header' => TRUE),
-      $access->title
-    );
-    $rows[] = array(
-      array('data' => t('Referrer'), 'header' => TRUE),
-      ($access->url ? l($access->url, $access->url) : '')
-    );
-    $rows[] = array(
-      array('data' => t('Date'), 'header' => TRUE),
-      format_date($access->timestamp, 'large')
-    );
-    $rows[] = array(
-      array('data' => t('User'), 'header' => TRUE),
-      theme('username', $access)
-    );
-    $rows[] = array(
-      array('data' => t('Hostname'), 'header' => TRUE),
-      check_plain($access->hostname)
-    );
-
-    return theme('table', array(), $rows);
-  }
-  else {
-    drupal_not_found();
-  }
-}
-
-/**
  * Form builder; Configure access logging.
  *
  * @ingroup forms
Index: modules/statistics/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v
retrieving revision 1.295
diff -u -p -r1.295 statistics.module
--- modules/statistics/statistics.module	22 Jan 2009 12:46:07 -0000	1.295
+++ modules/statistics/statistics.module	22 Jan 2009 23:35:57 -0000
@@ -122,33 +122,40 @@ function statistics_nodeapi_view($node, 
  * Implementation of hook_menu().
  */
 function statistics_menu() {
-  $items['admin/reports/hits'] = array(
+  $items['statistics'] = array(
+    'title' => 'Statistics',
+    'description' => 'View statistics.',
+    'page callback' => 'menu_list',
+    'page arguments' => array('statistics'),
+    'access arguments' => array('access statistics'),
+  );
+  $items['statistics/hits'] = array(
     'title' => 'Recent hits',
     'description' => 'View pages that have recently been visited.',
     'page callback' => 'statistics_recent_hits',
     'access arguments' => array('access statistics'),
   );
-  $items['admin/reports/pages'] = array(
+  $items['statistics/pages'] = array(
     'title' => 'Top pages',
     'description' => 'View pages that have been hit frequently.',
     'page callback' => 'statistics_top_pages',
     'access arguments' => array('access statistics'),
     'weight' => 1,
   );
-  $items['admin/reports/visitors'] = array(
+  $items['statistics/visitors'] = array(
     'title' => 'Top visitors',
     'description' => 'View visitors that hit many pages.',
     'page callback' => 'statistics_top_visitors',
     'access arguments' => array('access statistics'),
     'weight' => 2,
   );
-  $items['admin/reports/referrers'] = array(
+  $items['statistics/referrers'] = array(
     'title' => 'Top referrers',
     'description' => 'View top referrers.',
     'page callback' => 'statistics_top_referrers',
     'access arguments' => array('access statistics'),
   );
-  $items['admin/reports/access/%'] = array(
+  $items['statistics/access/%'] = array(
     'title' => 'Details',
     'description' => 'View access log.',
     'page callback' => 'statistics_access_log',
Index: modules/statistics/statistics.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.pages.inc,v
retrieving revision 1.6
diff -u -p -r1.6 statistics.pages.inc
--- modules/statistics/statistics.pages.inc	13 Oct 2008 00:33:04 -0000	1.6
+++ modules/statistics/statistics.pages.inc	22 Jan 2009 23:35:57 -0000
@@ -6,7 +6,177 @@
  * User page callbacks for the statistics module.
  */
 
-function statistics_node_tracker() {
+/**
+ * Menu callback; presents the "recent hits" page.
+ */
+function statistics_recent_hits() {
+  $header = array(
+    array('data' => t('Timestamp'), 'field' => 'a.timestamp', 'sort' => 'desc'),
+    array('data' => t('Page'), 'field' => 'a.path'),
+    array('data' => t('User'), 'field' => 'u.name'),
+    array('data' => t('Operations'))
+  );
+
+  $sql = 'SELECT a.aid, a.path, a.title, a.uid, u.name, a.timestamp FROM {accesslog} a LEFT JOIN {users} u ON u.uid = a.uid' . tablesort_sql($header);
+
+  $result = pager_query($sql, 30);
+  $rows = array();
+  while ($log = db_fetch_object($result)) {
+    $rows[] = array(
+      array('data' => format_date($log->timestamp, 'small'), 'class' => 'nowrap'),
+      _statistics_format_item($log->title, $log->path),
+      theme('username', $log),
+      l(t('details'), "admin/reports/access/$log->aid"));
+  }
+
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 4));
+  }
+
+  $output = theme('table', $header, $rows);
+  $output .= theme('pager', NULL, 30, 0);
+  return $output;
+}
+
+/**
+ * Menu callback; presents the "top pages" page.
+ */
+function statistics_top_pages() {
+  // MAX(title) avoids having empty node titles which otherwise causes duplicates in the top pages list
+  $sql = "SELECT COUNT(path) AS hits, path, MAX(title) AS title, AVG(timer) AS average_time, SUM(timer) AS total_time FROM {accesslog} GROUP BY path";
+  $sql_cnt = "SELECT COUNT(DISTINCT(path)) FROM {accesslog}";
+
+  $header = array(
+    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
+    array('data' => t('Page'), 'field' => 'path'),
+    array('data' => t('Average page generation time'), 'field' => 'average_time'),
+    array('data' => t('Total page generation time'), 'field' => 'total_time')
+  );
+  $sql .= tablesort_sql($header);
+  $result = pager_query($sql, 30, 0, $sql_cnt);
+
+  $rows = array();
+  while ($page = db_fetch_object($result)) {
+    $rows[] = array($page->hits, _statistics_format_item($page->title, $page->path), t('%time ms', array('%time' => round($page->average_time))), format_interval(round($page->total_time / 1000)));
+  }
+
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 4));
+  }
+
+  drupal_set_title(t('Top pages in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
+  $output = theme('table', $header, $rows);
+  $output .= theme('pager', NULL, 30, 0);
+  return $output;
+}
+
+/**
+ * Menu callback; presents the "top visitors" page.
+ */
+function statistics_top_visitors() {
+
+  $header = array(
+    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
+    array('data' => t('Visitor'), 'field' => 'u.name'),
+    array('data' => t('Total page generation time'), 'field' => 'total'),
+    array('data' => user_access('block IP addresses') ? t('Operations') : '', 'colspan' => 2),
+  );
+
+  $sql = "SELECT COUNT(a.uid) AS hits, a.uid, u.name, a.hostname, SUM(a.timer) AS total, bl.iid FROM {accesslog} a LEFT JOIN {blocked_ips} bl ON a.hostname = bl.ip LEFT JOIN {users} u ON a.uid = u.uid GROUP BY a.hostname, a.uid, u.name, bl.iid" . tablesort_sql($header);
+  $sql_cnt = "SELECT COUNT(DISTINCT(CONCAT(CAST(uid AS char), hostname))) FROM {accesslog}";
+  $result = pager_query($sql, 30, 0, $sql_cnt);
+
+  $rows = array();
+  while ($account = db_fetch_object($result)) {
+    $qs = drupal_get_destination();
+    $ban_link =  $account->iid ? l(t('unblock IP address'), "admin/settings/ip-blocking/delete/$account->iid", array('query' => $qs)) : l(t('block IP address'), "admin/settings/ip-blocking/$account->hostname", array('query' => $qs));
+    $rows[] = array($account->hits, ($account->uid ? theme('username', $account) : $account->hostname), format_interval(round($account->total / 1000)), (user_access('block IP addresses') && !$account->uid) ? $ban_link : '');
+  }
+
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 4));
+  }
+
+  drupal_set_title(t('Top visitors in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
+  $output = theme('table', $header, $rows);
+  $output .= theme('pager', NULL, 30, 0);
+  return $output;
+}
+
+/**
+ * Menu callback; presents the "referrer" page.
+ */
+function statistics_top_referrers() {
+  $query = "SELECT url, COUNT(url) AS hits, MAX(timestamp) AS last FROM {accesslog} WHERE url NOT LIKE :host AND url <> '' GROUP BY url";
+  $query_cnt = "SELECT COUNT(DISTINCT(url)) FROM {accesslog} WHERE url <> '' AND url NOT LIKE :host";
+  drupal_set_title(t('Top referrers in the past %interval', array('%interval' => format_interval(variable_get('statistics_flush_accesslog_timer', 259200)))), PASS_THROUGH);
+
+  $header = array(
+    array('data' => t('Hits'), 'field' => 'hits', 'sort' => 'desc'),
+    array('data' => t('Url'), 'field' => 'url'),
+    array('data' => t('Last visit'), 'field' => 'last'),
+  );
+
+  $query .= tablesort_sql($header);
+  $result = pager_query($query, 30, 0, $query_cnt, array(':host' => '%'. $_SERVER['HTTP_HOST'] .'%'));
+
+  $rows = array();
+  while ($referrer = db_fetch_object($result)) {
+    $rows[] = array($referrer->hits, _statistics_link($referrer->url), t('@time ago', array('@time' => format_interval(REQUEST_TIME - $referrer->last))));
+  }
+
+  if (empty($rows)) {
+    $rows[] = array(array('data' => t('No statistics available.'), 'colspan' => 3));
+  }
+
+  $output = theme('table', $header, $rows);
+  $output .= theme('pager', NULL, 30, 0);
+  return $output;
+}
+
+/**
+ * Menu callback; Displays recent page accesses.
+ */
+function statistics_access_log($aid) {
+  $result = db_query('SELECT a.*, u.name FROM {accesslog} a LEFT JOIN {users} u ON a.uid = u.uid WHERE aid = %d', $aid);
+  if ($access = db_fetch_object($result)) {
+    $rows[] = array(
+      array('data' => t('URL'), 'header' => TRUE),
+      l(url($access->path, array('absolute' => TRUE)), $access->path)
+    );
+    // It is safe to avoid filtering $access->title through check_plain because
+    // it comes from drupal_get_title().
+    $rows[] = array(
+      array('data' => t('Title'), 'header' => TRUE),
+      $access->title
+    );
+    $rows[] = array(
+      array('data' => t('Referrer'), 'header' => TRUE),
+      ($access->url ? l($access->url, $access->url) : '')
+    );
+    $rows[] = array(
+      array('data' => t('Date'), 'header' => TRUE),
+      format_date($access->timestamp, 'large')
+    );
+    $rows[] = array(
+      array('data' => t('User'), 'header' => TRUE),
+      theme('username', $access)
+    );
+    $rows[] = array(
+      array('data' => t('Hostname'), 'header' => TRUE),
+      check_plain($access->hostname)
+    );
+
+    return theme('table', array(), $rows);
+  }
+  else {
+    drupal_not_found();
+  }
+}
+
+/**
+ * Menu callback; Displays recent node accesses.
+ */function statistics_node_tracker() {
   if ($node = node_load(arg(1))) {
 
     $header = array(
@@ -39,6 +209,9 @@ function statistics_node_tracker() {
   }
 }
 
+/**
+ * Menu callback; Displays a user's recent activity.
+ */
 function statistics_user_tracker() {
   if ($account = user_load(array('uid' => arg(1)))) {
 
