? DrupalCVS.zpj
? files
? node_submit_hooks_105.patch
? node_submit_hooks_106.patch
Index: includes/form.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/form.inc,v
retrieving revision 1.139
diff -u -r1.139 form.inc
--- includes/form.inc	23 Aug 2006 05:04:05 -0000	1.139
+++ includes/form.inc	25 Aug 2006 07:55:56 -0000
@@ -678,8 +678,7 @@
         $cache[$element_type] = array_merge_recursive($basic_defaults, $info);
       }
     }
-  }
-
+  } 
   return $cache[$type];
 }
 
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 07:55:57 -0000
@@ -187,18 +187,19 @@
   return db_fetch_object(db_query('SELECT * FROM {book} WHERE vid = %d', $node->vid));
 }
 
-/**
- * Implementation of hook_insert().
- */
-function book_insert($node) {
-  db_query("INSERT INTO {book} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d)", $node->nid, $node->vid, $node->parent, $node->weight);
+function book_form_alter($form_id, &$form) {
+  if ($form_id == 'book_node_form') {
+    // add own handler for saving ancestry to {book} table
+    $form['#submit']['book_node_submit'] = array();
+  }
+  elseif ($form_id == 'node_delete_confirm') {
+    $form['#submit']['book_node_delete_confirm_submit'] = array();
+  }
 }
 
-/**
- * Implementation of hook_update().
- */
-function book_update($node) {
-  if ($node->revision) {
+function book_node_submit($form_id, $node) {
+  $node = (object)$node;
+  if ($node->is_new || $node->revision) {
     db_query("INSERT INTO {book} (nid, vid, parent, weight) VALUES (%d, %d, %d, %d)", $node->nid, $node->vid, $node->parent, $node->weight);
   }
   else {
@@ -206,30 +207,16 @@
   }
 }
 
-/**
- * Implementation of hook_delete().
- */
-function book_delete(&$node) {
-  db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
-}
-
-/**
- * Implementation of hook_submit().
- */
-function book_submit(&$node) {
-  global $user;
-  // Set default values for non-administrators.
-  if (!user_access('administer nodes')) {
-    $node->revision = 1;
-    $book->uid = $user->uid;
-    $book->name = $user->uid ? $user->name : '';
-  }
+function book_node_delete_confirm_submit($form_id, $form_values) {
+  db_query('DELETE FROM {book} WHERE nid = %d OR parent = %d', $form_values['node']->nid, $form_values['node']->nid);
 }
 
 /**
  * Implementation of hook_form().
  */
 function book_form(&$node) {
+  global $user;
+
   $type = node_get_types('type', $node);
   if ($node->nid && !$node->parent && !user_access('create new books')) {
     $form['parent'] = array('#type' => 'value', '#value' => $node->parent);
@@ -265,22 +252,23 @@
     '#description' => t('An explanation of the additions or updates being made to help other authors understand your motivations.'),
   );
 
-  if (user_access('administer nodes')) {
-    $form['weight'] = array('#type' => 'weight',
-      '#title' => t('Weight'),
-      '#default_value' => $node->weight,
-      '#delta' => 15,
-      '#weight' => 5,
-      '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
-    );
-  }
-  else {
+  $form['weight'] = array('#type' => 'weight',
+    '#title' => t('Weight'),
+    '#access' => user_access('administer nodes'),
+    '#default_value' => $node->weight,
+    '#delta' => 15,
+    '#weight' => 5,
+    '#description' => t('Pages at a given level are ordered first by weight and then by title.'),
+  );
+
+  if (!user_access('administer nodes')) {
     // If a regular user updates a book page, we preserve the node weight; otherwise
     // we use 0 as the default for new pages
     $form['weight'] = array(
       '#type' => 'value',
       '#value' => isset($node->weight) ? $node->weight : 0,
     );
+    $form['name'] = array('#type' => 'value', '#value' => $user->uid ? $user->name : '');
   }
 
   return $form;
@@ -481,9 +469,6 @@
     case 'delete revision':
       db_query('DELETE FROM {book} WHERE vid = %d', $node->vid);
       break;
-    case 'delete':
-      db_query('DELETE FROM {book} WHERE nid = %d', $node->nid);
-      break;
   }
 }
 
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.478
diff -u -r1.478 comment.module
--- modules/comment/comment.module	22 Aug 2006 11:13:03 -0000	1.478
+++ modules/comment/comment.module	25 Aug 2006 07:56:00 -0000
@@ -280,6 +280,7 @@
   }
   elseif (isset($form['type'])) {
     if ($form['type']['#value'] .'_node_form' == $form_id) {
+      $form['#submit']['comment_node_submit'] = array();
       $node = $form['#node'];
       $form['comment_settings'] = array(
         '#type' => 'fieldset',
@@ -297,6 +298,10 @@
       );
     }
   }
+  
+  if ($form_id == 'node_delete_confirm') {
+    $form['#submit']['comment_node_delete_confirm_submit'] = array();
+  }
 }
 
 /**
@@ -315,15 +320,6 @@
       }
       break;
 
-    case 'insert':
-      db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->created, $node->uid);
-      break;
-
-    case 'delete':
-      db_query('DELETE FROM {comments} WHERE nid = %d', $node->nid);
-      db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $node->nid);
-      break;
-
     case 'update index':
       $text = '';
       $comments = db_query('SELECT subject, comment, format FROM {comments} WHERE nid = %d AND status = %d', $node->nid, COMMENT_PUBLISHED);
@@ -346,6 +342,17 @@
   }
 }
 
+function comment_node_delete_confirm_submit($form_id, $form_values) {
+  db_query('DELETE FROM {comments} WHERE nid = %d', $form_values['node']->nid);
+  db_query('DELETE FROM {node_comment_statistics} WHERE nid = %d', $form_values['node']->nid);
+}
+
+function comment_node_submit($form_id, $node) {
+  if ($node->is_new) {
+    db_query('INSERT INTO {node_comment_statistics} (nid, last_comment_timestamp, last_comment_name, last_comment_uid, comment_count) VALUES (%d, %d, NULL, %d, 0)', $node->nid, $node->created, $node->uid);
+  }
+}
+
 /**
  * Implementation of hook_user().
  *
Index: modules/forum/forum.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/forum/forum.module,v
retrieving revision 1.352
diff -u -r1.352 forum.module
--- modules/forum/forum.module	23 Aug 2006 07:23:08 -0000	1.352
+++ modules/forum/forum.module	25 Aug 2006 07:56:01 -0000
@@ -233,6 +233,39 @@
       unset($form['nodes']['forum']);
     }
   }
+  
+  if ($form_id == 'forum_node_form') {
+    // add own handlers to node form
+    $form['#validate']['forum_node_validate'] = array();
+    // prepend this handler to insure that it executes before node_form_submit() performs its save.
+    array_unshift($form['#submit'], array('forum_node_submit_early' => array()));
+    $form['#submit']['forum_node_submit'] = array();
+  }
+  
+  if ($form_id == 'node_delete_confirm'  && $form['node']['#value']->type == 'forum') {
+    $form['#submit']['forum_node_delete_confirm_submit'] = array();
+  }
+}
+
+/**
+ * Check in particular that only a "leaf" term in the associated taxonomy
+ * vocabulary is selected, not a "container" term.
+ */
+function forum_node_validate($form_id, $node) {
+  $node = (object)$node;
+  if ($node->taxonomy) {
+    // Extract the node's proper topic ID.
+    $vocabulary = variable_get('forum_nav_vocabulary', '');
+    $containers = variable_get('forum_containers', array());
+    foreach ($node->taxonomy as $term) {
+      if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
+        if (in_array($term, $containers)) {
+          $term = taxonomy_get_term($term);
+          form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => theme('placeholder', $term->name))));
+        }
+      }
+    }
+  }
 }
 
 /**
@@ -327,12 +360,9 @@
 }
 
 /**
- * Implementation of hook_submit().
- *
- * Check in particular that only a "leaf" term in the associated taxonomy
- * vocabulary is selected, not a "container" term.
+ * An early submit handler of the forum_node_form. Runs before the node is saved.
  */
