diff -urp --strip-trailing-cr ../category/category.module ./category.module
--- ../category/category.module	2009-08-05 06:52:53.000000000 +0200
+++ ./category.module	2009-09-24 00:02:42.000000000 +0200
@@ -1135,42 +1135,30 @@ function category_del_container($cid) {
  * 1. If any category contains multiple parents, the container will be given a
  * hieararchy of 2.
  *
- * @param $container
- *   An array of the container structure.
- * @param $changed_category
- *   An array of the category structure that was updated.
- */
-function category_check_container_hierarchy($container, $changed_category) {
-  $tree = category_get_tree($container['cid']);
-  $hierarchy = 0;
-  foreach ($tree as $category) {
-    // Update the changed category with the new parent value before comparision.
-    if ($category->cid == $changed_category['cid']) {
-      $category = (object)$changed_category;
-    }
-    // Check this term's parent count.
-    if (count($category->parents) > 1) {
-      $hierarchy = 2;
-      break;
-    }
-    elseif (count($category->parents) == 1) {
-      $first_parent = array_shift($category->parents);
-      if (!empty($first_parent)) {
-        if (!category_is_root_parent($first_parent, $container['cid'])) {
-          $hierarchy = 1;
-        }
-      }
-    }
-  }
-  if ($hierarchy != $container['hierarchy']) {
-    $container['hierarchy'] = $hierarchy;
+ * Note: We're not inheriting the core taxonomy code here, because our workflow
+ * is different in that we save category data in hook_nodeapi() rather than in a
+ * form submit handler, so we can't use form values. Also the code is simplified.
+ *
+ * @param $cnid
+ *   The container to be updated.
+ */
+function category_update_container_hierarchy($cnid) {
+  $container = category_get_container($cnid);
+
+  // Retrieve the new value for hierarchy field as the biggest of all parent counts
+  // for categories in this container, reduced to maximum value of 2.
+  $hierarchy = (int) db_result(db_query('SELECT COUNT(h.parent) AS parents FROM {category_hierarchy} h INNER JOIN {category} c ON h.cid = c.cid WHERE c.cnid = %d AND h.parent <> %d GROUP BY h.cid ORDER BY parents DESC', $cnid, $cnid));
+  $hierarchy = $hierarchy < 2 ? $hierarchy : 2;
+
+  // Update the container, if we got a different hierarchy.
+  if ($hierarchy != $container->hierarchy) {
+    $container->hierarchy = $hierarchy;
     $node = new StdClass();
-    $node->nid = $container['cid'];
-    $node->category = $container;
+    $node->nid = $container->cid;
+    $node->category = (array) $container;
     category_save_container($node);
+    // TODO: Allow Taxonomy wrapper to take an action, too.
   }
-
-  return $hierarchy;
 }
 
 /**
@@ -1179,6 +1167,15 @@ function category_check_container_hierar
  */
 function category_save_category(&$node) {
   $new = empty($node->category['cid']);
+
+  // Before we save anything, retrieve the container this category used to
+  // be in previously, if any.
+  $old_cnid = NULL;
+  if (!$new) {
+    $old_category = category_get_category($node->nid);
+    $old_cnid = $old_category->cnid;
+  }
+
   $node->category['cid'] = $node->nid;
 
   if (empty($node->category['cnid'])) {
@@ -1237,6 +1234,12 @@ function category_save_category(&$node) 
     }
   }
 
+  // Update the hierarchy flag on affected container(s).
+  if (!empty($old_cnid) && $node->category['cnid'] != $old_cnid) {
+    category_update_container_hierarchy($old_cnid);
+  }
+  category_update_container_hierarchy($node->category['cnid']);
+
   category_cache_op('flush', 'all');
   return $status;
 }
@@ -1250,12 +1253,16 @@ function category_save_category(&$node) 
  *   Status constant indicating deletion.
  */
 function category_del_category($cid) {
+  $old_category = category_get_category($cid);
+
   db_query('DELETE FROM {category} WHERE cid = %d', $cid);
   db_query('DELETE FROM {category_hierarchy} WHERE cid = %d', $cid);
   db_query('DELETE FROM {category_relation} WHERE cid1 = %d OR cid2 = %d', $cid, $cid);
   db_query('DELETE FROM {category_synonym} WHERE cid = %d', $cid);
   db_query('DELETE FROM {category_node} WHERE cid = %d', $cid);
 
+  category_update_container_hierarchy($old_category->cnid);
+
   category_cache_op('flush', 'all');
   return SAVED_DELETED;
 }
@@ -1625,71 +1632,6 @@ function _category_add_form_elements(&$f
       '#default_value' => implode("\n", category_get_synonyms($node->category['cid'])),
       '#description' => t('Synonyms of this category, one synonym per line.'),
     );
-    $form['#submit'][] = 'category_form_category_submit';
-  }
-}
-
-/**
- * Submit handler to insert or update a category. Updates the
- * hierarchy setting for the container of the category being updated.
- */
-function category_form_category_submit($form, &$form_state) {
-  $container = category_get_container($form['#node']->category['container']);
-  $container->parents = _category_flatten_parents(category_get_parents($container->cid));
-
-  if (!$container->tags) {
-    if (empty($form_state['values']['category']['parents']) || !is_array($form_state['values']['category']['parents'])) {
-      $form_state['values']['category']['parents'] = array();
-    }
-
-    $current_parent_count = count($form_state['values']['category']['parents']);
-    $previous_parent_count = count($form['#node']->category['parents']);
-
-    if ($current_parent_count == 1) {
-      $first_parent = current($form_state['values']['category']['parents']);
-      if (!empty($first_parent)) {
-        if (category_is_root_parent($first_parent, $container->cid)) {
-          $current_parent_count--;
-        }
-      }
-    }
-    if ($previous_parent_count == 1) {
-      $first_parent = current($form['#node']->category['parents']);
-      if (!empty($first_parent)) {
-        if (category_is_root_parent($first_parent, $container->cid)) {
-          $previous_parent_count--;
-        }
-      }
-    }
-
-    // If the number of parents has been reduced to one or none, do a check on the
-    // parents of every category in the container value.
-    $new_container = NULL;
-    if ($current_parent_count < $previous_parent_count && $current_parent_count < 2) {
-      $changed_category = $form_state['values']['category'];
-      category_check_container_hierarchy((array) $container, $changed_category);
-      if ($form['#node']->category['container'] != $form_state['values']['category']['container']) {
-        $new_container = category_get_container($form_state['values']['category']['container']);
-        $new_container->parents = _category_flatten_parents(category_get_parents($new_container->cid));
-        category_check_container_hierarchy((array) $new_container, $changed_category);
-      }
-    }
-    // If we've increased the number of parents and this is a single or flat
-    // hierarchy, update the container immediately.
-    elseif ($current_parent_count > $previous_parent_count && $container->hierarchy < 2) {
-      $container->hierarchy = $current_parent_count == 1 ? 1 : 2;
-      $node = new StdClass();
-      $node->nid = $container->cid;
-      $node->category = (array) $container;
-      category_save_container($node);
-      if (!empty($new_container)) {
-        $new_container->hierarchy = $current_parent_count == 1 ? 1 : 2;
-        $node = new StdClass();
-        $node->nid = $new_container->cid;
-        $node->category = (array) $new_container;
-        category_save_container($node);
-      }
-    }
   }
 }
 
