Index: modules/blog/blog.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/blog/blog.module,v
retrieving revision 1.262
diff -u -r1.262 blog.module
--- modules/blog/blog.module	23 Aug 2006 07:32:18 -0000	1.262
+++ modules/blog/blog.module	25 Aug 2006 13:21:51 -0000
@@ -13,7 +13,6 @@
   return array(
     'blog' => array(
       'name' => t('blog entry'),
-      'module' => 'blog',
       'description' => t('A blog is a regularly updated journal or diary made up of individual posts shown in reversed chronological order. Each member of the site may create and maintain a blog.'),
     )
   );
Index: modules/book/book.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/book/book.module,v
retrieving revision 1.386
diff -u -r1.386 book.module
--- modules/book/book.module	23 Aug 2006 06:38:49 -0000	1.386
+++ modules/book/book.module	25 Aug 2006 13:21:52 -0000
@@ -13,7 +13,6 @@
   return array(
     'book' => array(
       'name' => t('book page'),
-      'module' => 'book',
       'description' => t("A book is a collaborative writing effort: users can collaborate writing the pages of the book, positioning the pages in the right order, and reviewing or modifying pages previously written. So when you have some information to share or when you read a page of the book and you didn't like it, or if you think a certain page could have been written better, you can do something about it."),
     )
   );
