? 318302_cat_save_improvement_3.patch
? 318302_cat_save_improvement_4.patch
? cat-save-improvement.patch
Index: /Applications/MAMP/htdocs/freetags/drupal/sites/all/modules/comment_alter_taxonomy/comment_alter_taxonomy.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/comment_alter_taxonomy/comment_alter_taxonomy.module,v
retrieving revision 1.10
diff -u -p -r1.10 comment_alter_taxonomy.module
--- comment_alter_taxonomy.module	14 Nov 2008 12:18:28 -0000	1.10
+++ comment_alter_taxonomy.module	16 Nov 2008 19:25:32 -0000
@@ -239,49 +239,28 @@ function comment_alter_taxonomy_comment(
       if (isset($arg['cid']['#value'])) {
         return array();
       }
-    return comment_alter_taxonomy_comment_form($arg);
+      return comment_alter_taxonomy_comment_form($arg);
 
     case 'insert':
-      // See if we already have a record of this node in {comment_alter_taxonomy} and if
-      // not save the "original" state of the taxonomy terms of this node.
-      if (!db_result(db_query_range('SELECT nid FROM {comment_alter_taxonomy} WHERE nid = %d AND cid = 0', $arg['nid'], 0, 1))) {
-        _comment_alter_taxonomy_save_tids($arg['nid'], 0);
-      }
-
-      // Create rows in {comment_alter_taxonomy} for any comments on this node
-      // between the last comment saved to the table and this comment.  If there
-      // are any such comments, then store term data for those comments based
-      // on the data present in the last saved comment for this node in the table.
-      // This is necessary to prevent the module from thinking that terms were
-      // deleted by a comment between the last comment in the table and this comment.
-      // This code is really only necessary in the rare case when this module is disabled
-      // and one or more comments is made on a node, and then the module is re-enabled.
-      $result = db_query("SELECT cid FROM {comments} WHERE nid = %d AND cid > (SELECT MAX(cid) FROM {comment_alter_taxonomy} WHERE nid = %d) AND cid <> %d", $arg['nid'], $arg['nid'], $arg['cid']);
-      while ($row = db_fetch_object($result)) {
-        _comment_alter_taxonomy_save_tids($arg['nid'], $row->cid);
-      }
-
       if (isset($arg['taxonomy'])) {
+        // Fetch the cid of the previous comment and store the tids of the current node if necessary.
+        $previous_cid = (int)db_result(db_query_range('SELECT cid FROM {comments} WHERE nid = %d AND cid < %d ORDER BY cid DESC', $arg['nid'], $arg['cid'], 0, 1));
+        _comment_alter_taxonomy_save_tids($arg['nid'], $previous_cid);
+
         // Save the terms to the node itself.
         taxonomy_node_save($arg['nid'], $arg['taxonomy']);
+
         // Load the node again so we can reset the internal node_load cache.
         node_load($arg['nid'], NULL, TRUE);
-      }
 
-      // Save the tids assigned to the node at this point to the {comment_alter_taxonomy} table.
-      _comment_alter_taxonomy_save_tids($arg['nid'], $arg['cid']);
+        // Store the tids assigned to the node at this point to the {comment_alter_taxonomy} table.
+        _comment_alter_taxonomy_save_tids($arg['nid'], $arg['cid']);
+      }
       break;
 
     case 'delete':
       db_query("DELETE FROM {comment_alter_taxonomy} WHERE cid = %d", $arg->cid);
       break;
-
-    case 'validate':
-      // Only validate term changes on new followups.
-      if (isset($arg['cid'])) {
-        return;
-      }
-      break;
   }
 }
 
