Index: fivestar.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fivestar/fivestar.module,v
retrieving revision 1.13.2.47
diff -u -r1.13.2.47 fivestar.module
--- fivestar.module	21 Oct 2008 05:34:45 -0000	1.13.2.47
+++ fivestar.module	16 Nov 2008 01:18:45 -0000
@@ -681,8 +681,7 @@
  */
 function fivestar_vote($type, $cid, $tag, $value) {
 
-  $result = _fivestar_cast_vote($type, $cid, $value, $tag, NULL, TRUE);
-  votingapi_recalculate_results($type, $cid);
+  $result = _fivestar_cast_vote($type, $cid, $value, $tag);
 
   if ($type == 'node') {
     $node = node_load($cid);
@@ -696,12 +695,21 @@
 
   if (count($result)) {
     foreach ($result as $data) {
-      if ($data['tag'] == $tag) {
+      if (isset($data['tag']) && $data['tag'] == $tag) {
         $output .= '<'. $data['function'] .'>'. $data['value'] .'</'. $data['function'] .'>';
         $summary[$data['tag']][$data['function']] = $data['value'];
       }
     }
   }
+
+  if (!isset($summary)) {
+    $summary[$tag] = array(
+      'average' => NULL,
+      'count' => NULL,
+      'user' => NULL,
+    );
+  }
+
   $output .= '<summary>';
   $output .= '<average><![CDATA['. theme('fivestar_summary', NULL, $summary[$tag]['average'], NULL, $stars, $feedback_enable) .']]></average>';
   $output .= '<average_count><![CDATA['. theme('fivestar_summary', NULL, $summary[$tag]['average'], $summary[$tag]['count'], $stars, $feedback_enable) .']]></average_count>';
@@ -727,10 +735,11 @@
  * Internal function to handle vote casting, flood control, XSS, IP based
  * voting, etc...
  */
-function _fivestar_cast_vote($type, $cid, $value, $tag = NULL, $uid = NULL, $result = FALSE) {
+function _fivestar_cast_vote($type, $cid, $value, $tag = NULL, $uid = NULL, $ip_address = NULL) {
   global $user;
-  $tag = empty($tag) ? 'vote' : $tag;
-  $uid = empty($uid) ? $user->uid : $uid;
+  $tag = !isset($tag) ? 'vote' : $tag;
+  $uid = !isset($uid) ? $user->uid : $uid;
+  $ip_address = !isset($ip_address) ? ip_address() : $ip_address;
 
   // Bail out if the user's trying to vote on an invalid object.
   if (!fivestar_validate_target($type, $cid, $uid)) {
@@ -756,15 +765,37 @@
       $votes = $criteria += array('value' => $value);
       votingapi_set_votes($votes, $user_votes);
     }
-    return fivestar_get_votes($type, $cid, $tag, $uid);
+
+    // Recalculate the vote values so we return the correct updated value.
+    votingapi_recalculate_results($type, $cid);
+
+    return fivestar_get_votes($type, $cid, $tag, $uid, $ip_address);
   }
 }
 
-function fivestar_get_votes($type, $cid, $tag = 'vote', $uid = NULL) {
-  global $user;
-  if (empty($uid)) {
-    $uid = $user->uid;
+/**
+ * Update an existing vote with a new value.
+ */
+function _fivestar_update_vote($vote_id, $value) {
+  $votes = votingapi_select_votes(array('vote_id' => $vote_id));
+
+  if (isset($votes[0])) {
+    if ($value != 0) {
+      $votes[0]['value'] = $value;
+      votingapi_set_votes($votes);
+    }
+    else {
+      votingapi_delete_votes($votes);
+    }
+    votingapi_recalculate_results($votes[0]['content_type'], $votes[0]['content_id']);
   }
+}
+
+function fivestar_get_votes($type, $cid, $tag = 'vote', $uid = NULL, $ip_address = NULL) {
+  global $user;
+
+  $uid = !isset($uid) ? $user->uid : $uid;
+  $ip_address = !isset($ip_address) ? ip_address() : $ip_address;
 
   $criteria = array(
     'content_type' => $type,
@@ -788,18 +819,17 @@
       $votes['count'] = $result;
     }
   }
-  if ($user->uid) {
-    $user_vote = votingapi_select_votes($criteria += array('uid' => $user->uid));
-    if ($user_vote) {
-      $votes['user'] = $user_vote[0];
-      $votes['user']['function'] = 'user';
-    }
+
+  if ($uid) {
+    $user_vote = votingapi_select_votes($criteria += array('uid' => $uid));
   }
   else {
-    // If the user is anonymous, we never bother loading their existing votes.
-    // Not only would it be hit-or-miss, it would break page caching. Safer to always
-    // show the 'fresh' version to anon users.
-    $votes['user'] = array('value' => 0);
+    $user_vote = votingapi_select_votes($criteria += array('uid' => 0, 'vote_source' => $ip_address));
+  }
+
+  if ($user_vote) {
+    $votes['user'] = $user_vote[0];
+    $votes['user']['function'] = 'user';
   }
 
   return $votes;
@@ -1012,6 +1042,11 @@
 
   $votes = fivestar_get_votes($content_type, $content_id);
 
+  // Anonymous votes are set to 0 if page caching is enabled.
+  if ($user->uid == 0 && variable_get('cache', 0) > 0) {
+    $votes['user']['value'] = 0;
+  }
+
   $values = array(
     'user' => isset($votes['user']['value']) ? $votes['user']['value'] : NULL,
     'average' => isset($votes['average']['value']) ? $votes['average']['value'] : NULL,
@@ -1048,6 +1083,11 @@
 
   $votes = fivestar_get_votes($content_type, $content_id, $tag);
 
+  // Anonymous votes are set to 0 if page caching is enabled.
+  if ($user->uid == 0 && variable_get('cache', 0) > 0) {
+    $votes['user']['value'] = 0;
+  }
+
   if ($content_type == 'node') {
     // Content type should always be passed to avoid this node load.
     if (!isset($node_type)) {
@@ -1248,7 +1288,6 @@
   if ($form_state['values']['form_id'] == 'fivestar_form_'. $form_state['values']['content_type'] .'_'. $form_state['values']['content_id']) {
     // Cast the vote.
     _fivestar_cast_vote($form_state['values']['content_type'], $form_state['values']['content_id'], $form_state['values']['vote']);
-    votingapi_recalculate_results($form_state['values']['content_type'], $form_state['values']['content_id']);
 
     // Set a message that the vote was received.
     if ($form_state['values']['vote'] === '0') {
@@ -1329,7 +1368,7 @@
   }
 
   $class = 'fivestar-form';
-  $class .= '-'. (isset($form['vote']['#tag']) ? $form['tag']['#tag'] : 'vote');
+  $class .= '-'. (isset($form['vote']['#tag']) ? $form['vote']['#tag'] : 'vote');
   $class .= '-'. (isset($form['content_id']['#value']) ? $form['content_id']['#value'] : 0);
 
   $output  = '';
@@ -1644,6 +1683,7 @@
 }
 
 function fivestar_views_widget_handler($value, $field, $columns, $summary) {
+  global $user;
 
   // If the user can't rate, use the display handler.
   if (!user_access('rate content')) {
@@ -1665,6 +1705,11 @@
 
     $votes = fivestar_get_votes($content_type, $content_id, $tag);
 
+    // Anonymous votes are set to 0 if page caching is enabled.
+    if ($user->uid == 0 && variable_get('cache', 0) > 0) {
+      $votes['user']['value'] = 0;
+    }
+
     $values = array(
       'user' => empty($votes['user']['value']) ? 0 : $votes['user']['value'],
       'average' => (int)$value,
Index: fivestar_comment.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fivestar/Attic/fivestar_comment.module,v
retrieving revision 1.1.2.4
diff -u -r1.1.2.4 fivestar_comment.module
--- fivestar_comment.module	5 Oct 2008 21:59:47 -0000	1.1.2.4
+++ fivestar_comment.module	16 Nov 2008 01:18:45 -0000
@@ -112,8 +112,11 @@
     case 'insert':
       if ($fivestar_status != FIVESTAR_COMMENT_DISABLED) {
         $comment = (object)$comment; // Comment module is inconsistent about comment data structures.
+        if (empty($comment->uid)) {
+          $comment->uid = 0;
+        }
         if ($comment->fivestar_rating) {
-          fivestar_comment_insert($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating);
+          fivestar_comment_insert($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating, $comment->status);
         }
         $comment = (array)$comment;
       }
@@ -122,11 +125,23 @@
         $comment = (object)$comment; // Comment module is inconsistent about comment data structures.
         $current_rating = fivestar_comment_load($comment->cid, $comment->nid);
         if ($comment->fivestar_rating) {
-          if (isset($current_rating['value'])) {
+          if (empty($comment->uid)) {
+            $comment->uid = 0;
+          }
+          if ($comment->status && isset($current_rating['value'])) {
+            // Update the comment rating but don't cast any vote.
+            fivestar_comment_update($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating, 0);
+          }
+          elseif (isset($current_rating['value']) && $current_rating['vote_id'] == 0) {
+            // Update the rating and cast a new vote.
             fivestar_comment_update($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating);
           }
+          elseif (isset($current_rating['value']) && $current_rating['vote_id']) {
+            // Update the rating and update the existing vote.
+            fivestar_comment_update($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating, $current_rating['vote_id']);
+          }
           else {
-            fivestar_comment_insert($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating);
+            fivestar_comment_insert($comment->cid, $comment->nid, $comment->uid, $comment->fivestar_rating, $comment->status);
           }
         }
         elseif ($fivestar_status != FIVESTAR_COMMENT_DISABLED && isset($current_rating['value'])) {
@@ -157,19 +172,36 @@
 }
 
 /**
- * Update a fivestar comment value.
+ * Update a Fivestar comment value.
+ *
+ * If $vote_id is passed in, the existing vote is updated. Otherwise a new
+ * vote is cast and the new vote_id is recorded.
  */
-function fivestar_comment_update($cid, $nid, $uid, $value) {
-  $vote = _fivestar_cast_vote('node', $nid, $value, 'vote', $uid);
-  db_query('UPDATE {fivestar_comment} SET value = %d, vote_id = %d WHERE cid = %d', $value, $vote['user']['vote_id'], $cid);
+function fivestar_comment_update($cid, $nid, $uid, $value, $vote_id = NULL) {
+  if (isset($vote_id)) {
+    if ($vote_id != 0) {
+      _fivestar_update_vote($vote_id, $value);
+    }
+    db_query('UPDATE {fivestar_comment} SET value = %d WHERE cid = %d', $value, $cid);
+  }
+  else {
+    $vote = _fivestar_cast_vote('node', $nid, $value, 'vote', $uid);
+    db_query('UPDATE {fivestar_comment} SET value = %d, vote_id = %d WHERE cid = %d', $value, $vote['user']['vote_id'], $cid);
+  }
 }
 
 /**
  * Insert a fivestar comment value.
  */
-function fivestar_comment_insert($cid, $nid, $uid, $value) {
-  $vote = _fivestar_cast_vote('node', $nid, $value, 'vote', $uid);
-  db_query('INSERT INTO {fivestar_comment} (cid, value) VALUES (%d, %d)', $cid, $vote['user']['vote_id'], $value);
+function fivestar_comment_insert($cid, $nid, $uid, $value, $moderated) {
+  if ($moderated) {
+    // Moderated comments don't cast a vote until approved.
+    db_query('INSERT INTO {fivestar_comment} (cid, value) VALUES (%d, %d)', $cid, $value);
+  }
+  else {
+    $vote = _fivestar_cast_vote('node', $nid, $value, 'vote', $uid);
+    db_query('INSERT INTO {fivestar_comment} (vote_id, cid, value) VALUES (%d, %d, %d)', $vote['user']['vote_id'], $cid, $value);
+  }
 }
 
 /**