-function forum_submit(&$node) {
+function forum_node_submit_early($form_id, &$node) {
   // Make sure all fields are set properly:
   $node->icon = $node->icon ? $node->icon : '';
 
@@ -359,32 +389,9 @@
   }
 }
 
-/**
- * Implementation of hook_validate().
- *
- * Check in particular that only a "leaf" term in the associated taxonomy
- * vocabulary is selected, not a "container" term.
- */
-function forum_validate($node) {
-  if ($node->taxonomy) {
-    // Extract the node's proper topic ID.
-    $vocabulary = variable_get('forum_nav_vocabulary', '');
-    $containers = variable_get('forum_containers', array());
-    foreach ($node->taxonomy as $term) {
-      if (db_result(db_query('SELECT COUNT(*) FROM {term_data} WHERE tid = %d AND vid = %d', $term, $vocabulary))) {
-        if (in_array($term, $containers)) {
-          $term = taxonomy_get_term($term);
-          form_set_error('taxonomy', t('The item %forum is only a container for forums. Please select one of the forums below it.', array('%forum' => $term->name)));
-        }
-      }
-    }
-  }
-}
 
-/**
- * Implementation of hook_update().
- */
-function forum_update($node) {
+function forum_node_submit($node) {
+  $node = (object)$node;
   if ($node->revision) {
     db_query("INSERT INTO {forum} (nid, vid, tid) VALUES (%d, %d, %d)", $node->nid, $node->vid, $node->tid);
   }
@@ -424,18 +431,8 @@
   }
 }
 
