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.4
diff -u -p -r1.4 comment_alter_taxonomy.module
--- comment_alter_taxonomy.module	21 Sep 2008 21:59:36 -0000	1.4
+++ comment_alter_taxonomy.module	21 Sep 2008 23:00:34 -0000
@@ -7,9 +7,6 @@
  * parent node from inside of a comment.
  */
 
-// Note:  This module requires PHP > 5.1.0 due to use of the array_intersect_key() PHP function.
-
-
 /**
  * Implementation of hook_perm().
  */
@@ -57,6 +54,7 @@ function comment_alter_taxonomy_admin_se
     '#type' => 'checkboxes',
     '#title' => t('Vocabularies that may be altered'),
     '#options' => $options,
+    '#array_filter' => TRUE,
     '#default_value' => array_filter(variable_get('comment_alter_taxonomy_vocabularies', array())),
   );
 
@@ -68,12 +66,6 @@ function comment_alter_taxonomy_admin_se
  */
 function comment_alter_taxonomy_form_alter($form_id, &$form) {
   switch ($form_id) {
-    case 'comment_form':
-      if (isset($form['taxonomy'])) {
-        $form['#validate']['comment_alter_taxonomy_validate'] = array();
-      }
-      break;
-
     case 'comment_admin_overview':
       // {comment_alter_taxonomy} may need to be updated if any comments are edited/deleted.
       $form['#submit']['comment_alter_taxonomy_comment_mass_update'] = array();
@@ -102,161 +94,51 @@ function comment_alter_taxonomy_form_alt
 function comment_alter_taxonomy_comment_form($form) {
   // Prepare some variables for later checking.
   $node = node_load($form['nid']['#value']);
-  $type = check_plain($node->type);
-  $access = "alter taxonomy on $type content";
+  $access = user_access("alter taxonomy on ". check_plain($node->type) ." content");
 
-  // It would be nice to be able to use the comment_alter_taxonomy_get_alterable_vocabularies()
-  // function here, but we actually need all of the vocabulary objects as well.
-  $vocabularies = taxonomy_get_vocabularies($type);
-  $enabled = array_keys($vocabularies);
-  $allowed = variable_get('comment_alter_taxonomy_vocabularies', array());
-  $intersect = array_intersect($enabled, $allowed);
-
-  if (!empty($enabled)) {
-    // We need to store the current taxonomy terms assigned to the node so that later,
-    // after form submission, we can add those terms that are currently assigned to the node but
-    // which the user is not given permission to alter in the comment back to the node.
-    // This is necessary because taxonomy_node_save() first deletes all terms on a node
-    // and then adds back those terms from the edit of the node.
-    foreach ($enabled as $vid) {
-      _comment_alter_taxonomy_vocabulary_form($vocabularies[$vid], $node, $form);
-    }
-
-    // Now put $form['taxonomy'] into a different form element that will not be included
-    // as part of the HTML that goes out to the user but will later be included in $form_values
-    // so we can process it.
-    $form['comment_alter_taxonomy_original_taxonomy'] = array(
-      '#type' => 'value',
-      '#value' => _comment_alter_taxonomy_taxonomy_form_parse($form['taxonomy']),
-    );
+  $vocabularies = taxonomy_get_vocabularies($node->type);
+  $allowed = $access ? comment_alter_taxonomy_get_alterable_vocabularies($node->type) : array();
 
-    unset($form['taxonomy']);
+  // We need to store the current taxonomy terms assigned to the node so that later,
+  // after form submission, we can add those terms that are currently assigned to the node but
+  // which the user is not given permission to alter in the comment back to the node.
+  // This is necessary because taxonomy_node_save() first deletes all terms on a node
+  // and then adds back those terms from the edit of the node.
+  foreach ($vocabularies as $vid => $vocabulary) {
+    _comment_alter_taxonomy_vocabulary_form($vocabulary, $node, $form, !isset($allowed[$vid]));
   }
 
-  // Only proceed if user has access to alter tags on this node type, and if
-  // node type has vocabularies enabled on it which can be altered.
-  if (user_access($access) && !empty($intersect)) {
-
-    // Display the edit form for each qualifying vocabulary.
-    foreach ($intersect as $vid) {
-      _comment_alter_taxonomy_vocabulary_form($vocabularies[$vid], $node, $form);
-    }
-
-    if (isset($form['taxonomy']) && !empty($form['taxonomy'])) {
-      // Add fieldset only if form has more than 1 element.
-      if (count($form['taxonomy']) > 1) {
-        $form['taxonomy'] += array(
-          '#type' => 'fieldset',
-          '#title' => t('Categories'),
-          '#collapsible' => TRUE,
-          '#collapsed' => FALSE,
-        );
-      }
-      $form['taxonomy']['#weight'] = -3;
-      $form['taxonomy']['#tree'] = TRUE;
-    }
-
-    // Add a place to put the output of
-    // comment_alter_taxonomy_validate().
-    $form['comment_alter_taxonomy_all_taxonomy'] = array(
-      '#type' => 'value',
-      '#value' => array(),
+  // Add fieldset only if form has more than 1 element.
+  if (count($allowed) > 1) {
+    $form['taxonomy'] += array(
+      '#type' => 'fieldset',
+      '#title' => t('Categories'),
+      '#collapsible' => TRUE,
+      '#collapsed' => FALSE,
     );
-    return $form;
   }
+  $form['taxonomy']['#weight'] = -3;
+  $form['taxonomy']['#tree'] = TRUE;
+  return $form;
 }
 
 /**
- * Processes an FAPI taxonomy array and returns an array
- * which is identical to what $node->taxonomy object
- * will look like after form validation.
- *
- * @param $taxonomy_form
- *   An FAPI array with the various elements necessary for
- *   a user to add/edit taxonomy terms.
- * @return
- *   An array identical in structure to that found in
- *   $node->taxonomy after submission of a node add/edit form.
- */
-function _comment_alter_taxonomy_taxonomy_form_parse($taxonomy_form = array()) {
-  $taxonomy = array();
-  foreach ($taxonomy_form as $key => $value) {
-    if ($key == 'tags') {
-      // Free tag vocabularies.
-      foreach ($value as $vid => $term) {
-          $taxonomy['tags'][$vid] = $term['#default_value'];
-      }
-    }
-    else {
-      $taxonomy[$key] = $value['#multiple'] ? drupal_map_assoc(array_values($value['#default_value'])) : $value['#default_value'][0];
-    }
-  }
-  return $taxonomy;
-}
-
-/**
- * Create an array that contains all taxonomy terms
- * assigned to a node.  This includes vocabularies found
- * in ['comment_alter_taxnomoy_original_taxonomy'] but not
- * in ['taxonomy'] because that given vocabulary was not alterable
- * by this module.
- */
-function comment_alter_taxonomy_validate($form_id, $form_values, $form) {
-  if (!isset($form_values['comment_alter_taxonomy_original_taxonomy']) || !isset($form_values['taxonomy'])) {
-    return;
-  }
-
-  $new_taxonomy = $form_values['taxonomy'];
-  $original_taxonomy = $form_values['comment_alter_taxonomy_original_taxonomy'];
-
-  form_set_value($form['comment_alter_taxonomy_all_taxonomy'], _comment_alter_taxonomy_all_taxonomy($original_taxonomy, $new_taxonomy));
-}
-
-/**
- * Takes two arrays of taxonomy terms in the format found in $node->taxonomy
- * after a node is submitted and merges them into one array that contains
- * all terms/vocabularies found in $new_taxonomy and all vocabularies/terms found
- * in $original_taxonomy but *not* found in $new_taxonomy.
- *
- * @param $original_taxonomy
- *   An array of taxonomy terms (as found in $node->taxonomy) originally
- *   present in a node.
- * @param $new_taxonomy
- *   An array of taxonomy terms (as found in $node->taxonomy) as set
- *   by a comment.  Because all vocabularies assigned to a node type might
- *   not necessairly be alterable by comment_alter_taxonomy, this array
- *   may not contain all vocabularies found in $original_taxonomy.
- * @return
- *   An array that contains all terms/vocabularies found in
- *  $new_taxonomy and all vocabularies/terms found in $original_taxonomy
- *  but *not* found in $new_taxonomy.
- */
-function _comment_alter_taxonomy_all_taxonomy($original_taxonomy = array(), $new_taxonomy = array()) {
-  $all_taxonomy = array();
-  foreach ($original_taxonomy as $key => $value) {
-    if ($key == 'tags') {
-      foreach ($value as $vid => $tags) {
-        if (!isset($all_taxonomy['tags'][$vid])) {
-          $all_taxonomy['tags'][$vid] = $new_taxonomy['tags'][$vid];
-        }
-      }
-    }
-    elseif (!isset($all_taxonomy[$key])) {
-      $all_taxonomy[$key] = $new_taxonomy[$key];
-    }
-  }
-  return $all_taxonomy;
-}
-
-
-
-/**
- * Generate taxonomy forms for a given set of vocabulary IDs.
+ * Generate taxonomy form for a given vocabulary.
  *
  * This is kind of nasty; mostly a copy/paste of taxonomy_form_alter, which is
  * a big glop of stuff.
+ *
+ * @param $vocabulary
+ *   A vocabulary object.
+ * @param $node
+ *   A node object.
+ * @param $form
+ *   The form array onto which the vocabulary widget should be placed.
+ * @param $disabled
+ *   Whether or not this widget should be disabled, for example if the user
+ *   does not have the permission to alter terms for this vocabulary.
  */
-function _comment_alter_taxonomy_vocabulary_form($vocabulary, $node, &$form) {
+function _comment_alter_taxonomy_vocabulary_form($vocabulary, $node, &$form, $disabled = FALSE) {
   // Determine existing term assignments, if any.
   if (!isset($node->taxonomy)) {
     if ($node->nid) {
@@ -305,6 +187,9 @@ function _comment_alter_taxonomy_vocabul
       '#maxlength' => 255,
       '#tree' => TRUE,
     );
+    if ($disabled) {
+      _comment_alter_taxonomy_disable_element($form['taxonomy']['tags'][$vocabulary->vid]);
+    }
   }
   else {
     // Extract terms belonging to the vocabulary in question.
@@ -315,6 +200,9 @@ function _comment_alter_taxonomy_vocabul
       }
     }
     $form['taxonomy'][$vocabulary->vid] = taxonomy_form($vocabulary->vid, array_keys($default_terms), $vocabulary->help);
+    if ($disabled) {
+      _comment_alter_taxonomy_disable_element($form['taxonomy'][$vocabulary->vid]);
+    }
     $form['taxonomy'][$vocabulary->vid]['#weight'] = $vocabulary->weight;
     $form['taxonomy'][$vocabulary->vid]['#required'] = $vocabulary->required;
     $form['taxonomy'][$vocabulary->vid]['#tree'] = TRUE;
@@ -322,6 +210,25 @@ function _comment_alter_taxonomy_vocabul
 }
 
 /**
+ * Recursively disable a form tree, transforming input element in value callbacks.
+ */
+function _comment_alter_taxonomy_disable_element(&$element) {
+  if (isset($element['#type'])) {
+    if (isset($element['#default_value'])) {
+      $element['#type'] = 'value';
+      $element['#value'] = $element['#default_value'];
+    }
+    else {
+      unset($element['#type']);
+    }
+    unset($element['#theme']);
+  }
+  foreach (element_children($element) as $child) {
+    _comment_alter_taxonomy_disable_element($element[$child]);
+  }
+}
+
+/**
  * Implementation of hook_comment().
  */
 function comment_alter_taxonomy_comment($arg, $op) {
@@ -335,37 +242,22 @@ function comment_alter_taxonomy_comment(
     return comment_alter_taxonomy_comment_form($arg);
 
     case 'insert':
-      if (isset($arg['comment_alter_taxonomy_all_taxonomy'])) {
-        // In comment_alter_taxonomy_validate() we saved an array
-        // containing all terms now assigned to the node (both those
-        // that were present before the comment and those the user
-        // added or removed via the comment).  We'll take that array
-        // here and then save all terms in that array to our own table.
-        $all_taxonomy = $arg['comment_alter_taxonomy_all_taxonomy'];
-
-        // Get the current taxonomy terms assigned to this node.
-        $tids = array_keys(taxonomy_node_get_terms($arg['nid'], 'tid'));
-
-        // 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.
-        //
-        // TODO: Test:  See if this actually works as intended.
-        //
-        if (!db_num_rows(db_query('SELECT cid FROM {comment_alter_taxonomy} WHERE nid = %d', $arg['nid']))) {
-          foreach ($tids as $tid) {
-            if (!empty($tid)) {
-              db_query('INSERT INTO {comment_alter_taxonomy} (nid, cid, tid) VALUES (%d, %d, %d)', $arg['nid'], 0, $tid);
-            }
-          }
-        }
+      // 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']))) {
+        _comment_alter_taxonomy_save_tids($arg['nid'], 0);
+      }
 
+      if (isset($arg['taxonomy'])) {
         // Save the terms to the node itself.
-        taxonomy_node_save($arg['nid'], $all_taxonomy);
+        taxonomy_node_save($arg['nid'], $arg['taxonomy']);
         // Load the node again so we can reset the internal node_load cache.
-        $new_node = 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'], $all_taxonomy);
+        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']);
+
       break;
 
     case 'unpublish':
@@ -404,17 +296,16 @@ function comment_alter_taxonomy_comment(
  * @param $cid
  *   The cid of the comment.  Set this to 0 if this is the original
  *   node and not an actual comment.
- * @param $taxonomy
- *   An array of taxonomy term ids that should be saved for this comment.
  */
-function _comment_alter_taxonomy_save_tids($nid, $cid, $taxonomy) {
-  $tids = array_keys(comment_alter_taxonomy_taxonomy_node_get_terms($nid, 'tid'));
-  foreach ($tids as $tid) {
-    if (!empty($tid)) {
-      db_query('INSERT INTO {comment_alter_taxonomy} (nid, cid, tid) VALUES (%d, %d, %d)', $nid, $cid, $tid);
-    }
+function _comment_alter_taxonomy_save_tids($nid, $cid) {
+  if ($cid == 0) {
+    // 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);
   }
-
 }
 
 /**
@@ -505,7 +396,7 @@ function comment_alter_taxonomy_project_
         $grouped_terms = array();
         foreach ($terms as $tid => $term) {
           $vid = $term->vid;
-          if (array_key_exists($vid, $allowed)) {
+          if (isset($allowed[$vid])) {
             if (!isset($metadata["taxonomy_vid_$vid"])) {
               $vocabulary = $allowed[$vid];
               $metadata["taxonomy_vid_$vid"] = array('label' => check_plain(t("$vocabulary->name")));
@@ -520,9 +411,6 @@ function comment_alter_taxonomy_project_
       }
 
     case 'diff':
-      $old_cid = isset($old_data->cid) ? $old_data->cid : 0;
-      $new_cid = isset($new_data->cid) ? $new_data->cid : 0;
-
       // Get an array containing all vocabulary objects that are associated
       // with project_issue nodes and which are alterable by comment_alter_taxonomy.
       $allowed = comment_alter_taxonomy_get_alterable_vocabularies('project_issue');
@@ -548,58 +436,20 @@ function comment_alter_taxonomy_project_
           );
       }
 
-      $old_terms = array();
-      if (!empty($old_data)) {
-        $old_terms = comment_alter_taxonomy_get_terms($node->nid, $old_cid);
-      }
-
-      // We want to display metadata changes in previews
-      // and allow taxonomy changes (by themselves) to be allowed in project_issue comments.
-      // The presence of $new_data->comment_alter_taxonomy_all_taxonomy and $new_data->taxonomy
-      // indicate that $new_data is being validated or submitted.  If that's the case,
-      // the new terms will not yet be saved to the database so to determine the terms assigned
-      // we have to look at these fields.
-      $new_terms = array();
-      if (isset($new_data->comment_alter_taxonomy_all_taxonomy) && isset($new_data->taxonomy)) {
-        $all_new_terms = _comment_alter_taxonomy_all_taxonomy($new_data->comment_alter_taxonomy_original_taxonomy, $new_data->taxonomy);
-        // Because the project_issue module will, when validating a comment on a project_issue,
-        // pass the actual issue node as $old_data, and not the previous comment.  That means
-        // that cid will not be set, and so $old_cid = 0 was passed to comment_alter_taxonomy_get_terms()
-        // above.  Thus, $old_terms will contain not the terms as they were after the most recent comment, but
-        // instead the original terms.  That's not what we want here.  To work around this problem, since
-        // we already have the most recent state of all taxonomy terms when the comment form was built stored in
-        // $new_data->comment_alter_taxonomy_original_taxonomy, we'll just pass that array to
-        // _comment_alter_taxonomy_build_term_list() which will give us a nice array of all terms like we need.
-        $old_terms = _comment_alter_taxonomy_build_term_list($new_data->comment_alter_taxonomy_original_taxonomy);
-        $new_terms = _comment_alter_taxonomy_build_term_list($all_new_terms);
-      }
-      else {
-        $new_terms = comment_alter_taxonomy_get_terms($node->nid, $new_cid);
-      }
+      $old_terms = _comment_alter_taxonomy_build_term_list($node->nid, $old_data);
+      $new_terms = _comment_alter_taxonomy_build_term_list($node->nid, $new_data);
 
-      if (empty($old_terms)) {
-        $all_terms = $new_terms;
-      }
-      elseif (empty($new_terms)) {
-        $all_terms = $old_terms;
-      }
-      else {
-        // array_merge() doesn't work here because it doesn't preserve the keys.
-        $all_terms = $old_terms;
-        foreach ($new_terms as $tid => $term) {
-          $all_terms[$tid] = $term;
-        }
-      }
+      $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.
-          if (!empty($old_terms) && !empty($new_terms) && array_key_exists($tid, $old_terms) && array_key_exists($tid, $new_terms)) {
+          if (!empty($old_terms) && !empty($new_terms) && isset($old_terms[$tid]) && isset($new_terms[$tid])) {
             continue;
           }
 
-          $vid = $term['vid'];
+          $vid = $term->vid;
           // Skip this term if its not associated with a vocabulary that's alterable
           // by comment_alter_taxonomy.
           if (!isset($metadata["taxonomy_vid_$vid"])) {
@@ -608,7 +458,7 @@ function comment_alter_taxonomy_project_
 
           // Determine if this term goes in the 'old' or 'new' element of
           // the $metadata array.
-          if (!empty($old_terms) && array_key_exists($tid, $old_terms)) {
+          if (isset($old_terms[$tid])) {
             $old_new = 'old';
           }
           else {
@@ -616,15 +466,16 @@ function comment_alter_taxonomy_project_
           }
 
           // Add this term change to the $metadata array.
+          $themed_term = theme('comment_alter_taxonomy_project_issue_metadata_term', $term);
           if (is_array($metadata["taxonomy_vid_$vid"][$old_new])) {
             // Multiple select vocabulary.
-            $metadata["taxonomy_vid_$vid"][$old_new][$tid] = theme('comment_alter_taxonomy_project_issue_metadata_term', (object) $term);
+            $metadata["taxonomy_vid_$vid"][$old_new][$tid] = $themed_term;
           }
           elseif (!empty($metadata["taxonomy_vid_$vid"][$old_new])) {
-            $metadata["taxonomy_vid_$vid"][$old_new] .= ', '. theme('comment_alter_taxonomy_project_issue_metadata_term', (object) $term);
+            $metadata["taxonomy_vid_$vid"][$old_new] .= ', '. $themed_term;
           }
           else {
-            $metadata["taxonomy_vid_$vid"][$old_new] = theme('comment_alter_taxonomy_project_issue_metadata_term', (object) $term);
+            $metadata["taxonomy_vid_$vid"][$old_new] = $themed_term;
           }
         }
       }
@@ -640,6 +491,7 @@ function comment_alter_taxonomy_project_
       break;
   }
 }
+
 /**
  * Theme a taxonomy term in a project issue metadata table.
  *
@@ -660,9 +512,8 @@ function theme_comment_alter_taxonomy_pr
  * is currently being validated or submitted, and return an array
  * containing each term object (when possible) as an element of the array.
  *
- * @param $terms
- *   An array containing all terms assigned, formatted in the same
- *   way that $node->taxonomy is formatted when a node is saved.
+ * @param $comment
+ *   Either a comment or the result of a posted comment.
  * @return
  *   A straight array (not nested) of terms with the tid of each
  *   term in the key of the array, when possible.  For new free tagging
@@ -671,50 +522,62 @@ function theme_comment_alter_taxonomy_pr
  *   all information we actually know about the term is included
  *   instead.
  */
-function _comment_alter_taxonomy_build_term_list($terms) {
+function _comment_alter_taxonomy_build_term_list($nid, $comment) {
   $term_list = array();
-  foreach ($terms as $key => $value) {
-    if ($key == 'tags') {
-      foreach ($value as $vid => $tags) {
-        $tags_array = explode(',', $tags);
-        foreach ($tags_array as $tag) {
-          $tag = trim($tag);
-          if (empty($tag)) {
-            continue;
-          }
+  if (isset($comment->taxonomy)) {
+    foreach ($comment->taxonomy as $key => $value) {
+      if ($key == 'tags') {
+        foreach ($value as $vid => $tags) {
+          $tags_array = explode(',', $tags);
+          foreach ($tags_array as $tag) {
+            $tag = trim($tag);
+            if (empty($tag)) {
+              continue;
+            }
 
-          // See if the term exists in the chosen vocabulary
-          // and return the tid; otherwise, add a new record.
-          // This block is modified from taxonomy_node_save().
-          $possibilities = taxonomy_get_term_by_name($tag);
-          $tag_tid = NULL; // tid match, if any.
-          foreach ($possibilities as $possibility) {
-            if ($possibility->vid == $vid) {
-              $tag_tid = $possibility->tid;
-              $term_list[$tag_tid] = (array) taxonomy_get_term($tag_tid);
+            // See if the term exists in the chosen vocabulary
+            // and return the tid; otherwise, add a new record.
+            // This block is modified from taxonomy_node_save().
+            $possibilities = taxonomy_get_term_by_name($tag);
+            $tag_tid = NULL; // tid match, if any.
+            foreach ($possibilities as $possibility) {
+              if ($possibility->vid == $vid) {
+                $tag_tid = $possibility->tid;
+                $term_list[$tag_tid] = taxonomy_get_term($tag_tid);
+              }
+            }
+            // This term is not in the database yet.  Add what we know about
+            // it to the $term_list array.  We use a hack here for the key
+            // since we don't want to accidentally overwrite another term in $term_list.
+            if (empty($tag_tid)) {
+              $term_list["$vid***$tag"] = array(
+                'tid' => NULL,
+                'vid' => $vid,
+                'name' => $tag,
+              );
+              $tag_tid = NULL;
             }
-          }
-          // This term is not in the database yet.  Add what we know about
-          // it to the $term_list array.  We use a hack here for the key
-          // since we don't want to accidentally overwrite another term in $term_list.
-          if (empty($tag_tid)) {
-            $term_list["$vid***$tag"] = array(
-              'tid' => NULL,
-              'vid' => $vid,
-              'name' => $tag,
-            );
-            $tag_tid = NULL;
           }
         }
       }
-    }
-    elseif (is_array($value)) {
-      foreach ($value as $tid) {
-        $term_list[$tid] = (array) taxonomy_get_term($tid);
+      elseif (is_object($value)) {
+        $term_list[$key] = $value;
+      }
+      elseif (is_array($value)) {
+        foreach ($value as $tid) {
+          $term_list[$tid] = taxonomy_get_term($tid);
+        }
+      }
+      else {
+        $term_list[$value] = taxonomy_get_term($value);
       }
     }
-    else {
-      $term_list[$value] = (array) taxonomy_get_term($value);
+  }
+  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);
+    while ($term = db_fetch_object($result)) {
+      $term_list[$term->tid] = $term;
     }
   }
   return $term_list;
@@ -808,33 +671,32 @@ function comment_alter_taxonomy_nodeapi(
  * that can be altered via comment_alter_taxonomy.
  *
  * @param $type
- *   If set, return only those vocabularies associated with this single node type.
+ *   Type of node for which to get vocabularies.
+ * @param $reset
+ *   Whether to reset the internal vocabularies cache.
  * @return
  *   An array of vocabulary objects that are alterable by this module.
  */
-function comment_alter_taxonomy_get_alterable_vocabularies($type = NULL) {
-  $vocabularies = taxonomy_get_vocabularies($type);
-  $enabled = array_keys($vocabularies);
-  $allowed = variable_get('comment_alter_taxonomy_vocabularies', array());
-  $intersect = array_intersect($enabled, $allowed);
-  return array_intersect_key($vocabularies, array_flip($intersect));
-}
-
-///**
-// * @return
-// *  An array with each value representing one vid present in $taxonomy.
-// */
-//function _comment_alter_taxonomy_get_vid_array($taxonomy) {
-//  $vid_array = array_keys($taxonomy);
-//  if (!empty($taxonomy) && array_key_exists('tags', $taxonomy)) {
-//
-//    $tag_vids = array_keys($taxonomy['tags']);
-//    $vid_array = array_merge($vid_array, $tag_vids);
-//  }
-//  return $vid_array;
-//}
+function comment_alter_taxonomy_get_alterable_vocabularies($type, $reset = NULL) {
+  static $vocabularies = NULL;
+
+  if ($reset) {
+    $vocabularies = NULL;
+  }
+
+  if (!isset($vocabularies[$type])) {
+    $vocabularies[$type] = array();
+    $all_vocabularies = taxonomy_get_vocabularies($type);
+    $alterable_vocabularies = variable_get('comment_alter_taxonomy_vocabularies', array());
+    foreach ($all_vocabularies as $vid => $vocabulary) {
+      if (!empty($alterable_vocabularies[$vid])) {
+        $vocabularies[$type][$vid] = $vocabulary;
+      }
+    }
+  }
+  return $vocabularies[$type];
+}
 
 // Unresolved problems:
 // TODO:  What do do when a comment is deleted.
 // TODO:  What do to when a comment is unpublished.
-// TODO:  Where should original data about taxonomy terms be stored?  In hook_comment() or in hook_nodeapi()?
