--- user_karma.module	2008-01-22 14:08:29.000000000 +0800
+++ user_karma.module	2008-01-23 18:24:33.000000000 +0800
@@ -4,7 +4,6 @@
 /**
  * @file
  */
-define('MAX_ROLES', 7);
 
 /**
  * Implementation of hook_help().
@@ -97,75 +96,86 @@ function user_karma_admin_settings() {
     '#value' => t('Run the mass-recalculation for user karma')
   );
 
-  $result = db_query('SELECT rid, name FROM {role} ORDER BY name');
-  $role_options = array();
-  $role_options[0] = t("None");
-  while ($role = db_fetch_object($result)) {
-    if ($role->rid != 1 && $role->rid != 2) {
-      $role_options[$role->rid] = $role->name;
-    }
-  }
+  $form['roles_selection'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Roles eligible for user karma'),
+    '#collapsible' => FALSE,
+  );
+
+  $roles = user_roles();
+
+  $form['roles_selection']['user_karma_eligible_roles'] = array(
+    '#type' => 'select',
+    '#title' => t('Choose roles for user karma'),
+    '#description' => t('You should choose roles created specifically for user karma.'),
+    '#options' => $roles,
+    '#default_value' => variable_get('user_karma_eligible_roles', array()),
+    '#multiple' => TRUE,
+    '#size' => 10,
+  );
 
   $form['role_assigning'] = array(
     '#type' => 'fieldset',
     '#title' => t('Assigning roles to karma amounts'),
+    '#description' => !variable_get('user_karma_eligible_roles', array()) ? t('There are roles currently eligible for user karma.') : t('Configure the user karma settings for each eligible role.'),
     '#collapsible' => FALSE,
     '#collapsed' => FALSE,
   );
 
   $karma_role_options[0] = t("Consider these absolute values");
   $karma_role_options[1] = t("Consider these as the user's ranking, out of 10000");
-  for ($i = 0;$i < MAX_ROLES;$i++) {
-    $form['role_assigning']['user_karma_role_'. $i] = array(
-      '#type' => 'select',
-      '#title' => t('Role to be assigned...'),
-      '#default_value' => variable_get('user_karma_role_'. $i, ''),
-      '#options' => $role_options,
-      '#description' =>  t('This role will be assigned if the user hits the karma in the range below'),
+
+  foreach (variable_get('user_karma_eligible_roles', array()) as $rid) {
+
+    $form['role_assigning']['user_karma_role_fieldset_'. $rid] = array(
+      '#type' => 'fieldset',
+      '#title' => t('User karma setting for role @role', array('@role' => $roles[$rid])),
+      '#collapsible' => TRUE,
+      '#collapsed' => TRUE,
     );
     
-    $form['role_assigning']['user_karma_role_'. $i .'_from'] = array(
+    $form['role_assigning']['user_karma_role_fieldset_'. $rid]['user_karma_role_'. $rid .'_from'] = array(
       '#type' => 'textfield', 
       '#title' => t('From'),
       '#description' => t('Leaving an empty value means "from 0"'),
       '#size' => 7, 
       '#maxlength' => 7, 
-      '#default_value' => variable_get('user_karma_role_'. $i .'_from', ''), 
+      '#default_value' => variable_get('user_karma_role_'. $rid. '_from', ''), 
     );
     
-    $form['role_assigning']['user_karma_role_'. $i .'_to'] = array(
+    $form['role_assigning']['user_karma_role_fieldset_'. $rid]['user_karma_role_'. $rid .'_to'] = array(
       '#type' => 'textfield', 
       '#title' => t('To'),
       '#description' => t('Leaving an empty value means "to infinite"'),
       '#size' => 7, 
       '#maxlength' => 7, 
-      '#default_value' => variable_get('user_karma_role_'. $i .'_to', ''), 
+      '#default_value' => variable_get('user_karma_role_'. $rid .'_to', ''), 
     );
 
-    $form['role_assigning']['user_karma_role_'. $i .'_type'] = array(
+    $form['role_assigning']['user_karma_role_fieldset_'. $rid]['user_karma_role_'. $rid .'_type'] = array(
       '#title' => t('How to interpret the numbers in the range'),
       '#type' => 'radios',
       '#options' => $karma_role_options,
-      '#default_value' => variable_get('user_karma_role_'. $i .'_type', 0),
+      '#default_value' => variable_get('user_karma_role_'. $rid .'_type', 0),
     );
     
   }
 
-  $form['user_karma_point_duration']=array(
+  $form['user_karma_point_duration'] = array(
     '#type' => 'textfield', 
     '#title' => t('How many days karma points are valid for.'),
     '#size' => 4, 
     '#maxlength' => 4, 
-    '#default_value' => variable_get('user_karma_point_duration', '90'), 
+    '#default_value' => variable_get('user_karma_point_duration', 90), 
   );
 
-  $form['user_karma_show_karma_in_user_page']=array(
+  $form['user_karma_show_karma_in_user_page'] = array(
     '#type' => 'checkbox', 
     '#title' => t('Show karma in the user profile page'),
     '#default_value' => variable_get('user_karma_show_karma_in_user_page', FALSE), 
   );
 
-  $form['user_karma_show_ranking_in_user_page']=array(
+  $form['user_karma_show_ranking_in_user_page'] = array(
     '#type' => 'checkbox', 
     '#title' => t('Show ranking in the user profile page'),
     '#default_value' => variable_get('user_karma_show_ranking_in_user_page', FALSE), 
@@ -196,7 +206,6 @@ function user_karma_admin_settings_valid
     drupal_goto('user_karma/karma_mass_recalculation');
   }
 
-
 }
 
 /**
@@ -338,17 +347,15 @@ function user_karma_new_vote($op, $v, $v
     }
 
   }
-
-  return TRUE;
 }
 
 function user_karma_assign_user_karma($recipient_uid) {
 
   // Calculate the new karma
-  $total_karma_amount=user_karma_calculate_karma($recipient_uid);
+  $total_karma_amount = user_karma_calculate_karma($recipient_uid);
 
   // Create the voting object
-  $new_vote= new stdClass();
+  $new_vote = new stdClass();
   $new_vote->value = $total_karma_amount;
   $new_vote->value_type = 'karma_points';
   $new_vote->tag = 'karma';
@@ -369,15 +376,16 @@ function user_karma_assign_user_karma($r
  * 
  */
 function user_karma_calculate_karma($recipient_uid) {
-  $query = "SELECT SUM(vv.value) FROM {votingapi_vote} vv LEFT JOIN {node} n ON vv.content_type='node' AND vv.content_id=n.nid WHERE vv.content_type='node' AND vv.value_type='points' AND n.uid = $recipient_uid AND ". user_karma_sql_duration("n.created");
-  $karma_from_nodes = db_result(db_query($query));
+
+  $query = "SELECT SUM(vv.value) FROM {votingapi_vote} vv LEFT JOIN {node} n ON vv.content_id = n.nid WHERE vv.content_type = 'node' AND vv.value_type = 'points' AND n.uid = %d ". user_karma_sql_duration("n.created");
+  $karma_from_nodes = db_result(db_query($query, $recipient_uid, time()));
   //drupal_set_message("Query: $query ; Karma from nodes: $karma_from_nodes");
   
-  $query = "SELECT SUM(vv.value) FROM {votingapi_vote} vv LEFT JOIN {comments} c ON vv.content_type='comment' AND vv.content_id=c.cid WHERE vv.content_type='comment' AND vv.value_type='points' AND c.uid = $recipient_uid AND ". user_karma_sql_duration("c.timestamp");
-  $karma_from_comments = db_result(db_query($query));
+  $query = "SELECT SUM(vv.value) FROM {votingapi_vote} vv LEFT JOIN {comments} c ON vv.content_id = c.cid WHERE vv.content_type = 'comment' AND vv.value_type = 'points' AND c.uid = %d ". user_karma_sql_duration("c.timestamp");
+  $karma_from_comments = db_result(db_query($query, $recipient_uid, time()));
   //drupal_set_message("Query: $query ; Karma from comments: $karma_from_comments");
 
-  $total_karma=$karma_from_nodes + $karma_from_comments;
+  $total_karma = $karma_from_nodes + $karma_from_comments;
 
   return (int) $total_karma;
 }
