--- user_stats.module	2008-01-24 09:49:52.000000000 +0800
+++ user_stats.module	2008-01-26 15:30:23.000000000 +0800
@@ -5,7 +5,113 @@
  * Implementation of hook_perm()
  */
 function user_stats_perm() {
-  return array('View statistics', 'View IP addresses');
+  return array('administer user stats', 'View statistics', 'View IP addresses');
+}
+
+/**
+ * Implementation of hook_menu().
+ */
+function user_stats_menu($may_cache) {
+  $items = array();
+
+  if ($may_cache) {
+    // Admin settings
+    $items[] = array(
+      'path' => 'admin/settings/user_stats',
+      'title' => t('User stats settings'),
+      'description' => t('Configuration of user stats module options.'),
+      'callback' => 'drupal_get_form',
+      'callback arguments' => array('user_stats_admin_settings'),
+      'access' => user_access('administer user stats'),
+      'type' => MENU_NORMAL_ITEM,
+    );
+    $items[] = array(
+      'path' => 'admin/settings/user_stats/reset',
+      'title' => t('reset user post stats'),
+      'callback' => 'drupal_get_form',
+      'callback arguments' => array('user_stats_reset_postcount_confirm'),
+      'access' => user_access('administer user stats'),
+      'type' => MENU_CALLBACK,
+    );
+  }
+  
+  return $items;
+}
+
+/**
+ * Implementation of hook_settings().
+ */
+function user_stats_admin_settings() {
+  $form['post_count_options'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Post count options'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+
+  foreach(content_types() as $types) {
+    $options[$types['type']] = $types['name'];
+  }
+
+  $form['post_count_options']['user_stats_included_content_types'] = array(
+    '#type' => 'select',
+    '#title' => t('Content types to include in post count'),
+    '#description' => t('Select the content types to include in the user post count. Both nodes and comments will be included in the post count. If you do not select any content types, then all types will be counted.'),
+    '#options' => $options,
+    '#default_value' => variable_get('user_stats_included_content_types', array()),
+    '#multiple' => TRUE,
+    '#size' => 10,
+  );
+
+  $form['post_count_reset'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Post count reset'),
+    '#collapsible' => TRUE,
+    '#collapsed' => FALSE,
+  );
+
+  $form['post_count_reset']['user_stats_user_per_cron'] = array(
+    '#type' => 'select',
+    '#title' => t('Number of users to update per cron run'),
+    '#options' => array('10' => '10', '25' => '25', '50' => '50', '100' => '100', '200' => '200'),
+    '#default_value' => variable_get('user_stats_user_per_cron', array('25')),
+  );
+
+  $form['post_count_reset']['user_stats_reset_count'] = array(
+    '#type' => 'submit',
+    '#value' => t('Reset all post counts'),
+  );
+
+  return system_settings_form($form);
+}
+
+/**
+ * Validate callback.
+ */
+function user_stats_admin_settings_validate($form_id, $form_values) {
+  if ($form_values['op'] == t('Reset post count')) {
+    drupal_goto('admin/settings/user_stats/reset');
+  }
+}
+
+/**
+ * reset post count confim callback
+ */
+function user_stats_reset_postcount_confirm() {
+  return confirm_form(array(), t('Are you sure you want to reset post counts?'),
+    'admin/settings/user_stats', '', t('Reset post count'), t('Cancel'));
+}
+
+/**
+ * reset post count handler
+ */
+function user_stats_reset_postcount_confirm_submit($form_id, &$form) {
+  if ($form['confirm']) {
+    variable_set('user_stats_rebuild_stats', TRUE);
+    user_stats_reset_postcounts();
+    drupal_set_message(t('The post counts will be reset during the next cron run.'));
+    drupal_goto('admin/settings/user_stats');
+  }
 }
 
 /**
@@ -26,7 +132,7 @@ function user_stats_perm() {
  *   The statistic requested. Every statistic except join_date, online and IP address is a numeric.
  *   Join date is a string, whilst online is a boolean and IP Address a string.
  */
-function user_stats_get_stats($type, $uid) {
+function user_stats_get_stats($type, $uid, $options = array()) {
   $user = _user_stats_user_cache($uid);
   if (user_access('View statistics') && $type != 'ip_address') {
     switch ($type) {
@@ -46,6 +152,14 @@ function user_stats_get_stats($type, $ui
         return $user->user_post_count;
       case 'online':
         return (round((time() - $user->access) / 60) < 15 ? TRUE : FALSE);
+      case 'profile':
+        if (!empty($options)) {
+          if (isset($user->$options['field']) && !is_array($user->$options['field'])) {
+            return $user->$options['field'];
+          }
+          break;
+        }
+        break;
     }
   }
   // IP address is really a bit of feature creep. But it's so useful in stopping spammers!
@@ -81,7 +195,7 @@ function _user_stats_user_cache($uid, $f
     return;
   }
   else if (!isset($users[$uid]) && $uid > (-1)) {
-    $users[$uid] = user_load(array('uid' => $uid));
+    $users[$uid] = user_stats_user_load($uid);
   }
   return $users[$uid];
 }
@@ -103,9 +217,11 @@ function _user_stats_user_cache($uid, $f
  *   The operation being performed. We are interested in insert, delete, update and view
  */
 function user_stats_nodeapi(&$node, $op) {
+  $postcount_content_types = variable_get('user_stats_included_content_types', array());
+  if (empty($postcount_content_types) || (in_array($node->type, $postcount_content_types))) {
   switch ($op) {
     case 'insert':
-      $user_node = user_load(array('uid' => $node->uid));
+        $user_node = user_stats_user_load($node->uid);
       if ($node->status) {
         user_stats_post_count_update($user_node, 'increment');
       }
@@ -116,11 +232,11 @@ function user_stats_nodeapi(&$node, $op)
       }
       break;
     case 'delete':
-      $user_node = user_load(array('uid' => $node->uid));
+        $user_node = user_stats_user_load($node->uid);
       user_stats_post_count_update($user_node, 'decrement');
       break;
     case 'update':
-      $user_node = user_load(array('uid' => $node->uid));
+        $user_node = user_stats_user_load($node->uid);
       // Can't think of any other way of doing this than resetting the user...
       user_stats_post_count_update($user_node, 'reset');
       global $user;
@@ -130,6 +246,7 @@ function user_stats_nodeapi(&$node, $op)
       }
       break;
   }
+  }
 }
 
 /**
@@ -150,8 +267,12 @@ function user_stats_comment(&$a1, $op) {
 
   switch ($op) {
     case 'insert':
-      $user_comment = user_load(array('uid' => $comment->uid));
-      user_stats_post_count_update($user_comment, 'increment');
+      $postcount_content_types = variable_get('user_stats_included_content_types', array());
+      $node = node_load(array('nid' => $comment->nid));
+      if (empty($postcount_content_types) || (in_array($node->type, $postcount_content_types))) {
+        $user = user_stats_user_load($comment->uid);
+        user_stats_post_count_update($user, 'increment');
+      }
       global $user;
       // User IP addresses are only interesting if they are posting the content
       if ($comment->uid == $user->uid) {
@@ -159,11 +280,20 @@ function user_stats_comment(&$a1, $op) {
       }
       break;
     case 'delete':
-      $user_comment = user_load(array('uid' => $comment->uid));
-      user_stats_post_count_update($user_comment, 'decrement');
+      $postcount_content_types = variable_get('user_stats_included_content_types', array());
+      $node = node_load(array('nid' => $comment->nid));
+      if (empty($postcount_content_types) || (in_array($node->type, $postcount_content_types))) {
+        $user = user_stats_user_load($comment->uid);
+        user_stats_post_count_update($user, 'decrement');
+      }
+      break;
     case 'update':
-      $user_comment = user_load(array('uid' => $comment->uid));
+      $postcount_content_types = variable_get('user_stats_included_content_types', array());
+      $node = node_load(array('nid' => $comment->nid));
+      if (empty($postcount_content_types) || (in_array($node->type, $postcount_content_types))) {
+        $user_comment = user_stats_user_load($comment->uid);
       user_stats_post_count_update($user_comment, 'reset');
+      }
       break;
   }
 }
@@ -185,14 +315,14 @@ function user_stats_cron() {
     $sql .= "  WHERE fid=%d ";
     $sql .= ") ";
     // Update 25 users per cron run
-    $result = db_query_range($sql, $fid, 0, 25);
+    $result = db_query_range($sql, $fid, 0, variable_get('user_stats_user_per_cron', array('25')));
     // If all users have been updated we'll avoid running this expensive 
     // query again by setting the following flag!
     if (db_num_rows($result) == 0) {
       variable_set('user_stats_rebuild_stats', FALSE);
     }
     while ($update_user = db_fetch_object($result)) {
-      $user = user_load($update_user);
+      $user = user_stats_user_load($update_user->uid);
       user_stats_post_count_update($user, 'reset');
     }
   }
@@ -206,7 +336,7 @@ function user_stats_cron() {
     $result = db_query($sql, variable_get('cron_last', time()));
     $reset_user_count = 0;
     while ($update_user = db_fetch_object($result)) {
-      $user = user_load($update_user);
+      $user = user_stats_user_load($update_user->uid);
       // We stop at 50 reset users (they'll just have to wait) so cron doesn't get timed out
       if (!isset($user->user_post_count) && $reset_user_count < 50) {
         user_stats_post_count_update($user, 'reset');
@@ -239,10 +369,20 @@ function user_stats_user($op, &$edit, &$
  *   Unix timestamp: date of the last post (node or comment).
  */
 function _user_stats_last_post($account) {
-  $sql  = "SELECT MAX(created) FROM {node} WHERE uid=%d";
-  $max_node = db_result(db_query($sql, $account->uid));
-  $sql  = "SELECT MAX(timestamp) FROM {comments} WHERE uid=%d";
-  $max_comments = db_result(db_query($sql, $account->uid));
+  $sql  = "SELECT MAX(created) FROM {node} WHERE status = %d AND uid=%d";
+  $postcount_content_types = variable_get('user_stats_included_content_types', array());
+  if (!empty($postcount_content_types)) {
+    $content_types = "'". implode("','", $postcount_content_types) ."'";
+    $where = ' AND type IN ('. $content_types .')';
+    $sql .= $where;
+  }
+  $max_node = db_result(db_query($sql, 1, $account->uid));
+  $sql  = "SELECT MAX(timestamp) FROM {comments} c INNER JOIN {node} n ON c.nid = n.nid WHERE c.status = %d AND c.uid=%d";
+  if (!empty($postcount_content_types)) {
+    $where = ' AND n.type IN ('. $content_types .')';
+    $sql .= $where;
+  }
+  $max_comments = db_result(db_query($sql, 0, $account->uid));
 
   if ($max_node > $max_comments) {
     return $max_node;
@@ -489,8 +629,18 @@ function user_stats_post_count_update(&$
         $fid = db_result(db_query($sql));
       }
       $sql  = "SELECT COUNT(*) FROM {node} WHERE uid=%d AND status<>0";
+      $postcount_content_types = variable_get('user_stats_included_content_types', array());
+      if (!empty($postcount_content_types)) {
+        $content_types = "'". implode("','", $postcount_content_types) ."'";
+        $where = ' AND type IN ('. $content_types .')';
+        $sql .= $where;
+      }
       $node_count = db_result(db_query($sql, $user->uid));
-      $sql = "SELECT COUNT(*) FROM {comments} WHERE uid=%d AND status=0";
+      $sql = "SELECT COUNT(*) FROM {comments} c INNER JOIN {node} n ON c.nid = n.nid WHERE c.uid=%d AND c.status=0";
+      if (!empty($postcount_content_types)) {
+        $where = ' AND n.type IN ('. $content_types .')';
+        $sql .= $where;
+      }
       $comments_count = db_result(db_query($sql, $user->uid));
       $total_count = $node_count + $comments_count;
       $sql =  "DELETE {profile_values} FROM {profile_values} ";
@@ -538,3 +688,27 @@ function user_stats_ip_address_update(&$
   }
   db_query($sql, $ip_address, $user->uid);
 }
+
+function user_stats_user_load($uid) {
+  $result = db_query('SELECT * FROM {users} u WHERE uid = %d', $uid);
+
+  if (db_num_rows($result)) {
+    $user = db_fetch_object($result);
+    $user = drupal_unpack($user);
+    if (module_exists('profile')) {
+      profile_load_profile($user);
+    }
+  }
+  else {
+    $user = FALSE;
+  }
+
+  return $user;
+}
+
+function user_stats_reset_postcounts() {
+  $fid = db_result(db_query("SELECT fid FROM {profile_fields} WHERE name = '%s'", 'user_post_count'));
+  if ($fid) {
+    db_query('DELETE FROM {profile_values} WHERE fid = %d', $fid);
+  }
+}