@@ -299,13 +278,20 @@ function comment_alter_taxonomy_comment(
  *   node and not an actual comment.
  */
 function _comment_alter_taxonomy_save_tids($nid, $cid) {
-  if ($cid == 0) {
+  if (!db_result(db_query_range("SELECT cid FROM {comment_alter_taxonomy} WHERE nid = %d AND cid = %d", $nid, $cid, 0, 1))) {
     // Insert a fake term to have rows in the table even if the node has no terms.
-    db_query("INSERT INTO {comment_alter_taxonomy} (nid, cid, tid) VALUES (%d, %d, %d)", $nid, $cid, 0);
-  }
-  $res = db_query("SELECT tid FROM {term_node} WHERE nid = %d", $nid);
-  while ($term = db_fetch_object($res)) {
-    db_query("INSERT INTO {comment_alter_taxonomy} (nid, cid, tid) VALUES(%d, %d, %d)", $nid, $cid, $term->tid);
+    // These queries could fail in case of concurrent access.
+    @db_query("INSERT INTO {comment_alter_taxonomy} (nid, cid, tid) VALUES (%d, %d, %d)", $nid, $cid, 0);
+    $res = db_query("SELECT tid FROM {term_node} WHERE nid = %d", $nid);
+    $count = 0;
+    while ($term = db_fetch_object($res)) {
+      @db_query("INSERT INTO {comment_alter_taxonomy} (nid, cid, tid) VALUES (%d, %d, %d)", $nid, $cid, $term->tid);
+      $count++;
+    }
+    if ($count > 0) {
+      // Remove the dummy tid = 0 term.
+      db_query("DELETE FROM {comment_alter_taxonomy} WHERE nid = %d AND cid = %d and tid = 0", $nid, $cid);
+    }
   }
 }
 
@@ -426,9 +412,10 @@ function comment_alter_taxonomy_project_
       $old_terms = _comment_alter_taxonomy_build_term_list($node->nid, $old_data);
       $new_terms = _comment_alter_taxonomy_build_term_list($node->nid, $new_data);
 
-      $all_terms = $old_terms + $new_terms;
+      if ($old_terms !== FALSE && $new_terms !== FALSE && (!empty($old_terms) || !empty($new_terms))) {
+        // Merge all terms together.
+        $all_terms = $old_terms + $new_terms;
 
-      if (!empty($all_terms)) {
         foreach ($all_terms as $tid => $term) {
           // If a term is in both $old_terms and $new_terms, than it didn't change and we can ignore
           // it since we're only interested in terms that were changed between $old_data and $new_data.
@@ -569,10 +556,19 @@ function _comment_alter_taxonomy_build_t
   }
   else {
     $cid = isset($comment->cid) ? $comment->cid : 0;
-    $result = db_query(db_rewrite_sql('SELECT t.* FROM {comment_alter_taxonomy} cat INNER JOIN {term_data} t ON cat.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE cat.nid = %d AND cat.cid = %d AND t.tid <> 0 ORDER BY v.weight, t.weight, t.name', 't', 'tid'), $nid, $cid);
+    $result = db_query(db_rewrite_sql('SELECT t.* FROM {comment_alter_taxonomy} cat INNER JOIN {term_data} t ON cat.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE cat.nid = %d AND cat.cid = %d ORDER BY v.weight, t.weight, t.name', 't', 'tid'), $nid, $cid);
     while ($term = db_fetch_object($result)) {
       $term_list[$term->tid] = $term;
     }
+    if (empty($term_list)) {
+      // This cannot be empty because we save a dummy tid = 0 term even if the
+      // node was associated to no terms at the time the comment was saved.
+      // This can only mean that this module was not enabled at that time,
+      // so abort the diff.
+      return FALSE;
+    }
+    // Remove the dummy tid = 0 if set.
+    unset($term_list[0]);
   }
   return $term_list;
 }
@@ -694,7 +690,7 @@ function comment_alter_taxonomy_get_alte
  * Handle deletion of terms and vocabularies from the database.
  */
 function comment_alter_taxonomy_taxonomy($op, $type, $array = NULL) {
-  if ($op == delete) {
+  if ($op == 'delete') {
     if ($type == 'vocabulary') {
       // Delete this vocabulary from the comment_alter_taxonomy_vocabularies variable.
       // When a vocabulary is deleted this hook is first called for each term