-/**
- * Implementation of hook_insert().
- */
-function forum_insert($node) {
-  db_query('INSERT INTO {forum} (nid, vid, tid) VALUES (%d, %d, %d)', $node->nid, $node->vid, $node->tid);
-}
-
-/**
- * Implementation of hook_delete().
- */
-function forum_delete(&$node) {
-  db_query('DELETE FROM {forum} WHERE nid = %d', $node->nid);
+function forum_node_delete_confirm_submit($form_id, $form_values) {
+  db_query('DELETE FROM {forum} WHERE nid = %d', $form_values['node']->nid);
 }
 
 /**
Index: modules/menu/menu.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/menu/menu.module,v
retrieving revision 1.82
diff -u -r1.82 menu.module
--- modules/menu/menu.module	22 Aug 2006 11:13:03 -0000	1.82
+++ modules/menu/menu.module	25 Aug 2006 07:56:02 -0000
@@ -147,31 +147,20 @@
   }
 }
 
-/**
- * Implementation of hook_nodeapi().
- */
-function menu_nodeapi(&$node, $op) {
-
-  if (user_access('administer menu')) {
-    switch ($op) {
-      case 'insert':
-      case 'update':
-        if ($node->menu['delete']) {
-          menu_node_form_delete($node);
-          menu_rebuild();
-        }
-        elseif ($node->menu['title']) {
-          $node->menu['path'] = ($node->menu['path']) ? $node->menu['path'] : "node/$node->nid";
-          menu_edit_item_save($node->menu);
-          menu_rebuild();
-        }
-        break;
+function menu_node_delete_confirm_submit($form_id, $form_values) {
+  menu_node_form_delete($form_values['node']);
+  menu_rebuild();
+}
 
-      case 'delete':
-        menu_node_form_delete($node);
-        menu_rebuild();
-        break;
-    }
+function menu_node_submit($form_id, $node) {
+  if ($node->menu['delete']) {
+    menu_node_form_delete($node);
+    menu_rebuild();
+  }
+  elseif ($node->menu['title']) {
+    $node->menu['path'] = ($node->menu['path']) ? $node->menu['path'] : "node/$node->nid";
+    menu_edit_item_save($node->menu);
+    menu_rebuild();
   }
 }
 
@@ -198,6 +187,8 @@
         $item = !is_array($item) ? $edit['menu'] : (($_POST['op'] == t('Preview')) ? array_merge($item, $edit['menu']) : array_merge($edit['menu'], $item));
       }
     }
+    
+    $form['#submit']['menu_node_submit'] = array();
 
     $form['menu'] = array('#type' => 'fieldset',
       '#title' => t('Menu settings'),
@@ -259,6 +250,10 @@
       );
     }
   }
+  
+  if ($form_id == 'node_delete_confirm') {
+    $form['#submit']['menu_node_delete_confirm_submit'] = array();
+  }
 }
 
 /**
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.685
diff -u -r1.685 node.module
--- modules/node/node.module	23 Aug 2006 18:38:41 -0000	1.685
+++ modules/node/node.module	25 Aug 2006 07:56:05 -0000
@@ -3,7 +3,27 @@
 
 /**
  * @file
- * The core that allows content to be submitted to the site.
+ * The core that allows content to be submitted to the site. Modules and scripts may  
+ * programmatically submit nodes using the usual form API pattern.
+
+ * CREATE/EDIT NODE EXAMPLE
+ * $type = 'story';
+ * $node = array('type' => $type);
+ * $form = drupal_retrieve_form($type. '_node_form', $node);
+ * $form['#post']['edit']['nid'] = 112; // send this if performing an edit
+ * $form['#post']['edit']['name'] = 'amy';
+ * $form['#post']['edit']['title'] = 'robotitle';
+ * $form['#post']['edit']['body'] = 'hello world';
+ * $goto = drupal_process_form($type. '_node_form', $form);
+ *
+ * DELETE SINGLE NODE EXAMPLE
+ * $node = node_load(112); 
+ * $form = drupal_retrieve_form('node_delete_confirm', $node);
+ * $form['#post']['op'] = t('Delete');
+ * $goto = drupal_process_form('node_delete_confirm', $form);
+ *
+ * Calling form_get_errors() will list any validation errors that prevented the
+ * form from being submitted.
  */
 
 define('NODE_NEW_LIMIT', time() - 30 * 24 * 60 * 60);
@@ -456,9 +476,9 @@
  * @return
  *   A fully-populated node object.
  */
-function node_load($param = array(), $revision = NULL, $reset = NULL) {
+function node_load($param = array(), $revision = NULL, $reset = NULL) {  
   static $nodes = array();
-
+  
   if ($reset) {
     $nodes = array();
   }
@@ -601,16 +621,6 @@
   db_query($node_query, $node_table_values);
   db_query($revisions_query, $revisions_table_values);
 
-  // Call the node specific callback (if any):
-  if ($node->is_new) {
-    node_invoke($node, 'insert');
-    node_invoke_nodeapi($node, 'insert');
-  }
-  else {
-    node_invoke($node, 'update');
-    node_invoke_nodeapi($node, 'update');
-  }
-
   // Update the node access table for this node.
   node_access_acquire_grants($node);
 
@@ -1072,6 +1082,8 @@
           'path' => 'node/add/'. $type_url_str,
           'title' => t($name),
           'access' => node_access('create', $type->type),
+          'callback' => 'drupal_get_form',
+          'callback arguments' => array($type->type. '_node_form', array('type' => $type->type))
         );
       }
     }
@@ -1100,7 +1112,7 @@
           'type' => MENU_LOCAL_TASK);
         $items[] = array('path' => 'node/'. arg(1) .'/delete', 'title' => t('delete'),
           'callback' => 'drupal_get_form',
-          'callback arguments' => array('node_delete_confirm'),
+          'callback arguments' => array('node_delete_confirm', $node),
           'access' => node_access('delete', $node),
           'weight' => 1,
           'type' => MENU_CALLBACK);
@@ -1757,53 +1769,9 @@
 }
 
 /**
- * Prepare node for save and allow modules to make changes.
+ * A form validate handler. Perform checks on the given node.
  */
