Index: category.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/category/category.inc,v
retrieving revision 1.64.2.1
diff -u -r1.64.2.1 category.inc
--- category.inc	2 Feb 2007 08:24:56 -0000	1.64.2.1
+++ category.inc	21 Aug 2007 19:40:23 -0000
@@ -577,18 +577,6 @@
 }
 
 /**
- * Implementation of hook_node_type().
- */
-function category_node_type($op, $info) {
-  if ($op == 'update' && !empty($info->old_type) && $info->type != $info->old_type) {
-    db_query("UPDATE {category_cont_node_types} SET type = '%s' WHERE type = '%s'", $info->type, $info->old_type);
-  }
-  elseif ($op == 'delete') {
-    db_query("DELETE FROM {category_cont_node_types} WHERE type = '%s'", $info->type);
-  }
-}
-
-/**
  * Find all category objects related to a given category ID.
  */
 function category_get_related($cid, $key = 'cid') {
@@ -703,6 +691,7 @@
 function category_node_save(&$node, $is_legacy = FALSE) {
   global $user;
   static $legacy_calls = array();
+  global $category_last_update_nid;
 
   if (!$is_legacy || !isset($legacy_calls[$node->nid])) {
     $cats_flat = array();
@@ -739,21 +728,23 @@
           }
 
           if (!$typed_cat_cid) {
-            $tag_node = new stdClass();
-            $tag_node->title = $typed_cat;
-            $tag_node->cnid = $cnid;
-            $tag_node->type = 'category_cat';
-            $tag_node->parents[0] = $tag_node->parent = $cnid;
-            $node_options = variable_get('node_options_'. $tag_node->type, array('status', 'promote'));
-            $tag_node->status = in_array('status', $node_options);
-            $tag_node->promote = in_array('promote', $node_options);
-            $tag_node->sticky = in_array('sticky', $node_options);
-            $tag_node->revision = in_array('revision', $node_options);
-            $tag_node->name = $user->name ? $user->name : 0;
-            $tag_node->date = date('j M Y H:i:s');
-            $tag_node = node_submit($tag_node);
-            node_save($tag_node);
-            $typed_cat_cid = $tag_node->nid;
+            // There wasn't a match, we need to autocreate a category.
+            $container = node_load($cnid);
+            $tempnode = array(
+              'uid' => $user->uid,
+              'name' => $user->name,
+              'type' => $container->freetag_node_type,
+            );
+            $values['title'] = $typed_cat;
+            $values['cnid'] = $cnid;
+            $values['parent'] = $cnid;
+            $values['parents'] = array($values['parent']);
+            drupal_execute($tempnode['type'].'_node_form', $values, $tempnode);
+            // Assertion: If freetag_callback_nid is not a valid nid,
+            // something went horribly wrong when autocreating the child
+            assert(is_numeric($category_last_update_nid) && $category_last_update_nid != 0);
+            $typed_cat_cid = $category_last_update_nid;
+            $freetag_callback_nid = 0;
           }
 
           if (!isset($cats_flat[$typed_cat_cid])) {
@@ -1245,6 +1236,14 @@
       '#description' => t('Sets this container\'s \'hidden\' attribute. This attribute is not used by the core category module, but can affect how this container is treated by other modules. For example, hidden containers do not have menu items generated by category_menu, and are not shown in navigational elements by category_display. This hidden behaviour applies only to the container itself, not to its child categories or to their assigned nodes.'),
       '#required' => TRUE,
     );
+    $form['catinfo']['freetag_node_type'] = array(
+      '#type' => 'select',
+      '#title' => t('Freetagging content type'),
+      '#default_value' => isset($node->freetag_node_type) ? $node->freetag_node_type : 'category_cat',
+      '#options' => _category_node_type_options(),
+      '#description' => t('Choose the content type to use when creating new freetagging categories.'),
+      '#required' => TRUE,
+    );
   }
 
   $blank = '<'. t('root') .'>';
@@ -1383,6 +1382,20 @@
 }
 
 /**
+ * Get a list of node types with category behavior.
+ */
+function _category_node_type_options() {
+  $types = node_get_types();
+  $options = array();
+  foreach ($types as $k => $v) {
+    if ($k == 'category_cat' || $k == 'category_cont' || variable_get('category_nodeapi_'. $k, 'none') != 'none') {
+      $options[$k] = $v->name;
+    }
+  }
+  return $options;
+}
+
+/**
  * Determines whether or not the specified wrapper is enabled and has database
  * maintenance turned on.
  *
Index: category.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/category/category.install,v
retrieving revision 1.11.2.2
diff -u -r1.11.2.2 category.install
--- category.install	8 Jul 2007 23:20:33 -0000	1.11.2.2
+++ category.install	20 Aug 2007 20:27:25 -0000
@@ -66,6 +66,7 @@
         multiple tinyint(3) unsigned NOT NULL default '0',
         required tinyint(3) unsigned NOT NULL default '0',
         tags tinyint(3) unsigned NOT NULL default '0',
+        freetag_node_type varchar(32) NOT NULL default 'category_cat',
         hidden_cont tinyint(3) unsigned NOT NULL default '0',
         PRIMARY KEY (cid)
         ) /*!40100 DEFAULT CHARACTER SET utf8 */
@@ -133,6 +134,7 @@
         multiple smallint  NOT NULL default '0',
         required smallint  NOT NULL default '0',
         tags smallint  NOT NULL default '0',
+        freetag_node_type varchar(32) NOT NULL default 'category_cat',
         hidden_cont smallint  NOT NULL default '0',
         PRIMARY KEY (cid)
       )");
@@ -268,3 +270,11 @@
 
   return $ret;
 }
+
+/**
+ * Freetagging modernization
+ */
+function category_update_10() {
+  $ret[] = update_sql("ALTER TABLE {category_cont} ADD freetag_node_type varchar(32) NOT NULL default 'category_cat' AFTER tags");
+  return $ret;
+}
\ No newline at end of file
Index: category.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/category/category.module,v
retrieving revision 1.124.2.14
diff -u -r1.124.2.14 category.module
--- category.module	16 Jul 2007 03:30:14 -0000	1.124.2.14
+++ category.module	21 Aug 2007 18:56:06 -0000
@@ -47,6 +47,29 @@
 }
 
 /**
+ * Implementation of hook_node_type().
+ */
+function category_node_type($op, $info) {
+  switch ($op) {
+    case 'delete':
+      // Reset any freetagging containers dependent on this.
+      db_query("UPDATE {category_cont} SET freetag_node_type = '%s' WHERE freetag_node_type = '%s'", 'category_cat', $info->type);
+
+      // Remove container node type mappings.
+      db_query("DELETE FROM {category_cont_node_types} WHERE type = '%s'", $info->type);
+      break;
+    case 'update':
+      // Update freetagging container settings.
+      db_query("UPDATE {category_cont} SET freetag_node_type = '%s' WHERE freetag_node_type = '%s'", $info->type, $info->old_type);
+
+      // Update container node type mappings.
+      db_query("UPDATE {category_cont_node_types} SET type = '%s' WHERE type = '%s'", $info->type, $info->old_type);
+
+      break;
+  }
+}
+
+/**
  * Implementation of hook_perm().
  */
 function category_perm() {
@@ -448,7 +471,8 @@
  * Implementation of hook_update().
  */
 function category_update($node, $type = NULL) {
-  $node->cid = $node->nid;
+  global $category_last_update_nid;
+  $category_last_update_nid = $node->cid = $node->nid;
   $node->module = $node->module ? $node->module : 'category';
 
   $type = category_node_get_type($node, $type);