@@ -411,7 +419,6 @@ function user_karma_votingapi_calculate(
 #             END OF INTERFACING WITH THE VOTING API
 ##################################################################
 
-
 /**
  * The module's cron hook. It's used to:
  *
@@ -422,13 +429,12 @@ function user_karma_votingapi_calculate(
  *   Nothing
  */
 function user_karma_cron() {
-
   //drupal_set_message("user_karma's cron started!");
 
   // This will only happen once every 12 hours maximum
   $cron_timestamp = variable_get('user_karma_cron_timestamp', '');
-  if ((time() - $cron_timestamp) >= 60*60*12 || TRUE) { 
-  //if ((time() - $cron_timestamp) >= 60*60*12) { 
+  //if ((time() - $cron_timestamp) >= 60 * 60 * 12 || TRUE) { 
+  if ((time() - $cron_timestamp) >= 60 * 60 * 12) { 
 
     //drupal_set_message("In the 'every 12 hours' section!");
     
@@ -439,7 +445,7 @@ function user_karma_cron() {
 
     // Only do the recalculation if an expiration is set for the
     // users' karma points
-    $days = variable_get('user_karma_point_duration', '');
+    $days = variable_get('user_karma_point_duration', 90);
     if ($days != 0) {
 
       // Scan through all of the users, load each one and
@@ -448,9 +454,9 @@ function user_karma_cron() {
       // over the time when a karma vote is valid for. So, if a person has
       // received a vote over the last 2 weeks and a vote lasts 2 months, the
       // recalculation won't be done. This will sieve out a few users.
-      $query="SELECT u.uid FROM {users} u LEFT JOIN {votingapi_cache} vc ON u.uid = vc.content_id WHERE vc.content_type = 'user' AND ". user_karma_sql_duration('vc.timestamp', '<');
+      $query = "SELECT u.uid FROM {users} u LEFT JOIN {votingapi_cache} vc ON u.uid = vc.content_id WHERE vc.content_type = 'user' ". user_karma_sql_duration('vc.timestamp', '<');
       //drupal_set_message("QUERY: $query");
-      $result = db_query($query);
+      $result = db_query($query, time());
       while ($u = db_fetch_object($result)) {
         user_karma_assign_user_karma($u->uid);
       }
@@ -482,18 +488,15 @@ function user_karma_roles_mass_recalcula
   set_time_limit(300);
 
   // Deletes right away any role that this module might possibly manage
-  for ($i = 0;$i < MAX_ROLES;$i++) {
-
-    $r = variable_get('user_karma_role_'. $i, '');
-    if ($r != 0) {
+  $roles = variable_get('user_karma_eligible_roles', array());
+  foreach ($roles as $rid) {
       //drupal_set_message("Deleting ALL roles $r");
-      db_query('DELETE FROM {users_roles} WHERE rid = %d', $r );
-    }
+    db_query('DELETE FROM {users_roles} where rid = %d', $rid);
   }
 
   // Get the list of users. You need the COMPLETE list, since you
   // might want to assign roles to users with no karma points assigned
-  $result = db_query('SELECT uid FROM {users} WHERE status=1');
+  $result = db_query('SELECT uid FROM {users} WHERE status = 1 AND uid != 0');
 
   // Recalculate for each user
   while ($data = db_fetch_object($result)) {
@@ -515,7 +518,7 @@ function user_karma_karma_mass_recalcula
   
   // Make up the list of users which will need karma recalculation
   // based on who added a node
-  $query = "SELECT uid FROM {node} GROUP BY uid";
+  $query = "SELECT uid FROM {node} WHERE status = 1 GROUP BY uid";
   $result = db_query($query);
   while ($u = db_fetch_object($result)) {
     $users[$u->uid] = TRUE;
@@ -523,17 +526,20 @@ function user_karma_karma_mass_recalcula
  
   // Make up the list of users whic will need karma recalculation
   // based on who added a comment
-  $query = "SELECT uid FROM {comments} GROUP BY uid";
+  $query = "SELECT uid FROM {comments} WHERE status = 0 GROUP BY uid";
   $result = db_query($query);
   while ($u = db_fetch_object($result)) {
+    if (!$users[$u->uid]) {
     $users[$u->uid] = TRUE;
   }
+  }
 
   // At this point, the keys of the $users variable will have a list of
   // unique UIDs: recalculate
   foreach ($users as $uid => $k) { 
     user_karma_assign_user_karma($uid);
   }
+
 }
 
 /**
@@ -559,8 +565,8 @@ function user_karma_calculate_role($uid,
   // Calculates the total number of users, and puts it in a static
   // variable. This way, if a mass recalculation is needed,
   // this query is not run thousands of times
-  if (!$users_t) {
-    $users_t = db_result(db_query("SELECT COUNT(*) FROM {users} WHERE status=1"));
+  if (!$users_t){
+   $users_t = db_result(db_query("SELECT COUNT(*) FROM {users} WHERE status = 1"));
     //drupal_set_message("Users_t is now $users_t");
   }
 
@@ -572,26 +578,23 @@ function user_karma_calculate_role($uid,
   // if the result is "1" then the rank is left as "1"!
   $rank = user_karma_user_rank($uid);
   //drupal_set_message("RB: $rank");
-  if ($rank != 1) {
-    $rank= (int) ($rank / $users_t * 10000);
+  if ($rank != 1){
+    $rank = (int) ($rank / $users_t * 10000);
   }
   //drupal_set_message("RA: $rank");
 
-  for ($i = 0;$i < MAX_ROLES;$i++) {
-
+  $roles = variable_get('user_karma_eligible_roles', array());
+  foreach ($roles as $rid) {
     // Create the vars with short names for the three roles/ranges.
-    $r    = variable_get('user_karma_role_'. $i, '');
-    $f    = variable_get('user_karma_role_'. $i .'_from', '');
-    $t    = variable_get('user_karma_role_'. $i .'_to', '');
-    $type = variable_get('user_karma_role_'. $i .'_type', '');
-
+    //$r =    variable_get('user_karma_role_'. $i, '');
+    $f =    variable_get('user_karma_role_'. $rid .'_from', '');
+    $t =    variable_get('user_karma_role_'. $rid .'_to', '');
+    $type = variable_get('user_karma_role_'. $rid .'_type', '');
 
     //drupal_set_message("Here: $r,$f,$t,$type");
 
-    if ($r != 0) {
-
       if ($delete) {
-        db_query('DELETE FROM {users_roles} WHERE uid = %d AND rid = %d', $uid, $r ); 
+      db_query('DELETE FROM {users_roles} where uid = %d and rid = %d', $uid, $rid ); 
         //drupal_set_message("Delete is on");
       }
 
@@ -600,20 +603,19 @@ function user_karma_calculate_role($uid,
         $variable = $total_karma; 
       }
       else { 
-        $variable=$rank; 
+      $variable = $rank; 
       }
       
       //drupal_set_message("Variable is $variable");
-
       //drupal_set_message("Type is $type. Comparing $variable with $f and $t");
       // If the variable is within the range, then assign the role!
-      if ( ($variable >= $f || $f == '') && ($variable <= $t || $t =='') ) {
-        db_query('INSERT INTO {users_roles} (uid, rid) VALUES (%d, %d)',  $uid, $r ); 
+    if ( ($variable >= $f || $f == '') && ($variable <= $t || $t == '') ) {
+      db_query('INSERT INTO {users_roles} (uid, rid) values (%d, %d)',  $uid, $rid ); 
         //drupal_set_message("ROLE '$r' ADDED");
       }
 
     } 
-  }
+
 }
 
 /**
@@ -624,11 +626,13 @@ function user_karma_calculate_role($uid,
  */
 function user_karma_roles() {
   $result = array();
-  for ($i = 0;$i < MAX_ROLES;$i++) {
-    $r = variable_get('user_karma_role_'. $i, '0');
-    if ( $r != 0) {
-      $result[] = $r;
-    }
+  $roles = variable_get('user_karma_eligible_roles', array());
+  foreach ($roles as $rid) {
+    //for ($i = 0;$i < MAX_ROLES;$i++) {
+    //$r = variable_get('user_karma_role_'. $i, '0');
+    //if ( $rid != 0) {
+    $result[] = $rid;
+    //}
   }
   return $result;
 }
@@ -661,16 +665,19 @@ function user_karma_roles_for_user($uid)
     $karma_roles = user_karma_roles();
 
     // Make up the query
-    $query = " 1 = 0 ";
-    for ($i = 0; $i < sizeof($karma_roles);$i++) {
-      $query .= " OR rid = $karma_roles[$i] ";
-    }
+    //$query = " 1 = 0 ";
+    //for ($i = 0; $i < sizeof($karma_roles);$i++) {
+    //  $query .= " OR rid = $karma_roles[$i] ";
+    //}
+    if (sizeof($karma_roles)) {
+      $query = ' AND rid IN ('. implode(', ', $karma_roles) .')';
   
     // Make up the $return variable with the query's result
-    $result = db_query("SELECT rid FROM {users_roles} WHERE uid = $uid AND ($query)");
+      $result = db_query("SELECT rid FROM {users_roles} WHERE uid = %d AND ($query)", $uid);
     while ($data = db_fetch_object($result)) {    
       $user_roles[$uid][] = $data->rid;
     }
+    }
   } // End of calculation if the user wasn't in the cache already
   
   //drupal_set_message("HERE: ". $user_roles[$uid][0]);
@@ -744,19 +751,22 @@ function user_karma_view_profile($accoun
  *   A nice SQL fragment that will fit after an AND and after a WHERE
  */
 function user_karma_sql_duration($field_name, $operator = '>') {
-  $days = variable_get('user_karma_point_duration', '');
-
+  $days = variable_get('user_karma_point_duration', 90);
+  if ((int)$days <= 0) {
+    return '';
+  }
   // This is important so that it still works if it's just after an "AND"
-  $return_str = " 1=1";
+  //$return_str = " AND 1 = 1";
 
   // If the day is set, ADD the bit that checks the point's expiry date
-  if ( $days != '') {
+  //if ($days != '') {
     $seconds = $days * 86400;
-    $return_str .=  " AND $field_name $operator UNIX_TIMESTAMP(CURRENT_TIMESTAMP()) - $seconds ";
-  } 
+  return ' AND '. $field_name . ' '. $operator .' (%d - '. $seconds .')';
+  //$return_str .=  " AND $field_name $operator UNIX_TIMESTAMP(CURRENT_TIMESTAMP()) - $seconds ";
+    //} 
 
   // That's it!
-  return $return_str;
+    //return $return_str;
 }
 
 function user_karma_user_rank($uid) {
@@ -765,18 +775,17 @@ function user_karma_user_rank($uid) {
   // Otherwise, the comparison is made with a sub-query.
   // THIS IS BECAUSE ANY INTEGER COMPARED TO NULL IS 0, WHICH WON'T WORK
   // IN TERMS OF RANKING
-  $r = db_result(db_query("SELECT COUNT(*) FROM {votingapi_cache} vc2 WHERE vc2.content_type = 'user' AND vc2.value_type='karma_points' AND vc2.tag='karma' AND vc2.function='sum' AND vc2.content_id=%d", $uid));
+  $r = db_result(db_query("SELECT COUNT(*) FROM {votingapi_cache} vc2 WHERE vc2.content_type = 'user' AND vc2.value_type = 'karma_points' AND vc2.tag = 'karma' AND vc2.function = 'sum' AND vc2.content_id = %d", $uid));
   if ($r == 0) {
     $extra_bit = "0";
-  }
-  else {
-    $extra_bit = "(SELECT value FROM {votingapi_cache} vc2 WHERE vc2.content_type = 'user' AND vc2.value_type='karma_points' AND vc2.tag='karma' AND vc2.function='sum' AND vc2.content_id=%d)";
+  } else {
+    $extra_bit = "(SELECT value FROM {votingapi_cache} vc2 WHERE vc2.content_type = 'user' AND vc2.value_type = 'karma_points' AND vc2.tag = 'karma' AND vc2.function = 'sum' AND vc2.content_id = %d)";
   }
 
   // Query curtesy of http://arjen-lentz.livejournal.com/55083.html and 
   // http://arjen-lentz.livejournal.com/56292.html - EVERYBODY should 
   // read those pages!
-    $r = db_result(db_query("SELECT COUNT(*)+1 AS ranking FROM {votingapi_cache} vc LEFT JOIN {users} u ON u.uid =  vc.content_id WHERE vc.content_type = 'user' AND  vc.value_type='karma_points' AND vc.tag='karma' AND vc.function='sum' AND vc.value > $extra_bit", $uid)); 
+  $r = db_result(db_query("SELECT COUNT(*) + 1 AS ranking FROM {votingapi_cache} vc LEFT JOIN {users} u ON u.uid = vc.content_id WHERE vc.content_type = 'user' AND vc.value_type = 'karma_points' AND vc.tag = 'karma' AND vc.function = 'sum' AND vc.value > $extra_bit", $uid)); 
 
   return $r;
 }
@@ -792,4 +801,4 @@ function user_karma_user_karma($uid) {
 
 # CHUNK #1
 
-//return (db_result(db_query("SELECT COUNT(*)+1 as ranking FROM {user_karma_cache} skc LEFT JOIN {users} u ON u.uid = skc.oid WHERE u.status=1 AND skc.otype = 'u' AND karma > (SELECT karma FROM {user_karma_cache} sk WHERE sk.otype='u' AND sk.oid=%d)", $uid))); # Curtesy of http://arjen-lentz.livejournal.com/55083.html and http://arjen-lentz.livejournal.com/56292.html - EVERYBODY should read it!
+//return (db_result(db_query("SELECT COUNT(*)+1 as ranking FROM {user_karma_cache} skc LEFT JOIN {users} u ON u.uid = skc.oid WHERE u.status=1 AND skc.otype = 'u' AND karma > (SELECT karma FROM {user_karma_cache} sk WHERE sk.otype='u' AND sk.oid=%d)",$uid))); # Curtesy of http://arjen-lentz.livejournal.com/55083.html and http://arjen-lentz.livejournal.com/56292.html - EVERYBODY should read it!