-function node_submit($node) {
-  global $user;
-
-  // Convert the node to an object, if necessary.
-  $node = (object)$node;
-
-  // Auto-generate the teaser, but only if it hasn't been set (e.g. by a
-  // module-provided 'teaser' form item).
-  if (!isset($node->teaser)) {
-    $node->teaser = isset($node->body) ? node_teaser($node->body, isset($node->format) ? $node->format : NULL) : '';
-  }
-
-  $access = user_access('administer nodes');
-  if ($access) {
-    // Populate the "authored by" field.
-    if ($account = user_load(array('name' => $node->name))) {
-      $node->uid = $account->uid;
-    }
-    else {
-      $node->uid = 0;
-    }
-
-    $node->created = $node->date ? strtotime($node->date) : NULL;
-  }
-  // Force defaults in case people modify the form:
-  $node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
-  foreach (array('status', 'promote', 'sticky', 'revision') as $key) {
-    if (!$access || !isset($node->$key)) {
-      $node->$key = in_array($key, $node_options);
-    }
-  }
-
-  // Do node-type-specific validation checks.
-  node_invoke($node, 'submit');
-  node_invoke_nodeapi($node, 'submit');
-
-  $node->validated = TRUE;
-
-  return $node;
-}
-
-/**
- * Perform validation checks on the given node.
- */
-function node_validate($node, $form = array()) {
+function node_form_validate($form_id, $node) {
   // Convert the node to an object, if necessary.
   $node = (object)$node;
   $type = node_get_types('type', $node);
@@ -1832,14 +1800,6 @@
       form_set_error('date', t('You have to specify a valid date.'));
     }
   }
-
-  // Do node-type-specific validation checks.
-  node_invoke($node, 'validate', $form);
-  node_invoke_nodeapi($node, 'validate', $form);
-}
-
-function node_form_validate($form_id, $form_values, $form) {
-  node_validate($form_values, $form);
 }
 
 function node_object_prepare(&$node) {
@@ -1858,9 +1818,11 @@
 }
 
 /**
- * Generate the node editing form array
+ * Generate the node add/edit form array.
  */
 function node_form($node) {
+  global $user;
+  
   $node = (object)$node;
   node_object_prepare($node);
 
@@ -1884,54 +1846,31 @@
     $form['title']['#weight'] = -5;
   }
 
+  // Populate $node so we can assign it to $form['#node].
   $node_options = variable_get('node_options_'. $node->type, array('status', 'promote'));
   // If this is a new node, fill in the default values.
   if (!isset($node->nid)) {
     foreach (array('status', 'promote', 'sticky', 'revision') as $key) {
       $node->$key = in_array($key, $node_options);
     }
-    global $user;
-    $node->uid = $user->uid;
   }
   else {
     // Nodes being edited should always be preset with the default revision setting.
     $node->revision = in_array('revision', $node_options);
   }
   $form['#node'] = $node;
