Index: taxonomy_user.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/taxonomy_user/taxonomy_user.module,v
retrieving revision 1.4
diff -u -p -r1.4 taxonomy_user.module
--- taxonomy_user.module	16 Dec 2006 17:02:13 -0000	1.4
+++ taxonomy_user.module	9 Feb 2007 01:49:23 -0000
@@ -1,516 +1,610 @@
-<?php
-
-/**
- * taxonomy_user - stores which users tagged what with a shared free tagging vocabulary
- */
-define('TU_POS_LINKS', 0);
-define('TU_POS_TOP', 2);
-define('TU_POS_BOTTOM', 4);
-
-/**
- * implementation of hook_help()
- */
-function taxonomy_user_help($section) {
-  
-  switch ($section) {
-    case 'admin/modules#description':
-      return t('Relates users to tags on nodes. The tags of the current user will be highlighted. Requires taxonomy module. 
-                Once installed, go to admin/categories and enable "Relate terms and users" for the vocabularies of your choice.
-                WARNING: Use fresh vocabulary. For more information, consult README file.');
-  }
-}
-
-/**
- * settings hook
- */
-function taxonomy_user_settings() {
-  $form = array();
-  
-  $form['taxonomy_user_tag_pos'] = array(
-    '#type' => 'select',
-    '#title' => t('Position of terms'),
-    '#default_value' => variable_get('taxonomy_user_tag_pos', TU_POS_BOTTOM),
-    '#options' => array(TU_POS_LINKS => 'With all other terms', TU_POS_TOP => 'Text top', TU_POS_BOTTOM => 'Text bottom'),
-    '#description' => t('Select where user taxonomy terms should show up. 
-      Note that if you select "With all other terms", terms of the current user and terms of all 
-      other users will not be set apart.'),
-    );
-  return $form;
-}
-
-/**
- * Implementation of hook_taxonomy().
- */
-function taxonomy_user_taxonomy($op, $type, $object = NULL) {
-  
-  switch ($op) {
-    case 'form':
-      switch ($type) {
-        case 'vocabulary':
-          return array('userterms' => array('#type' => 'checkboxes',
-                '#title' => t('User terms'),
-                '#default_value' => variable_get('taxonomy_user_vocab_'.$object['vid'], 0),
-                '#options' => array(1 => t('Relate terms and users (Only works if free tagging enabled)')),
-                '#description' => t('Relates terms in the vocabulary to the users that associated them to a node.'),
-                '#weight' => 1,
-                  ));
-          break;
-      }
-      break;
-    case 'update':
-    case 'insert':
-      switch ($type) {
-        case 'vocabulary':
-        if ($object['tags'] == 1) {
-          variable_set('taxonomy_user_vocab_'.$object['vid'], $object['userterms'][1]);
-          if ($object['userterms'][1]) {
-            db_query('UPDATE {vocabulary} SET module = "taxonomy_user" WHERE vid = %d', $object['vid']);
-          }
-          else {
-            db_query('UPDATE {vocabulary} SET module = "taxonomy" WHERE vid = %d', $object['vid']);
-          }
-        }
-        else {
-          variable_set('taxonomy_user_vocab_'.$object['vid'], 0);
-          db_query('UPDATE {vocabulary} SET module = "taxonomy" WHERE vid = %d', $object['vid']);
-        }
-        break;
-      }
-      break;
-    case 'delete':
-      switch ($type) {
-        case 'vocabulary':
-        variable_del('taxonomy_user_vocab_'.$object['vid']);
-        break;
-      }
-      break;
-  }
-}
-
-/**
- * implementation of hook_form_alter()
- */
-function taxonomy_user_form_alter($form_id, &$form) {
-  
-  if ($form_id == 'taxonomy_form_vocabulary') {
-    $form['submit']['#weight'] = 2;
-    $form['delete']['#weight'] = 2;
-  }
-  else if (strpos($form_id, '_node_form') !== false) {
-    
-    global $user;
-    
-    if (isset($form['taxonomy']['tags'])) {
-      
-      // check each free tagging category, if marked for user taxonomy -
-      // if so, get all according terms from term_node_user and sort out those that are not this user's terms
-      foreach ($form['taxonomy']['tags'] as $vid => $tags) {
-        
-        if (variable_get('taxonomy_user_vocab_'.$vid, 0)) {
-          
-          if (isset($form['nid']['#value'])) {
-            if ($uterms = taxonomy_user_load(array('nid' => $form['nid']['#value'], 'vid' => $vid))) {
-          
-              $this_users_tags = array();
-              $tags_others = array();
-              $other_users_tags = array();
-              
-              foreach ($uterms as $uterm) {
-                // if a tag is from this user, show it in textarea, if not, hide it in a hidden form field
-                if ($uterm->uid == $user->uid) {
-                  $this_users_tags[] = $uterm->name;
-                }
-                else {
-                  $other_users_tags[$uterm->tid] = $uterm->name;
-                  $tags_others[] = array( 'uid' => $uterm->uid, 
-                                          'tid' => $uterm->tid, 
-                                          'name' => $uterm->name);
-                }
-              }
-              
-              $form['taxonomy']['tags_others'][$vid] = array( '#type' => 'value',
-                                                              '#value' => $tags_others,
-                                                              );
-              
-              $form['taxonomy']['tags'][$vid]['#default_value'] = implode(", ", $this_users_tags);
-              
-              if (count($other_users_tags) > 0) {
-                $form['taxonomy']['tags'][$vid]['#description'] .= '<div class="tags others">'.t('Other people tagged').': '.implode(', ', $other_users_tags).'</div>';
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-}
-
-/**
- * Implementation of hook_nodeapi().
- */
-function taxonomy_user_nodeapi(&$node, $op, $arg = 0) {
-  
-  switch ($op) {
-    case 'load':
-      taxonomy_user_node_load($node);
-      break;
-    case 'submit':
-      taxonomy_user_node_submit($node);
-      break;
-    case 'insert':
-    case 'update':
-      taxonomy_user_node_save($node);
-      break;
-    case 'delete':
-      taxonomy_user_node_delete($node->nid);
-      break;
-    case 'view':
-      taxonomy_user_node_view($node);
-      break;
-  }
-}
-
-/**
- * implementation of hook_block
- */
-function taxonomy_user_block($op = 'list', $delta = O, $edit = array()) {
-  
-  if ($op == 'view') {
-    switch($delta)
-    {
-      case 0:
-        if (module_exist('tagadelic')) {
-          $blocks['subject'] = t('My tags');
-          $blocks['content'] = taxonomy_user_my_tag_cloud();
-        }
-        break;
-    } 
-  }
-  elseif ($op == 'list') {
-    $blocks[0]['info'] = t('taxonomy_user user tag cloud - requires tagadelic module');
-  }
-  return $blocks;
-}
-
-/**
- * loads a tid/nid/uid triple
- * $args can contain one or several of the following values
- * Array(
- *    'tid' => int(11),
- *    'nid' => int(11),
- *    'uid' => int(11),
- *    )
- */
-function taxonomy_user_load($args = array()) {
-  
-  if (count($args) < 1) {
-    return FALSE;
-  }
-  if (isset($args['tid'])) {
-    $where[] = 'tnu.tid = %d';
-    $whereargs[] = $args['tid'];
-  }
-  if (isset($args['nid'])) {
-    $where[] = 'tnu.nid = %d';
-    $whereargs[] = $args['nid'];
-  }
-  if (isset($args['uid']) && ($args['uid'] != 0)) {
-    $where[] = 'tnu.uid = %d';
-    $whereargs[] = $args['uid'];
-  }
-  if (isset($args['vid'])) {
-    $where[] = 'td.vid = %d';
-    $whereargs[] = $args['vid'];
-  }
-  $result = db_query('SELECT tnu.tid, td.vid, tnu.uid, tnu.nid,  
-                             td.name, td.description, td.weight
-                      FROM {term_node_user} tnu 
-                      JOIN {term_data} td ON td.tid = tnu.tid 
-                      WHERE '.implode(' AND ', $where).' ORDER BY td.vid ASC, td.name ASC', $whereargs );
-  while ($tnu = db_fetch_object($result)) {
-    $return[] = $tnu;
-  }
-  return $return;
-}
-
-/**
- * save node's user terms
- */
-function taxonomy_user_node_save(&$node) {
-  taxonomy_user_node_delete($node->nid);
-  
-  foreach($node->taxonomy_user as $uterm) {
-    if (!$inserted[$uterm->tid][$uterm->uid]) {
-      $inserted[$uterm->tid][$uterm->uid] = TRUE;          
-      db_query('INSERT INTO {term_node_user} (nid, tid, uid) VALUES (%d, %d, %d)', $node->nid, $uterm->tid, $uterm->uid);
-    }
-  }        
-}
-
-/**
- * intercept node here before it goes to taxonomy.module
- */
-function taxonomy_user_node_submit(&$node) {
-  
-  global $user;
-  
-  if (isset($node->taxonomy['tags'])) {
-    foreach ($node->taxonomy['tags'] as $vid => $vid_value) {
-      if (variable_get('taxonomy_user_vocab_'.$vid, 0)) {
-        
-        // the following is taken from taxonomy.module - duplication - not the ideal solution, alas.
-        
-        // This regexp allows the following types of user input:
-        // this, "somecmpany, llc", "and ""this"" w,o.rks", foo bar
-        $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
-        preg_match_all($regexp, $vid_value, $matches);
-        $typed_terms = array_unique($matches[1]);
-        
-        $inserted = array();
-        foreach ($typed_terms as $typed_term) {
-          // If a user has escaped a term (to demonstrate that it is a group,
-          // or includes a comma or quote character), we remove the escape
-          // formatting so to save the term into the DB as the user intends.
-          $typed_term = str_replace('""', '"', preg_replace('/^"(.*)"$/', '\1', $typed_term));
-          $typed_term = trim($typed_term);
-          if ($typed_term == "") { continue; }
-  
-          // See if the term exists in the chosen vocabulary
-          // and return the tid, otherwise, add a new record.
-          $possibilities = taxonomy_get_term_by_name($typed_term);
-          $typed_term_tid = NULL; // tid match if any.
-          foreach ($possibilities as $possibility) {
-            if ($possibility->vid == $vid) {
-              $typed_term_tid = $possibility->tid;
-            }
-          }
-  
-          if (!$typed_term_tid) {
-            $edit = array('vid' => $vid, 'name' => $typed_term);
-            $status = taxonomy_save_term($edit);
-            $typed_term_tid = $edit['tid'];
-          }
-          
-          // stick stub of term on node for saving in taxonomy_user_save_node()
-          $new_term = new stdClass();
-          $new_term->tid = $typed_term_tid;
-          $new_term->uid = $user->uid;
-          $node->taxonomy_user[] = $new_term;
-        }
-        // now pluck off other people's tags and stick it onto the node->taxonomy_user variable as well
-        if (is_array($node->taxonomy['tags_others'][$vid])) {
-          foreach($node->taxonomy['tags_others'][$vid] as $term) {
-            $new_term = new stdClass();
-            $new_term->tid = $term['tid'];
-            $new_term->uid = $term['uid'];
-            $node->taxonomy_user[] = $new_term;
-            // merge with original 'tags' array, so that taxonomy.module saves those tags as well
-            $node->taxonomy['tags'][$vid] .= ",".$term['name'];
-          }
-        }
-        // this would hide user terms from taxonomy module - buggy
-        // unset($node->taxonomy['tags'][$vid]);
-      }
-    }
-  }
-  // unset our temp variable here, otherwise taxonomy.module takes it as yet another term category
-  unset($node->taxonomy['tags_others']);
-}
-
-/**
- * delete all term/user associations for a given node
- */
-function taxonomy_user_node_delete($nid) {
-  
-  db_query('DELETE FROM {term_node_user} WHERE nid = %d', $nid);
-}
-
-/**
- * Renders user taxonomy for a given node
- */
-function taxonomy_user_node_view(&$node) {
- 
-  if (!is_array($node->taxonomy_user)) {
-    return;
-  }
-  
-  // TU_SHOW_LINKS_INLINE options needs to get a settings page implemented....
-  $tagpos = variable_get('taxonomy_user_tag_pos', TU_POS_BOTTOM);
-  if (($tagpos == TU_POS_TOP) || ($tagpos == TU_POS_BOTTOM)) {
-    // take out those terms from taxonomy link list, that are already 
-    // in taxonomy user
-    if (is_array($node->taxonomy)) {
-      foreach($node->taxonomy_user as $term) {
-        if (array_key_exists($term->tid, $node->taxonomy)) {
-          unset($node->taxonomy[$term->tid]);
-        }
-      }
-    }
-    $themed_links = theme('taxonomy_user_inline_link', $node);
-    if (isset($node->teaser)) {
-      if ($tagpos == TU_POS_TOP) {
-        $node->teaser = $themed_links.$node->teaser;
-      }
-      else {
-        $node->teaser = $node->teaser.$themed_links;
-      }
-    }
-    if (isset($node->body)) {
-      if ($tagpos == TU_POS_TOP) {
-        $node->body = $themed_links.$node->body;
-      }
-      else {
-        $node->body = $node->body.$themed_links;
-      }
-    }
-  }
-}
-
-/**
- * Load user taxonomy for a given node
- */
-function taxonomy_user_node_load(&$node) {
-  
-  $node->taxonomy_user = array();
-  if ($uterms = taxonomy_user_load(array('nid' => $node->nid))) {
-    global $user;
-    foreach ($uterms as $uterm) {
-      // do not user $uterm->tid as key, two users could have the tagged with the same $uterm->tid!
-      $node->taxonomy_user[] = $uterm;
-    }
-  }
-}
-
-/**
- * callback function for taxonomy_term_path()
- */
-function taxonomy_user_term_path($term) {
-  global $user;
-  if ($term->uid == $user->uid) {
-    return 'taxonomy_user/term/'.$term->tid;
-  }
-  return 'taxonomy/term/'.$term->tid;
-}
-
-/**
- * theme function for links
- */
-function theme_taxonomy_user_inline_link($node) {
-  global $user;
-  if (count($node->taxonomy_user) != 0) {
-    $myterms = array();
-    $otherterms = array();
-    foreach ($node->taxonomy_user as $uterm) {
-      if ($uterm->uid == $user->uid) {
-        $myterms[] = l($uterm->name, taxonomy_term_path($uterm), array('rel' => 'tag', 'title' => strip_tags($uterm->description), 'class' => 'myterm'));
-      } 
-      else {
-        $otherterms[$uterm->tid] = l($uterm->name, taxonomy_term_path($uterm), array('rel' => 'tag', 'title' => strip_tags($uterm->description), 'class' => 'otherterm'));
-      }
-    }
-  }
-  if (count($myterms)) {
-    $output = '<div class="links myterms">';
-    $output .= '<div class="title">'.t('My tags:').'</div>';
-    $output .= implode(' | ', $myterms);
-    $output .= '</div>';  
-  }
-  if (count($otherterms)) {
-    $output .= '<div class="links otherterms">';
-    if ($user->uid != 0) {
-      $output .= '<div class="title">'.t('Other people tagged').':</div>';
-    }
-    else {
-      $output .= '<div class="title">'.t('Tags').':</div>';
-    }
-    $output .= implode(' | ', $otherterms);
-    $output .= '</div>';  
-  }
-  
-  return $output;
-}
-
-/**
- * builds a tag cloud of tags of current user
- */
-function taxonomy_user_my_tag_cloud() {
-  
-  global $user;
-  if ($user->uid == 0) {
-    return;
-  }
-    
-  $result = db_query("SELECT COUNT( * ) AS count, td.tid, td.name, td.vid, tnu.uid
-                      FROM {term_data} td 
-                      INNER JOIN {term_node_user} tnu ON tnu.tid = td.tid
-                      INNER JOIN {node} n ON n.nid = tnu.nid
-                      WHERE tnu.uid = %d
-                      GROUP BY td.tid, td.vid
-                      ORDER BY count DESC", $user->uid);
-  
-  $tags = tagadelic_build_weighted_tags($result);
-  return theme('tagadelic_weighted',tagadelic_sort_tags($tags));
-}
-
-/**
- * menu callback - shows a list of nodes tagged by the current user
- */
-function taxonomy_user_page() {
-  
-  $tid = func_get_arg(0);
-  if (!is_numeric($tid)) {
-    return $tid;
-    return drupal_not_found();
-  }
-  
-  global $user;
-  
-  if ($term = taxonomy_get_term($tid)) { 
-    $query = db_rewrite_sql( 'SELECT n.nid
-                              FROM {node} n 
-                              JOIN {term_node_user} tnu ON tnu.nid = n.nid
-                              WHERE n.status = 1 
-                              AND tnu.uid = %d
-                              AND tnu.tid = %d
-                              ORDER BY n.sticky DESC, n.created DESC', 
-                              'n', 'nid'                           
-                              );
-    $result = pager_query( $query, variable_get('default_nodes_main', 10), 0, NULL, $user->uid, $tid);
-    if (db_num_rows($result) > 0) {
-      while ($node = db_fetch_object($result)) {
-        $output .= node_view(node_load(array('nid' => $node->nid)), true);
-      }
-    }
-    else {
-      $output .= t('There are currently no posts in this category.');
-    }
-    if ($user->uid != 0) {
-      drupal_set_title(t('Content you tagged %termname', array('%termname' => $term->name)));
-    }
-    else {
-      drupal_set_title(t('Content tagged %termname', array('%termname' => $term->name)));
-    }
-  }
-  else {
-    $output .= t('Given category does not exist.');
-    drupal_set_title(t('No such category'));
-  }
-  return $output;
-}
-
-/**
- * implementation of hook_menu()
- */
-function taxonomy_user_menu($may_cache) {
-  $items = array();
-
-  if ($may_cache) {
-    $items[] = array('path' => 'taxonomy_user/term', 
-                     'title' => t('Taxonomy user'),
-                     'callback' => 'taxonomy_user_page',
-                     'access' => user_access('access content'),
-                     'type' => MENU_CALLBACK,
-                     );
-  }
-  return $items;  
+<?php
+/**
+ * taxonomy_user - stores which users tagged what with a shared free tagging vocabulary
+ */
+define('TU_POS_LINKS', 0);
+define('TU_POS_TOP', 2);
+define('TU_POS_BOTTOM', 4);
+
+/**
+ * implementation of hook_help()
+ */
+function taxonomy_user_help($section) {
+  
+  switch ($section) {
+  // the 'module' section is depricated in 5.0; moved content to .info file
+  }
+}
+
+/**
+ * implementation of hook_menu()
+ */
+function taxonomy_user_menu($may_cache) {
+  $items = array();
+
+  if ($may_cache) {
+    $items[] = array('path' => 'taxonomy_user/term', 
+                     'title' => t('Taxonomy user'),
+                     'callback' => 'taxonomy_user_page',
+                     'access' => user_access('access content'),
+                     'type' => MENU_CALLBACK,
+                     );
+    $items[] = array('path' => 'taxonomy_user/tag', 
+                     'title' => t('Taxonomy User Tag'),
+                     'callback' => 'taxonomy_user_tag',
+                     'access' => user_access('access content'),
+                     'type' => MENU_CALLBACK,
+                     );
+    $items[] = array('path' => 'admin/settings/taxonomy_user', 
+                     'title' => t('Taxonomy user settings'),
+                     'callback'  => 'drupal_get_form',
+                     'callback arguments'  => array('taxonomy_user_settings'),
+                     'access' => user_access('administer taxonomy'),
+                     'type' => MENU_NORMAL_ITEM,
+                     );
+  }
+  return $items;  
+}
+
+// Menu callback for tagging other people's stuff
+// Works either by ajax, or else (to be added) by loading a new page to tag
+function taxonomy_user_tag($vid, $submit = FALSE) {
+  if ($_POST['op'] == 'ajax') {
+    // TODO, figure out how to get the vid in there
+    print drupal_get_form('taxonomy_user_ajax_form', $vid);
+  }
+  elseif ($_POST['op'] == 'submit') {
+    // call utility storage function
+    $terms = taxonomy_user_store_tag($_POST['nid'], $vid, $_POST['typed_string']);
+    // return the full taxonomy string for ajaxian update
+    print $terms;
+  }
+  else {
+    // this doesn't work yet; needs to be full 'no ajax' fallback.
+    return drupal_get_form('taxonomy_user_ajax_form', $vid, $_POST['nid']);
+  }
+}
+
+/**
+* Form function to send the form through via ajax
+*/
+function taxonomy_user_ajax_form($vid) {
+  $vocabulary = taxonomy_get_vocabulary($vid);
+  $form['text_input'] = array(
+    '#type' => 'textfield',
+    '#title' => $vocabulary->name,
+    '#attributes' => array('class' => 'taxonomy_user_tag_input'),
+   );
+   $form['text_input']['#suffix'] = l(t('Tag it!'), '', array('class' => 'taxonomy_user_tag'));
+    // for some reason, making a submit button here causes the drupal_get_form 
+    // to return a whole page in the above function; it's weird! 
+//  $form['submit'] = array('#type' => 'submit', '#value' => t('Tag'));
+   return $form;
+}
+
+/**
+* Function to store a submitted usertag form.
+*
+* Basically what we wanna do here is load up the node, munge in the new tags
+* and call the usual hook_save routines. This should keep it clean. The way the
+* module works is to make taxonomy_user_tags an array of the actual tids and
+* uids, which get whipped out on nodeapi op submit with some copied code. Not 
+* ideal...
+*
+* Also, we want to return an updated list of terms so that if the theme is set
+* up right, the AJAX can update the listed tags.
+*/
+
+function taxonomy_user_store_tag($nid, $vid, $typed_string) {
+  global $user;
+  if (strlen(trim($typed_string)) > 0) {
+    $node = node_load($nid);
+    // Set up the tags to go to be stored. We don't need to worry about existing
+    // taxonomy since there's a whole $node->taxonomy already.
+    $node->taxonomy['tags'] = array($vid => $typed_string);
+    // Set up the user_tags as well.
+    $node->taxonomy_user_tags = array($vid => $typed_string);
+    // This also needs to include pre-existing tags from this user since the 
+    // ajax form comes up empty by default.
+    foreach($node->taxonomy_user as $term) {
+      if ($term->uid == $user->uid) {
+        $node->taxonomy_user_tags[$term->vid] .= $node->taxonomy_user_tags[$term->vid] ? ', '.$term->name : $term->name;
+      }
+    }
+    node_save($node);
+  }
+  // Ideally we use taxonomy_node_get_terms here, but it has a static $terms
+  // variable, so instead we're duplicating code. Waaah!
+  //  $node->taxonomy = taxonomy_node_get_terms($node->nid);
+  $result = db_query(db_rewrite_sql('SELECT t.* FROM {term_node} r INNER JOIN {term_data} t ON r.tid = t.tid INNER JOIN {vocabulary} v ON t.vid = v.vid WHERE r.nid = %d ORDER BY v.weight, t.weight, t.name', 't', 'tid'), $node->nid);
+  $node->taxonomy = array();
+  while ($term = db_fetch_object($result)) {
+    $node->taxonomy[$term->tid] = $term;
+  }
+
+  print theme('user_taxonomy_replace', $node);
+}
+
+/**
+ * settings hook
+ */
+function taxonomy_user_settings() {
+  $form['taxonomy_user_tag_pos'] = array(
+    '#type' => 'select',
+    '#title' => t('Position of terms'),
+    '#default_value' => variable_get('taxonomy_user_tag_pos', TU_POS_BOTTOM),
+    '#options' => array(TU_POS_LINKS => 'With all other terms', TU_POS_TOP => 'Text top', TU_POS_BOTTOM => 'Text bottom'),
+    '#description' => t('Select where user taxonomy terms should show up. 
+      Note that if you select "With all other terms", terms of the current user and terms of all 
+      other users will not be set apart.'),
+    );
+  return system_settings_form($form);
+}
+
+/**
+ * Implementation of hook_taxonomy().
+ */
+function taxonomy_user_taxonomy($op, $type, $object = NULL) {
+  
+  switch ($op) {
+    case 'update':
+    case 'insert':
+      switch ($type) {
+        case 'vocabulary':
+        if ($object['tags'] == 1) {
+          variable_set('taxonomy_user_vocab_'.$object['vid'], $object['userterms'][1]);
+          if ($object['userterms'][1]) {
+            db_query('UPDATE {vocabulary} SET module = "taxonomy_user" WHERE vid = %d', $object['vid']);
+          }
+          else {
+            db_query('UPDATE {vocabulary} SET module = "taxonomy" WHERE vid = %d', $object['vid']);
+          }
+        }
+        else {
+          variable_set('taxonomy_user_vocab_'.$object['vid'], 0);
+          db_query('UPDATE {vocabulary} SET module = "taxonomy" WHERE vid = %d', $object['vid']);
+        }
+        break;
+      }
+      break;
+    case 'delete':
+      switch ($type) {
+        case 'vocabulary':
+        variable_del('taxonomy_user_vocab_'.$object['vid']);
+        break;
+      }
+      break;
+  }
+}
+
+/**
+ * implementation of hook_form_alter()
+ */
+function taxonomy_user_form_alter($form_id, &$form) {
+  if ($form_id == 'taxonomy_form_vocabulary') {
+    $form['submit']['#weight'] = 2;
+    $form['delete']['#weight'] = 2;
+    $form['userterms'] = array('#type' => 'checkboxes',
+                '#title' => t('User terms'),
+                '#default_value' => variable_get('taxonomy_user_vocab_'.$form['vid']['#value'], 0),
+                '#options' => array(1 => t('Relate terms and users (Only works if free tagging enabled)')),
+                '#description' => t('Relates terms in the vocabulary to the users that associated them to a node.'),
+                '#weight' => 1,
+              );
+  }
+  else if (strpos($form_id, '_node_form') !== false) {
+    
+    global $user;
+    
+    if (isset($form['taxonomy']['tags'])) {
+      
+      // check each free tagging category, if marked for user taxonomy -
+      // if so, get all according terms from term_node_user and sort out those that are not this user's terms
+      foreach ($form['taxonomy']['tags'] as $vid => $tags) {
+        
+        if (variable_get('taxonomy_user_vocab_'.$vid, 0)) {
+          
+          if (isset($form['nid']['#value'])) {
+            if ($uterms = taxonomy_user_load(array('nid' => $form['nid']['#value'], 'vid' => $vid))) {
+          
+              $this_users_tags = array();
+              $tags_others = array();
+              $other_users_tags = array();
+              
+              foreach ($uterms as $uterm) {
+                // if a tag is from this user, show it in textarea, if not, hide it in a hidden form field
+                if ($uterm->uid == $user->uid) {
+                  $this_users_tags[] = $uterm->name;
+                }
+                else {
+                  $other_users_tags[$uterm->tid] = $uterm->name;
+                  $tags_others[] = array( 'uid' => $uterm->uid, 
+                                          'tid' => $uterm->tid, 
+                                          'name' => $uterm->name);
+                }
+              }
+              // take this out of $form['taxonomy'] space to prevent any screwups
+              $form['taxonomy_user_tags_others']['#tree'] = TRUE;
+              $form['taxonomy_user_tags_others'][$vid] = array( '#type' => 'value',
+                                                              '#value' => $tags_others,
+                                                              );
+              // put in only this users tags, so it looks right
+              $form['taxonomy']['tags'][$vid]['#default_value'] = implode(", ", $this_users_tags);
+              
+              if (count($other_users_tags) > 0) {
+                $form['taxonomy']['tags'][$vid]['#description'] .= '<div class="tags others">'.t('Other people tagged').': '.implode(', ', $other_users_tags).'</div>';
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Implementation of hook_nodeapi().
+ */
+function taxonomy_user_nodeapi(&$node, $op, $arg = 0) {
+  
+  switch ($op) {
+    case 'load':
+      taxonomy_user_node_load($node);
+      break;
+    case 'submit':
+      taxonomy_user_node_submit($node);
+      break;
+    case 'insert':
+    case 'update':
+      taxonomy_user_node_save($node);
+      break;
+    case 'delete':
+      taxonomy_user_node_delete($node->nid);
+      break;
+    case 'view':
+      taxonomy_user_node_view($node);
+      break;
+  }
+}
+
+/**
+ * implementation of hook_block
+ */
+function taxonomy_user_block($op = 'list', $delta = O, $edit = array()) {
+  
+  if ($op == 'view') {
+    switch($delta)
+    {
+      case 0:
+        if (module_exist('tagadelic')) {
+          $blocks['subject'] = t('My tags');
+          $blocks['content'] = taxonomy_user_my_tag_cloud();
+        }
+        break;
+    } 
+  }
+  elseif ($op == 'list') {
+    $blocks[0]['info'] = t('taxonomy_user user tag cloud - requires tagadelic module');
+  }
+  return $blocks;
+}
+
+/**
+ * loads a tid/nid/uid triple
+ * $args can contain one or several of the following values
+ * Array(
+ *    'tid' => int(11),
+ *    'nid' => int(11),
+ *    'uid' => int(11),
+ *    )
+ */
+function taxonomy_user_load($args = array()) {
+  
+  if (count($args) < 1) {
+    return FALSE;
+  }
+  if (isset($args['tid'])) {
+    $where[] = 'tnu.tid = %d';
+    $whereargs[] = $args['tid'];
+  }
+  if (isset($args['nid'])) {
+    $where[] = 'tnu.nid = %d';
+    $whereargs[] = $args['nid'];
+  }
+  if (isset($args['uid']) && ($args['uid'] != 0)) {
+    $where[] = 'tnu.uid = %d';
+    $whereargs[] = $args['uid'];
+  }
+  if (isset($args['vid'])) {
+    $where[] = 'td.vid = %d';
+    $whereargs[] = $args['vid'];
+  }
+  $result = db_query('SELECT tnu.tid, td.vid, tnu.uid, tnu.nid,  
+                             td.name, td.description, td.weight
+                      FROM {term_node_user} tnu 
+                      JOIN {term_data} td ON td.tid = tnu.tid 
+                      WHERE '.implode(' AND ', $where).' ORDER BY td.vid ASC, td.name ASC', $whereargs );
+  while ($tnu = db_fetch_object($result)) {
+    $return[] = $tnu;
+  }
+  return $return;
+}
+
+/**
+ * save node's user terms
+ */
+function taxonomy_user_node_save(&$node) {
+  // get the terms from processed taxonomy
+  global $user;
+  foreach($node->taxonomy_user_tags as $vid => $tags) {
+    if (variable_get('taxonomy_user_vocab_'. $vid, 0) == 1) { 
+      // the tags are usertaggable; let's get the actual tids
+      $terms = taxonomy_node_get_terms_by_vocabulary($node->nid, $vid, 'name');
+      // we can't assume these all belong to the user, so we need to winnow
+      // so we parse the typed_string ala taxonomy_node_save
+      $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x';
+      preg_match_all($regexp, $tags, $matches);
+      $user_tags = array_unique($matches[1]);
+      foreach ($terms as $tag => $term) {
+        if (in_array($tag, $user_tags)) {
+          // these are worth saving as this user's
+          $user_terms[] = array('tid' => $term->tid, 'uid' => $user->uid);
+        }
+      } 
+    }
+  }
+  
+  // We only clear the current user's tags, since that's all we're changing.
+  taxonomy_user_node_delete($node->nid, $user->uid);
+  // save the user's terms
+  foreach($user_terms as $term) {
+    if (!isset($inserted[$term['tid']])) { 
+      db_query('INSERT INTO {term_node_user} (nid, tid, uid) VALUES (%d, %d, %d)', $node->nid, $term['tid'], $term['uid']);
+      $inserted[$term['tid']] = TRUE;
+    }
+  }
+} 
+
+
+/**
+ * intercept node here before it goes to taxonomy.module
+ *
+ * This is where the duplicate code was. I get around this by calling 
+ * taxonomy_get_terms in the save function.
+ * 
+ * What would be nice would be if taxonomy.module would put it's business
+ * in the $node object as it's passed along. Alas, it does not, so we have
+ * a choice between running through the tags twice, or hitting the database
+ * to find out the results of taxonomy_node_save.
+ *
+ * I'm implementing the latter, meaning no 'submit' processing of user terms.
+ *
+ * Instead we just do a little switcharoo on the form arrays
+ */
+function taxonomy_user_node_submit(&$node) {
+//  Here we take the input value of any freetagging fields to preserve the
+//  original user input for use in our taxonomy_user_node_save function.
+  $node->taxonomy_user_tags = $node->taxonomy['tags'];
+  
+//  Now we append the "hidden" tags (those by other users) to the 
+//  $node->taxonomy['tags'] elements, so that taxonomy_node_save will save 
+//  them all into term_node.
+  if ($node->taxonomy_user_tags_others) {
+    foreach($node->taxonomy_user_tags_others as $vid => $terms) {
+      foreach($terms as $term) {
+        $node->taxonomy['tags'][$vid] .= $node->taxonomy['tags'][$vid] ? ', '.$term['name'] : $term['name'];
+      }
+    }
+  }
+}
+
+/**
+ * delete all term/user associations for a given node
+ */
+function taxonomy_user_node_delete($nid, $uid = NULL) {
+  if ($uid) {
+    db_query('DELETE FROM {term_node_user} WHERE nid = %d AND uid = %d', $nid, $uid);
+  }
+  else {
+    db_query('DELETE FROM {term_node_user} WHERE nid = %d', $nid);
+  }
+}
+
+/**
+ * Renders user taxonomy for a given node
+ */
+function taxonomy_user_node_view(&$node) {
+  drupal_add_js(drupal_get_path('module', 'taxonomy_user').'/taxonomy_user.js');
+  if (!is_array($node->taxonomy_user)) {
+    return;
+  }
+  
+  // this needs to change to the new $node->content style
+  
+  // TU_SHOW_LINKS_INLINE options needs to get a settings page implemented....
+  $tagpos = variable_get('taxonomy_user_tag_pos', TU_POS_BOTTOM);
+  if (($tagpos == TU_POS_TOP) || ($tagpos == TU_POS_BOTTOM)) {
+    // take out those terms from taxonomy link list, that are already 
+    // in taxonomy user
+    if (is_array($node->taxonomy)) {
+      foreach($node->taxonomy_user as $term) {
+        if (array_key_exists($term->tid, $node->taxonomy)) {
+          unset($node->taxonomy[$term->tid]);
+        }
+      }
+    }
+    $themed_links = theme('taxonomy_user_inline_link', $node);
+    if (isset($node->teaser)) {
+      if ($tagpos == TU_POS_TOP) {
+        $node->teaser = $themed_links.$node->teaser;
+      }
+      else {
+        $node->teaser = $node->teaser.$themed_links;
+      }
+    }
+    if (isset($node->body)) {
+      if ($tagpos == TU_POS_TOP) {
+        $node->body = $themed_links.$node->body;
+      }
+      else {
+        $node->body = $node->body.$themed_links;
+      }
+    }
+  }
+  $result = db_query("SELECT v.vid, v.name FROM {vocabulary_node_types} vt INNER JOIN {vocabulary} v on vt.vid = v.vid WHERE vt.type = '%s'", $node->type);
+  while ($vocab = db_fetch_object($result)) {
+    if (variable_get('taxonomy_user_vocab_'.$vocab->vid, FALSE)) {
+      $node->content['user_taxonomy_add_terms'][] = array(
+        '#value' =>  '<div id="taxonomyuser_'. $node->nid. '">'. l('Add '. $vocab->name, 'taxonomy_user/tag/'. $vocab->vid, array('class' => 'taxonomy_user_addlink', 'id' => 'TU_LINK'. $node->nid)) . '</div>',
+        '#weight' => 11,
+      );
+    }
+  }
+  return $node;
+}
+
+/**
+ * Load user taxonomy for a given node
+ */
+function taxonomy_user_node_load(&$node) {
+  
+  $node->taxonomy_user = array();
+  if ($uterms = taxonomy_user_load(array('nid' => $node->nid))) {
+    global $user;
+    foreach ($uterms as $uterm) {
+      // do not user $uterm->tid as key, two users could have the tagged with the same $uterm->tid!
+      $node->taxonomy_user[] = $uterm;
+    }
+  }
+}
+
+/**
+ * callback function for taxonomy_term_path()
+ */
+function taxonomy_user_term_path($term) {
+  global $user;
+  if ($term->uid == $user->uid) {
+    return 'taxonomy_user/term/'.$term->tid;
+  }
+  return 'taxonomy/term/'.$term->tid;
+}
+
+/**
+ * theme function for links
+ */
+function theme_taxonomy_user_inline_link($node) {
+  global $user;
+  if (count($node->taxonomy_user) != 0) {
+    $myterms = array();
+    $otherterms = array();
+    foreach ($node->taxonomy_user as $uterm) {
+      if ($uterm->uid == $user->uid) {
+        $myterms[] = l($uterm->name, taxonomy_term_path($uterm), array('rel' => 'tag', 'title' => strip_tags($uterm->description), 'class' => 'myterm'));
+      } 
+      else {
+        $otherterms[$uterm->tid] = l($uterm->name, taxonomy_term_path($uterm), array('rel' => 'tag', 'title' => strip_tags($uterm->description), 'class' => 'otherterm'));
+      }
+    }
+  }
+  if (count($myterms)) {
+    $output = '<div class="links myterms">';
+    $output .= '<div class="title">'.t('My tags:').'</div>';
+    $output .= implode(' | ', $myterms);
+    $output .= '</div>';  
+  }
+  if (count($otherterms)) {
+    $output .= '<div class="links otherterms">';
+    if ($user->uid != 0) {
+      $output .= '<div class="title">'.t('Other people tagged').':</div>';
+    }
+    else {
+      $output .= '<div class="title">'.t('Tags').':</div>';
+    }
+    $output .= implode(' | ', $otherterms);
+    $output .= '</div>';  
+  }
+  
+  return $output;
+}
+
+/**
+ * builds a tag cloud of tags of current user
+ */
+function taxonomy_user_my_tag_cloud() {
+  
+  global $user;
+  if ($user->uid == 0) {
+    return;
+  }
+    
+  $result = db_query("SELECT COUNT( * ) AS count, td.tid, td.name, td.vid, tnu.uid
+                      FROM {term_data} td 
+                      INNER JOIN {term_node_user} tnu ON tnu.tid = td.tid
+                      INNER JOIN {node} n ON n.nid = tnu.nid
+                      WHERE tnu.uid = %d
+                      GROUP BY td.tid, td.vid
+                      ORDER BY count DESC", $user->uid);
+  
+  $tags = tagadelic_build_weighted_tags($result);
+  return theme('tagadelic_weighted',tagadelic_sort_tags($tags));
+}
+
+/**
+ * menu callback - shows a list of nodes tagged by the current user
+ */
+function taxonomy_user_page() {
+  
+  $tid = func_get_arg(0);
+  if (!is_numeric($tid)) {
+    return $tid;
+    return drupal_not_found();
+  }
+  
+  global $user;
+  
+  if ($term = taxonomy_get_term($tid)) { 
+    $query = db_rewrite_sql( 'SELECT n.nid
+                              FROM {node} n 
+                              JOIN {term_node_user} tnu ON tnu.nid = n.nid
+                              WHERE n.status = 1 
+                              AND tnu.uid = %d
+                              AND tnu.tid = %d
+                              ORDER BY n.sticky DESC, n.created DESC', 
+                              'n', 'nid'                           
+                              );
+    $result = pager_query( $query, variable_get('default_nodes_main', 10), 0, NULL, $user->uid, $tid);
+    if (db_num_rows($result) > 0) {
+      while ($node = db_fetch_object($result)) {
+        $output .= node_view(node_load(array('nid' => $node->nid)), true);
+      }
+    }
+    else {
+      $output .= t('There are currently no posts in this category.');
+    }
+    if ($user->uid != 0) {
+      drupal_set_title(t('Content you tagged %termname', array('%termname' => $term->name)));
+    }
+    else {
+      drupal_set_title(t('Content tagged %termname', array('%termname' => $term->name)));
+    }
+  }
+  else {
+    $output .= t('Given category does not exist.');
+    drupal_set_title(t('No such category'));
+  }
+  return $output;
+}
+
+/**
+* Theme function to upate the taxonomy links with ajaxian submit.
+*
+* For this to work, the span or div containing the taxonomy links needs to have
+* the id #taxonomy_$nid.
+*
+* This is easy to add in your node.tpl.php.
+*/
+
+function theme_user_taxonomy_replace($node) {
+  $taxonomy = taxonomy_link('taxonomy terms', $node);
+  return theme('links', $taxonomy, array('class' => 'links inline'));
 }
\ No newline at end of file