Index: modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.353
diff -u -r1.353 forum.module
--- modules/forum/forum.module	25 Aug 2006 08:55:04 -0000	1.353
+++ modules/forum/forum.module	25 Aug 2006 13:21:53 -0000
@@ -116,7 +116,6 @@
   return array(
     'forum' => array(
       'name' => t('forum topic'),
-      'module' => 'forum',
       'description' => t('Create a new topic for discussion in the forums.'),
       'title_label' => t('Subject'),
     )
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.5
diff -u -r1.5 content_types.inc
--- modules/node/content_types.inc	23 Aug 2006 04:40:56 -0000	1.5
+++ modules/node/content_types.inc	25 Aug 2006 13:21:53 -0000
@@ -17,7 +17,7 @@
 
   foreach ($names as $key => $name) {
     $type = $types[$key];
-    if (function_exists($type->module .'_form')) {
+    if (function_exists($type->module . (!empty($type->prefix) ? '_'. $type->prefix : '') .'_form')) {
       $name = check_plain($name);
       $type_url_str = str_replace('_', '-', $type->type);
       // Populate the operations field.
@@ -56,7 +56,7 @@
 function node_type_form($type = NULL) {
   if (!isset($type->type)) {
     $type = new stdClass();
-    $type->type = $type->name = $type->module = $type->description = $type->help = '';
+    $type->type = $type->name = $type->module = $type->prefix = $type->description = $type->help = '';
     $type->min_word_count = 0;
     $type->has_title = TRUE;
     $type->has_body = TRUE;
@@ -174,6 +174,10 @@
     '#type' => 'value',
     '#value' => $type->module,
   );
+  $form['prefix'] = array(
+    '#type' => 'value',
+    '#value' => $type->prefix,
+  );
   $form['custom'] = array(
     '#type' => 'value',
     '#value' => $type->custom,
@@ -263,6 +267,7 @@
   $type->body_label = $form_values['body_label'];
 
   $type->module = !empty($form_values['module']) ? $form_values['module'] : 'node';
+  $type->prefix = !empty($form_values['prefix']) ? $form_values['prefix'] : 'content';
   $type->has_title = $type->has_body = TRUE;
   $type->custom = $form_values['custom'];
   $type->modified = TRUE;
@@ -362,7 +367,7 @@
 /**
  * Menu callback; delete a single content type.
  */
-function node_type_delete($type) {
+function node_type_delete_form($type) {
   $form['type'] = array('#type' => 'value', '#value' => $type->type);
   $form['name'] = array('#type' => 'value', '#value' => $type->name);
 
@@ -383,7 +388,7 @@
  * Process content type delete form submissions.
  */
 function node_type_delete_form_submit($form_id, $form_values) {
-  db_query("DELETE FROM {node_type} WHERE type = '%s'", $form_values['type']);
+  node_type_delete($form_values['type']);
 
   $t_args = array('%name' => $form_values['name']);
   drupal_set_message(t('The content type %name has been deleted.', $t_args));
@@ -394,4 +399,3 @@
 
   return 'admin/content/types';
 }
-
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.686
diff -u -r1.686 node.module
--- modules/node/node.module	25 Aug 2006 09:01:12 -0000	1.686
+++ modules/node/node.module	25 Aug 2006 13:21:56 -0000
@@ -201,8 +201,8 @@
  *
  * @param $op
  *   The format in which to return the list. When this is set to 'type',
- *   'module', or 'name', only the specified node type is returned. When set to
- *   'types' or 'names', all node types are returned.
+ *   'module', 'prefix', or 'name', only the specified node type is returned.
+ *   When set to 'types' or 'names', all node types are returned.
  * @param $node
  *   A node object, array, or string that indicates the node type to return.
  *   Leave at default value (NULL) to return a list of all node types.
@@ -242,6 +242,8 @@
       return $_node_types[$type];
     case 'module':
       return $_node_types[$type]->module;
+    case 'prefix':
+      return $_node_types[$type]->prefix;
     case 'names':
       return $_node_names;
     case 'name':
@@ -282,16 +284,26 @@
   $is_existing = db_num_rows(db_query("SELECT * FROM {node_type} WHERE type = '%s'", $existing_type));
 
   if ($is_existing) {
-    db_query("UPDATE {node_type} SET type = '%s', name = '%s', module = '%s', has_title = %d, title_label = '%s', has_body = %d, body_label = '%s', description = '%s', help = '%s', min_word_count = %d, custom = %d, modified = %d, locked = %d WHERE type = '%s'", $info->type, $info->name, $info->module, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->description, $info->help, $info->min_word_count, $info->custom, $info->modified, $info->locked, $existing_type);
+    db_query("UPDATE {node_type} SET type = '%s', name = '%s', module = '%s', prefix = '%s', has_title = %d, title_label = '%s', has_body = %d, body_label = '%s', description = '%s', help = '%s', min_word_count = %d, custom = %d, modified = %d, locked = %d WHERE type = '%s'", $info->type, $info->name, $info->module, $info->prefix, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->description, $info->help, $info->min_word_count, $info->custom, $info->modified, $info->locked, $existing_type);
     return SAVED_UPDATED;
   }
   else {
-    db_query("INSERT INTO {node_type} (type, name, module, has_title, title_label, has_body, body_label, description, help, min_word_count, custom, modified, locked, orig_type) VALUES ('%s', '%s', '%s', %d, '%s', %d, '%s', '%s', '%s', %d, %d, %d, %d, '%s')", $info->type, $info->name, $info->module, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->description, $info->help, $info->min_word_count, $info->custom, $info->modified, $info->locked, $info->orig_type);
+    db_query("INSERT INTO {node_type} (type, name, module, prefix, has_title, title_label, has_body, body_label, description, help, min_word_count, custom, modified, locked, orig_type) VALUES ('%s', '%s', '%s', '%s', %d, '%s', %d, '%s', '%s', '%s', %d, %d, %d, %d, '%s')", $info->type, $info->name, $info->module, $info->prefix, $info->has_title, $info->title_label, $info->has_body, $info->body_label, $info->description, $info->help, $info->min_word_count, $info->custom, $info->modified, $info->locked, $info->orig_type);
     return SAVED_NEW;
   }
 }
 
 /**
+ * Deletes a node type from the database.
+ *
+ * @param $type
+ *   The machine-readable name of the node type to be deleted.
+ */
+function node_type_delete($type) {
+  db_query("DELETE FROM {node_type} WHERE type = '%s'", $type);
+}
+
+/**
  * Updates all nodes of one type to be of another type.
  *
  * @param $orig_type
@@ -315,8 +327,19 @@
 function _node_types_build() {
   $_node_types = array();
   $_node_names = array();
+  $info_array = array();
+  $hook = 'node_info';
+
+  foreach (module_implements($hook) as $module) {
+    $info = module_invoke($module, $hook);
+    if (isset($info) && is_array($info)) {
+      foreach (array_keys($info) as $type) {
+        $info[$type]['module'] = $module;
+      }
+      $info_array += $info;
+    }
+  }
 
-  $info_array = module_invoke_all('node_info');
   foreach ($info_array as $type => $info) {
     $info['type'] = $type;
     $_node_types[$type] = (object) _node_type_set_defaults($info);
@@ -345,6 +368,10 @@
  * Set default values for a node type defined through hook_node_info().
  */
 function _node_type_set_defaults($info) {
+  if (!isset($info['prefix'])) {
+    $info['prefix'] = '';
+  }
+
   if (!isset($info['has_title'])) {
     $info['has_title'] = TRUE;
   }
@@ -386,10 +413,10 @@
  *   TRUE iff the $hook exists in the node type of $node.
  */
 function node_hook(&$node, $hook) {
-  $module = node_get_types('module', $node);
-  if ($module == 'node') {
-    $module = 'node_content'; // Avoid function name collisions.
-  }
+  $type = node_get_types('type', $node);
+  $module = $type->module;
+  $hook = (!empty($type->prefix) ? $type->prefix .'_' : '') . $hook;
+
   return module_hook($module, $hook);
 }
 
@@ -407,11 +434,10 @@
  */
 function node_invoke(&$node, $hook, $a2 = NULL, $a3 = NULL, $a4 = NULL) {
   if (node_hook($node, $hook)) {
-    $module = node_get_types('module', $node);
-    if ($module == 'node') {
-      $module = 'node_content'; // Avoid function name collisions.
-    }
-    $function = $module .'_'. $hook;
+    $type = node_get_types('type', $node);
+    $module = $type->module;
+
+    $function = $module .'_'. (!empty($type->prefix) ? $type->prefix .'_' : '') . $hook;
     return ($function($node, $a2, $a3, $a4));
   }
 }
@@ -1065,7 +1091,7 @@
       'type' => MENU_CALLBACK);
 
     foreach (node_get_types() as $type) {
-      if (function_exists($type->module .'_form')) {
+      if (function_exists($type->module . (!empty($type->prefix) ? '_'. $type->prefix : '') .'_form')) {
         $name = check_plain($type->name);
         $type_url_str = str_replace('_', '-', $type->type);
         $items[] = array(
@@ -1137,7 +1163,7 @@
             'path' => 'admin/content/types/'. $type_url_str .'/delete',
             'title' => t('delete'),
             'callback' => 'drupal_get_form',
-            'callback arguments' => array('node_type_delete', $type),
+            'callback arguments' => array('node_type_delete_form', $type),
             'type' => MENU_CALLBACK,
           );
         }
@@ -2021,7 +2047,7 @@
   else {
     // If no (valid) node type has been provided, display a node type overview.
     foreach ($types as $type) {
-      if (function_exists($type->module .'_form') && node_access('create', $type->type)) {
+      if (function_exists($type->module . (!empty($type->prefix) ? '_'. $type->prefix : '') .'_form') && node_access('create', $type->type)) {
         $type_url_str = str_replace('_', '-', $type->type);
         $title = t('Add a new @s.', array('@s' => $type->name));
         $out = '<dt>'. l($type->name, "node/add/$type_url_str", array('title' => $title)) .'</dt>';
@@ -2556,11 +2582,10 @@
 
   // Can't use node_invoke(), because the access hook takes the $op parameter
   // before the $node parameter.
-  $module = node_get_types('module', $node);
-  if ($module == 'node') {
-    $module = 'node_content'; // Avoid function name collisions.
-  }
-  $access = module_invoke($module, 'access', $op, $node);
+  $type = node_get_types('type', $node);
+  $base = $type->module . (!empty($type->prefix) ? '_'. $type->prefix : '');
+
+  $access = module_invoke($base, 'access', $op, $node);
   if (!is_null($access)) {
     return $access;
   }
Index: modules/poll/poll.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/poll/poll.module,v
retrieving revision 1.211
diff -u -r1.211 poll.module
--- modules/poll/poll.module	24 Aug 2006 08:56:17 -0000	1.211
+++ modules/poll/poll.module	25 Aug 2006 13:21:57 -0000
@@ -279,7 +279,6 @@
   return array(
     'poll' => array(
       'name' => t("poll"),
-      'module' => 'poll',
       'description' => t("A poll is a multiple-choice question which visitors can vote on."),
       'title_label' => t('Question'),
       'has_body' => FALSE,
Index: modules/system/system.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/system/system.install,v
retrieving revision 1.12
diff -u -r1.12 system.install
--- modules/system/system.install	24 Aug 2006 06:27:41 -0000	1.12
+++ modules/system/system.install	25 Aug 2006 13:22:00 -0000
@@ -202,6 +202,7 @@
         type varchar(32) NOT NULL,
         name varchar(255) NOT NULL default '',
         module varchar(255) NOT NULL,
+        prefix varchar(255) NOT NULL,
         description mediumtext NOT NULL,
         help mediumtext NOT NULL,
         has_title tinyint unsigned NOT NULL,
@@ -604,6 +605,7 @@
         type varchar(32) NOT NULL,
         name varchar(255) NOT NULL default '',
         module varchar(255) NOT NULL,
+        prefix varchar(255) NOT NULL,
         description text NOT NULL,
         help text NOT NULL,
         has_title smallint_unsigned NOT NULL,
@@ -823,8 +825,8 @@
 
   db_query("INSERT INTO {node_access} VALUES (0, 0, 'all', 1, 0, 0)");
 
-  db_query("INSERT INTO {node_type} (type, name, module, description, help, has_title, title_label, has_body, body_label, min_word_count, custom, modified, locked, orig_type) VALUES ('page', 'page', 'node', 'If you want to add a static page, like a contact page or an about page, use a page.', '', 1, 'Title', 1, 'Body', 0, 1, 1, 0, 'page')");
-  db_query("INSERT INTO {node_type} (type, name, module, description, help, has_title, title_label, has_body, body_label, min_word_count, custom, modified, locked, orig_type) VALUES ('story', 'story', 'node', 'Stories are articles in their simplest form: they have a title, a teaser and a body, but can be extended by other modules. The teaser is part of the body too. Stories may be used as a personal blog or for news articles.', '', 1, 'Title', 1, 'Body', 0, 1, 1, 0, 'story')");
+  db_query("INSERT INTO {node_type} (type, name, module, prefix, description, help, has_title, title_label, has_body, body_label, min_word_count, custom, modified, locked, orig_type) VALUES ('page', 'page', 'node', 'content', 'If you want to add a static page, like a contact page or an about page, use a page.', '', 1, 'Title', 1, 'Body', 0, 1, 1, 0, 'page')");
+  db_query("INSERT INTO {node_type} (type, name, module, prefix, description, help, has_title, title_label, has_body, body_label, min_word_count, custom, modified, locked, orig_type) VALUES ('story', 'story', 'node', 'content', 'Stories are articles in their simplest form: they have a title, a teaser and a body, but can be extended by other modules. The teaser is part of the body too. Stories may be used as a personal blog or for news articles.', '', 1, 'Title', 1, 'Body', 0, 1, 1, 0, 'story')");
 
   db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('Filtered HTML',',1,2,',1)");
   db_query("INSERT INTO {filter_formats} (name, roles, cache) VALUES ('PHP code','',0)");
@@ -2963,6 +2965,7 @@
         type varchar(32) NOT NULL,
         name varchar(255) NOT NULL,
         module varchar(255) NOT NULL,
+        prefix varchar(255) NOT NULL,
         description mediumtext NOT NULL,
         help mediumtext NOT NULL,
         has_title tinyint unsigned NOT NULL,
@@ -2983,6 +2986,7 @@
         type varchar(32) NOT NULL,
         name varchar(255) NOT NULL,
         module varchar(255) NOT NULL,
+        prefix varchar(255) NOT NULL,
         description text NOT NULL,
         help text NOT NULL,
         has_title integer unsigned NOT NULL,
@@ -3005,6 +3009,7 @@
       'type' => 'page',
       'name' => t('page'),
       'module' => 'node',
+      'prefix' => 'content',
       'description' => t('If you want to add a static page, like a contact page or an about page, use a page.'),
       'custom' => TRUE,
       'modified' => TRUE,
@@ -3014,6 +3019,7 @@
       'type' => 'story',
       'name' => t('story'),
       'module' => 'node',
+      'prefix' => 'content',
       'description' => t('Stories are articles in their simplest form: they have a title, a teaser and a body, but can be extendd by other modules. The teaser is part of the body too. Stories may be used as a personal blog or for news articles.'),
       'custom' => TRUE,
       'modified' => TRUE,