-
-  // Node author information for administrators
-  $form['author'] = array(
-    '#type' => 'fieldset',
-    '#access' => user_access('administer nodes'),
-    '#title' => t('Authoring information'),
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-    '#weight' => 20,
-  );
-  $form['author']['name'] = array('#type' => 'textfield', '#title' => t('Authored by'), '#maxlength' => 60, '#autocomplete_path' => 'user/autocomplete', '#default_value' => $node->name ? $node->name : '', '#weight' => -1, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', 'Anonymous'))));
-  $form['author']['date'] = array('#type' => 'textfield', '#title' => t('Authored on'), '#maxlength' => 25, '#description' => t('Format: %time. Leave blank to use the time of form submission.', array('%time' => $node->date)));
-
-  if (isset($node->nid)) {
-    $form['author']['date']['#default_value'] = $node->date;
-  }
-
-  // Node options for administrators
-  $form['options'] = array(
-    '#type' => 'fieldset',
-    '#access' => user_access('administer nodes'),
-    '#title' => t('Publishing options'),
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-    '#weight' => 25,
-  );
+  
+  // Node author information is editable only by administrators.
+  $form['author'] = array('#type' => 'fieldset', '#title' => t('Authoring information'), '#access' => user_access('administer nodes'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => 20);
+  $form['author']['name'] = array('#type' => 'textfield', '#title' => t('Authored by'), '#maxlength' => 60, '#autocomplete_path' => 'user/autocomplete', '#default_value' => $node->nid ? $node->name : $user->name, '#weight' => -1, '#description' => t('Leave blank for %anonymous.', array('%anonymous' => variable_get('anonymous', 'Anonymous'))));
+  $form['author']['date'] = array('#type' => 'textfield', '#title' => t('Authored on'), '#maxlength' => 25, '#default_value' => $node->date, '#description' => t('Format: %time. Leave blank to use the time of form submission.', array('%time' => $node->date)));
+  
+  // Node options are editable only by administrators.
+  $form['options'] = array('#type' => 'fieldset', '#title' => t('Publishing options'), '#access' => user_access('administer nodes'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#weight' => 25);
   $form['options']['status']   = array('#type' => 'checkbox', '#title' => t('Published'), '#default_value' => $node->status);
   $form['options']['promote']  = array('#type' => 'checkbox', '#title' => t('Promoted to front page'), '#default_value' => $node->promote);
   $form['options']['sticky']   = array('#type' => 'checkbox', '#title' => t('Sticky at top of lists'), '#default_value' => $node->sticky);
   $form['options']['revision'] = array('#type' => 'checkbox', '#title' => t('Create new revision'), '#default_value' => $node->revision);
-  // These values are used when the user has no administrator accesss.
-  foreach (array('uid', 'created') as $key) {
-    $form[$key] = array('#type' => 'value', '#value' => $node->$key);
-  }
 
   // Add the buttons.
   $form['preview'] = array('#type' => 'button', '#value' => t('Preview'), '#weight' => 40);
@@ -2003,40 +1942,30 @@
 }
 
 /**
- * Present a node submission form or a set of links to such forms.
+ * Present set of list of node creation links
  */
-function node_add($type = NULL) {
+function node_add() {
   global $user;
 
   $types = node_get_types();
   $type = isset($type) ? str_replace('-', '_', $type) : NULL;
-  // If a node type has been specified, validate its existence.
-  if (isset($types[$type]) && node_access('create', $type)) {
-    // Initialize settings:
-    $node = array('uid' => $user->uid, 'name' => $user->name, 'type' => $type);
+  
+  foreach ($types as $type) {
+    if (function_exists($type->module .'_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>';
+      $out .= '<dd>'. filter_xss_admin($type->description) .'</dd>';
+      $item[$type->type] = $out;
+    }
+  }
 
-    $output = drupal_get_form($type .'_node_form', $node);
-    drupal_set_title(t('Submit @name', array('@name' => $types[$type]->name)));
+  if (isset($item)) {
+    uksort($item, 'strnatcasecmp');
+    $output = t('Choose the appropriate item from the list:') .'<dl>'. implode('', $item) .'</dl>';
   }
   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)) {
-        $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>';
-        $out .= '<dd>'. filter_xss_admin($type->description) .'</dd>';
-        $item[$type->type] = $out;
-      }
-    }
-
-    if (isset($item)) {
-      uksort($item, 'strnatcasecmp');
-      $output = t('Choose the appropriate item from the list:') .'<dl>'. implode('', $item) .'</dl>';
-    }
-    else {
-      $output = t('No content types available.');
-    }
+    $output = t('No content types available.');
   }
 
   return $output;
@@ -2116,31 +2045,27 @@
   return '<div class="log"><div class="title">'. t('Log') .':</div>'. $log .'</div>';
 }
 
-function node_form_submit($form_id, $edit) {
+function node_form_submit($form_id, &$node) {
   global $user;
-
-  // Fix up the node when required:
-  $node = node_submit($edit);
-
-  // Prepare the node's body:
-  if ($node->nid) {
-    // Check whether the current user has the proper access rights to
-    // perform this operation:
-    if (node_access('update', $node)) {
-      node_save($node);
-      watchdog('content', t('@type: updated %title.', array('@type' => t($node->type), '%title' => $node->title)), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
-      drupal_set_message(t('The %post was updated.', array ('%post' => node_get_types('name', $node))));
-    }
-  }
-  else {
-    // Check whether the current user has the proper access rights to
-    // perform this operation:
-    if (node_access('create', $node)) {
-      node_save($node);
-      watchdog('content', t('@type: added %title.', array('@type' => t($node->type), '%title' => $node->title)), WATCHDOG_NOTICE, l(t('view'), "node/$node->nid"));
-      drupal_set_message(t('Your %post was created.', array ('%post' => node_get_types('name', $node))));
-    }
+  
+  $node = (object)$node;
+  // Auto-generate the teaser, but only if it hasn't been set (e.g. by a
+  // module-provided 'teaser' form item).
+  if (!isset($node->teaser)) {
+    $node->teaser = isset($node->body) ? node_teaser($node->body, isset($node->format) ? $node->format : NULL) : '';
   }
+
+  // Populate the uid based on name field.
+  $account = user_load(array('name' => $node->name));
+  $node->uid = $account->uid;
+  $node->created = strtotime($node->date);
+
+  $action = $node->nid ? 'updated' : 'created';
+  node_save($node);
+  watchdog('content', t("@type: $action %title.", array('@type' => t($node->type), '%title' => $node->title)), WATCHDOG_NOTICE, l(t('view'), 'node/'. $node->nid));
+  drupal_set_message(t("The %post was $action.", array ('%post' => node_get_types('name', $node))));
+  
+  // redirect the submitter as needed
   if ($node->nid) {
     if (node_access('view', $node)) {
       return 'node/'. $node->nid;
@@ -2156,13 +2081,9 @@
 /**
  * Menu callback -- ask for confirmation of node deletion
  */
-function node_delete_confirm() {
-  $edit = $_POST['edit'];
-  $edit['nid'] = $edit['nid'] ? $edit['nid'] : arg(1);
-  $node = node_load($edit['nid']);
-
+function node_delete_confirm($node) {
   if (node_access('delete', $node)) {
-    $form['nid'] = array('#type' => 'value', '#value' => $node->nid);
+    $form['node'] = array('#type' => 'value', '#value' => $node);
     $output = confirm_form($form,
                    t('Are you sure you want to delete %title?', array('%title' => $node->title)),
                    $_GET['destination'] ? $_GET['destination'] : 'node/'. $node->nid, t('This action cannot be undone.'),
@@ -2176,10 +2097,7 @@
  * Execute node deletion
  */
 function node_delete_confirm_submit($form_id, $form_values) {
-  if ($form_values['confirm']) {
-    node_delete($form_values['nid']);
-  }
-
+  node_delete($form_values['node']->nid);
   return '';
 }
 
@@ -2194,10 +2112,6 @@
     db_query('DELETE FROM {node} WHERE nid = %d', $node->nid);
     db_query('DELETE FROM {node_revisions} WHERE nid = %d', $node->nid);
 
-    // Call the node-specific callback (if any):
-    node_invoke($node, 'delete');
-    node_invoke_nodeapi($node, 'delete');
-
     // Clear the cache so an anonymous poster can see the node being deleted.
     cache_clear_all();
 
Index: modules/path/path.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/path/path.module,v
retrieving revision 1.91
diff -u -r1.91 path.module
--- modules/path/path.module	22 Aug 2006 11:13:04 -0000	1.91
+++ modules/path/path.module	25 Aug 2006 07:56:05 -0000
@@ -209,16 +209,6 @@
 function path_nodeapi(&$node, $op, $arg) {
   if (user_access('create url aliases') || user_access('administer url aliases')) {
     switch ($op) {
-      case 'validate':
-        $node->path = trim($node->path);
-        if ($node->path && !valid_url($node->path)) {
-          form_set_error('path', t('The path is invalid.'));
-        }
-        else if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND src != '%s'", $node->path, "node/$node->nid"))) {
-          form_set_error('path', t('The path is already in use.'));
-        }
-        break;
-
       case 'load':
         $path = "node/$node->nid";
         // We don't use drupal_get_path_alias() to avoid custom rewrite functions.
@@ -228,27 +218,37 @@
           $node->path = db_result($result);
         }
         break;
+    }
+  }
+}
 
-      case 'insert':
-        // Don't try to insert if path is NULL. We may have already set
-        // the alias ahead of time.
-        if ($node->path) {
-          path_set_alias("node/$node->nid", $node->path);
-        }
-        break;
-
-      case 'update':
-        path_set_alias("node/$node->nid", $node->path, $node->pid);
-        break;
+function path_node_delete_confirm_submit($form_id, $form_values) {
+  $path = 'node/'. $form_values['node']->nid;
+  if (drupal_get_path_alias($path) != $path) {
+    path_set_alias($path);
+  }
+}
 
-      case 'delete':
-        $path = "node/$node->nid";
-        if (drupal_get_path_alias($path) != $path) {
-          path_set_alias($path);
-        }
-        break;
+function path_node_submit($form_id, $node) {
+  if ($node->is_new) {
+    // Don't try to insert if path is NULL. We may have already set the alias ahead of time.
+    if ($node->path) {
+      path_set_alias("node/$node->nid", $node->path);
     }
   }
+  else {
+    path_set_alias("node/$node->nid", $node->path, $node->pid);
+  }
+}
+
+function path_node_validate($form_id, $node) {
+  $node['path'] = trim($node['path']);
+  if ($node['path'] && !valid_url($node['path'])) {
+    form_set_error('path', t('The path is invalid.'));
+  }
+  else if (db_result(db_query("SELECT COUNT(dst) FROM {url_alias} WHERE dst = '%s' AND src != '%s'", $node['path'], 'node/'. $node['nid']))) {
+    form_set_error('path', t('The path is already in use.'));
+  }
 }
 
 /**
@@ -256,6 +256,12 @@
  */
 function path_form_alter($form_id, &$form) {
   if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
+    
+    if (user_access('create url aliases')) {
+      $form['#validate']['path_node_validate'] = array();
+      $form['#submit']['path_node_submit'] = array();
+    }
+    
     $path = $form['#node']->path;
     $form['path'] = array(
       '#type' => 'fieldset',
@@ -280,6 +286,10 @@
       );
     }
   }
+  
+  if ($form_id == 'node_delete_confirm') {
+    $form['#submit']['path_node_delete_confirm_submit'] = array();
+  }
 }
 
 
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 07:56:06 -0000
@@ -78,46 +78,52 @@
   }
 }
 
-/**
- * Implementation of hook_delete().
- */
-function poll_delete($node) {
-  db_query("DELETE FROM {poll} WHERE nid = %d", $node->nid);
-  db_query("DELETE FROM {poll_choices} WHERE nid = %d", $node->nid);
-  db_query("DELETE FROM {poll_votes} WHERE nid = %d", $node->nid);
+function poll_node_delete_confirm_submit($form_id, $form_values) { 
+  db_query("DELETE FROM {poll} WHERE nid = %d", $form_values['node']->nid);
+  db_query("DELETE FROM {poll_choices} WHERE nid = %d", $form_values['node']->nid);
+  db_query("DELETE FROM {poll_votes} WHERE nid = %d", $form_values['node']->nid);
 }
 
 /**
- * Implementation of hook_submit().
+ * An early submit handler of the poll_node_form. Runs before the node is saved.
  */
-function poll_submit(&$node) {
+function poll_node_submit_early($form_id, &$node) {
   // Renumber fields
   $node->choice = array_values($node->choice);
   $node->teaser = poll_teaser($node);
 }
 
-/**
- * Implementation of hook_validate().
- */
-function poll_validate($node) {
-  if (isset($node->title)) {
-    // Check for at least two options and validate amount of votes:
-    $realchoices = 0;
-    // Renumber fields
-    $node->choice = array_values($node->choice);
-    foreach ($node->choice as $i => $choice) {
-      if ($choice['chtext'] != '') {
-        $realchoices++;
-      }
-      if ($choice['chvotes'] < 0) {
-        form_set_error("choice][$i][chvotes", t('Negative values are not allowed.'));
-      }
+function poll_node_validate($form_id, $node) {
+  $node = (object)$node;
+  // Check for at least two options and validate amount of votes:
+  $realchoices = 0;
+  // Renumber fields
+  $node->choice = array_values($node->choice);
+  foreach ($node->choice as $i => $choice) {
+    if ($choice['chtext'] != '') {
+      $realchoices++;
     }
-
-    if ($realchoices < 2) {
-      form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.'));
+    if ($choice['chvotes'] < 0) {
+      form_set_error("choice][$i][chvotes", t('Negative values are not allowed.'));
     }
   }
+
+  if ($realchoices < 2) {
+    form_set_error("choice][$realchoices][chtext", t('You must fill in at least two choices.'));
+  }
+}
+
+function poll_form_alter($form_id, &$form) {
+  if ($form_id == 'poll_node_form') {
+    // add own handlers to for validating/saving questions and choices
+    $form['#validate']['poll_node_validate'] = array();
+    // prepend this handler to insure that it executes before node_form_submit() performs its save.
+    array_unshift($form['#submit'], array('poll_node_submit_early' => array()));
+    $form['#submit']['poll_node_submit'] = array();
+  }
+  elseif ($form_id == 'node_delete_confirm' && $form['node']['#value']->type == 'poll') {
+    $form['#submit']['poll_node_delete_confirm_submit'] = array();
+  }
 }
 
 /**
@@ -582,12 +588,19 @@
   return $node;
 }
 
-/**
- * Implementation of hook_update().
- */
+function poll_node_submit($form_id, $node) {
+  $node = (object)$node;
+  if ($node->is_new) {
+    poll_insert($node);
+  }
+  else {
+    poll_update($node);
+  }
+}
+
 function poll_update($node) {
   db_query('UPDATE {poll} SET runtime = %d, active = %d WHERE nid = %d', $node->runtime, $node->active, $node->nid);
-
+  
   db_query('DELETE FROM {poll_choices} WHERE nid = %d', $node->nid);
   db_query('DELETE FROM {poll_votes} WHERE nid = %d', $node->nid);
 
Index: modules/statistics/statistics.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/statistics/statistics.module,v
retrieving revision 1.237
diff -u -r1.237 statistics.module
--- modules/statistics/statistics.module	18 Aug 2006 18:58:46 -0000	1.237
+++ modules/statistics/statistics.module	25 Aug 2006 07:56:06 -0000
@@ -534,14 +534,13 @@
   return $output;
 }
 
-/**
- * Implementation of hook_nodeapi().
- */
-function statistics_nodeapi(&$node, $op, $arg = 0) {
-  switch ($op) {
-    case 'delete':
-      // clean up statistics table when node is deleted
-      db_query('DELETE FROM {node_counter} WHERE nid = %d', $node->nid);
+function statistics_node_delete_confirm_submit($form_id, $form_values) {
+  db_query('DELETE FROM {node_counter} WHERE nid = %d', $form_values['node']->nid);
+}
+
+function statistics_form_alter($form_id, &$form) {
+  if ($form_id == 'node_delete_confirm') {
+    $form['#submit']['statistics_node_delete_confirm_submit'] = array();
   }
 }
 
Index: modules/taxonomy/taxonomy.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/taxonomy/taxonomy.module,v
retrieving revision 1.308
diff -u -r1.308 taxonomy.module
--- modules/taxonomy/taxonomy.module	24 Aug 2006 06:29:50 -0000	1.308
+++ modules/taxonomy/taxonomy.module	25 Aug 2006 07:56:08 -0000
@@ -606,8 +606,12 @@
  */
 function taxonomy_form_alter($form_id, &$form) {
   if (isset($form['type']) && $form['type']['#value'] .'_node_form' == $form_id) {
+    // inject custom validate and submit handlers
+    $form['#validate']['taxonomy_node_validate'] = array();
+    $form['#submit']['taxonomy_node_submit'] = array();
+  
     $node = $form['#node'];
-
+    
     if (!isset($node->taxonomy)) {
       if ($node->nid) {
         $terms = taxonomy_node_get_terms($node->nid);
@@ -672,6 +676,10 @@
       $form['taxonomy'] += array('#type' => 'fieldset', '#title' => t('Categories'), '#collapsible' => TRUE, '#collapsed' => FALSE, '#tree' => TRUE, '#weight' => -3);
     }
   }
+  
+  if ($form_id == 'node_delete_confirm') {
+    $form['#submit']['taxonomy_node_delete_confirm_submit'] = array();
+  }
 }
 
 /**
@@ -705,9 +713,9 @@
 /**
  * Make sure incoming vids are free tagging enabled.
  */
-function taxonomy_node_validate(&$node) {
-  if ($node->taxonomy) {
-    $terms = $node->taxonomy;
+function taxonomy_node_validate($form_id, $node) {
+  if ($node['taxonomy']) {
+    $terms = $node['taxonomy'];
     if ($terms['tags']) {
       foreach ($terms['tags'] as $vid => $vid_value) {
         $vocabulary = taxonomy_get_vocabulary($vid);
@@ -724,14 +732,14 @@
 /**
  * Save term associations for a given node.
  */
-function taxonomy_node_save($nid, $terms) {
-  taxonomy_node_delete($nid);
+function taxonomy_node_submit($form_id, $node) {
+  taxonomy_node_delete($node->nid);
 
   // Free tagging vocabularies do not send their tids in the form,
   // so we'll detect them here and process them independently.
-  if (isset($terms['tags'])) {
-    $typed_input = $terms['tags'];
-    unset($terms['tags']);
+  if (isset($node->taxonomy['tags'])) {
+    $typed_input = $node->taxonomy['tags'];
+    unset($node->taxonomy['tags']);
 
     foreach ($typed_input as $vid => $vid_value) {
       // This regexp allows the following types of user input:
@@ -767,27 +775,27 @@
 
         // Defend against duplicate, different cased tags
         if (!isset($inserted[$typed_term_tid])) {
-          db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $typed_term_tid);
+          db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $node->nid, $typed_term_tid);
           $inserted[$typed_term_tid] = TRUE;
         }
       }
     }
   }
 
-  if (is_array($terms)) {
-    foreach ($terms as $term) {
+  if (is_array($node->taxonomy)) {
+    foreach ($node->taxonomy as $term) {
       if (is_array($term)) {
         foreach ($term as $tid) {
           if ($tid) {
-            db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $tid);
+            db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $node->nid, $tid);
           }
         }
       }
       else if (is_object($term)) {
-        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term->tid);
+        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $node->nid, $term->tid);
       }
       else if ($term) {
-        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $nid, $term);
+        db_query('INSERT INTO {term_node} (nid, tid) VALUES (%d, %d)', $node->nid, $term);
       }
     }
   }
@@ -1157,18 +1165,6 @@
     case 'load':
      $output['taxonomy'] = taxonomy_node_get_terms($node->nid);
      return $output;
-    case 'insert':
-      taxonomy_node_save($node->nid, $node->taxonomy);
-      break;
-    case 'update':
-      taxonomy_node_save($node->nid, $node->taxonomy);
-      break;
-    case 'delete':
-      taxonomy_node_delete($node->nid);
-      break;
-    case 'validate':
-      taxonomy_node_validate($node);
-      break;
     case 'rss item':
       return taxonomy_rss_item($node);
     case 'update index':
@@ -1176,6 +1172,10 @@
   }
 }
 
+function taxonomy_node_confirm_delete_submit($form_id, $form_values) {
+  taxonomy_node_delete($form_values['node']->nid);
+}
+
 /**
  * Implementation of hook_nodeapi('update_index').
  */
Index: modules/upload/upload.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/upload/upload.module,v
retrieving revision 1.121
diff -u -r1.121 upload.module
--- modules/upload/upload.module	22 Aug 2006 11:13:04 -0000	1.121
+++ modules/upload/upload.module	25 Aug 2006 07:56:09 -0000
@@ -360,7 +360,13 @@
 
   if (isset($form['type'])) {
     $node = $form['#node'];
+
     if ($form['type']['#value'] .'_node_form' == $form_id && variable_get("upload_$node->type", TRUE)) {
+      if (user_access('upload files')) {
+        $form['#validate']['upload_node_validate'] = array();
+        $form['#submit']['upload_node_submit'] = array();
+      }
+
       drupal_add_js('misc/progress.js');
       drupal_add_js('misc/upload.js');
 
@@ -386,9 +392,14 @@
       $form['#attributes']['enctype'] = 'multipart/form-data';
     }
   }
+  
+  if ($form_id == 'node_delete_confirm') {
+    $form['#submit']['upload_node_delete_confirm_submit'] = array();
+  }
 }
 
-function _upload_validate(&$node) {
+function upload_node_validate($form_id, $node) {
+  $node = (object)$node;
   // Accumulator for disk space quotas.
   $filesize = 0;
 
@@ -480,10 +491,6 @@
       _upload_prepare($node);
       break;
 
-    case 'validate':
-      _upload_validate($node);
-      break;
-
     case 'view':
       if (isset($node->files) && user_access('view uploaded files')) {
         // Add the attachments list to node body with a heavy
@@ -518,18 +525,6 @@
         }
       }
       break;
-
-    case 'insert':
-    case 'update':
-      if (user_access('upload files')) {
-        upload_save($node);
-      }
-      break;
-
-    case 'delete':
-      upload_delete($node);
-      break;
-
     case 'delete revision':
       upload_delete_revision($node);
       break;
@@ -576,6 +571,12 @@
   }
 }
 
+function upload_node_submit($form_id, $node) {
+  if (user_access('upload files')) {
+    upload_save($node);
+  }
+}
+
 /**
  * Displays file attachments in table
  */
@@ -727,9 +728,9 @@
   }
 }
 
-function upload_delete($node) {
+function upload_node_delete_confirm_submit($form_id, $form_values) {
   $files = array();
-  $result = db_query('SELECT * FROM {files} WHERE nid = %d', $node->nid);
+  $result = db_query('SELECT * FROM {files} WHERE nid = %d', $form_values['node']->nid);
   while ($file = db_fetch_object($result)) {
     $files[$file->fid] = $file;
   }
@@ -741,7 +742,7 @@
   }
 
   // Delete all files associated with the node
-  db_query('DELETE FROM {files} WHERE nid = %d', $node->nid);
+  db_query('DELETE FROM {files} WHERE nid = %d', $form_values['node']->nid);
 }
 
 function upload_delete_revision($node) {
@@ -881,7 +882,7 @@
 
   // Handle new uploads, and merge tmp files into node-files.
   _upload_prepare($node);
-  _upload_validate($node);
+  upload_node_validate(NULL, $node);
 
   $form = _upload_form($node);
   foreach (module_implements('form_alter') as $module) {
Index: sites/default/settings.php
===================================================================
RCS file: /cvs/drupal/drupal/sites/default/settings.php,v
retrieving revision 1.33
diff -u -r1.33 settings.php
--- sites/default/settings.php	3 Aug 2006 01:12:03 -0000	1.33
+++ sites/default/settings.php	25 Aug 2006 07:56:09 -0000
@@ -84,8 +84,8 @@
  *   $db_url = 'mysqli://username:password@localhost/databasename';
  *   $db_url = 'pgsql://username:password@localhost/databasename';
  */
-$db_url = 'mysql://username:password@localhost/databasename';
-$db_prefix = '';
+$db_url = 'mysql://drupal:drupal@localhost/greenas_headfirst';
+$db_prefix = 'hf_';
 
 /**
  * Base URL (optional).
