--- node.module	2010-08-06 12:41:12.000000000 +0200
+++ node.module	2010-09-02 11:25:05.000000000 +0200
@@ -701,80 +701,7 @@ function node_invoke_nodeapi(&$node, $op
  *   A fully-populated node object.
  */
 function node_load($param = array(), $revision = NULL, $reset = NULL) {
-  static $nodes = array();
-
-  if ($reset) {
-    $nodes = array();
-  }
-
-  $cachable = ($revision == NULL);
-  $arguments = array();
-  if (is_numeric($param)) {
-    if ($cachable) {
-      // Is the node statically cached?
-      if (isset($nodes[$param])) {
-        return is_object($nodes[$param]) ? drupal_clone($nodes[$param]) : $nodes[$param];
-      }
-    }
-    $cond = 'n.nid = %d';
-    $arguments[] = $param;
-  }
-  elseif (is_array($param)) {
-    // Turn the conditions into a query.
-    foreach ($param as $key => $value) {
-      $cond[] = 'n.'. db_escape_table($key) ." = '%s'";
-      $arguments[] = $value;
-    }
-    $cond = implode(' AND ', $cond);
-  }
-  else {
-    return FALSE;
-  }
-
-  // Retrieve a field list based on the site's schema.
-  $fields = drupal_schema_fields_sql('node', 'n');
-  $fields = array_merge($fields, drupal_schema_fields_sql('node_revisions', 'r'));
-  $fields = array_merge($fields, array('u.name', 'u.picture', 'u.data'));
-  // Remove fields not needed in the query: n.vid and r.nid are redundant,
-  // n.title is unnecessary because the node title comes from the
-  // node_revisions table.  We'll keep r.vid, r.title, and n.nid.
-  $fields = array_diff($fields, array('n.vid', 'n.title', 'r.nid'));
-  $fields = implode(', ', $fields);
-  // Rename timestamp field for clarity.
-  $fields = str_replace('r.timestamp', 'r.timestamp AS revision_timestamp', $fields);
-  // Change name of revision uid so it doesn't conflict with n.uid.
-  $fields = str_replace('r.uid', 'r.uid AS revision_uid', $fields);
-
-  // Retrieve the node.
-  // No db_rewrite_sql is applied so as to get complete indexing for search.
-  if ($revision) {
-    array_unshift($arguments, $revision);
-    $node = db_fetch_object(db_query('SELECT '. $fields .' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.nid = n.nid AND r.vid = %d WHERE '. $cond, $arguments));
-  }
-  else {
-    $node = db_fetch_object(db_query('SELECT '. $fields .' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond, $arguments));
-  }
-
-  if ($node && $node->nid) {
-    // Call the node specific callback (if any) and piggy-back the
-    // results to the node or overwrite some values.
-    if ($extra = node_invoke($node, 'load')) {
-      foreach ($extra as $key => $value) {
-        $node->$key = $value;
-      }
-    }
-
-    if ($extra = node_invoke_nodeapi($node, 'load')) {
-      foreach ($extra as $key => $value) {
-        $node->$key = $value;
-      }
-    }
-    if ($cachable) {
-      $nodes[$node->nid] = is_object($node) ? drupal_clone($node) : $node;
-    }
-  }
-
-  return $node;
+  return _node_operations('load', array('param' => $param, 'revision' => $revision), $reset);
 }
 
 /**
@@ -861,81 +788,176 @@ function node_submit($node) {
  * Save a node object into the database.
  */
 function node_save(&$node) {
-  // Let modules modify the node before it is saved to the database.
-  node_invoke_nodeapi($node, 'presave');
-  global $user;
-
-  // Insert a new node.
-  $node->is_new = empty($node->nid);
+  return _node_operations('save', array('node' => $node));
+}
 
-  if ($node->is_new || !empty($node->revision)) {
-    // When inserting a node, $node->log must be set because
-    // {node_revisions}.log does not (and cannot) have a default
-    // value.  If the user does not have permission to create
-    // revisions, however, the form will not contain an element for
-    // log so $node->log will be unset at this point.
-    if (!isset($node->log)) {
-      $node->log = '';
-    }
-  }
-  elseif (empty($node->log)) {
-    // When updating a node, however, avoid clobbering an existing
-    // log entry with an empty one.
-    unset($node->log);
+function _node_operations($action, $vars, $reset=false) {
+  static $nodes = array();
+  if($reset) {
+    $nodes = array();
   }
 
-  // For the same reasons, make sure we have $node->teaser and
-  // $node->body set.
-  if (!isset($node->teaser)) {
-    $node->teaser = '';
-  }
-  if (!isset($node->body)) {
-    $node->body = '';
+  foreach($vars as $v_name => $v_value) {
+    $$v_name = $v_value;
   }
 
-  // Save the old revision if needed.
-  if (!$node->is_new && !empty($node->revision) && $node->vid) {
-    $node->old_vid = $node->vid;
-  }
+  switch(strtolower($action)) {
+    /********* START LOAD NODE ************/
+    case 'load':
+      $cachable = ($revision == NULL);
+      $arguments = array();
+      if (is_numeric($param)) {
+        if ($cachable) {
+          // Is the node statically cached?
+          if (isset($nodes[$param])) {
+            return is_object($nodes[$param]) ? drupal_clone($nodes[$param]) : $nodes[$param];
+          }
+        }
+        $cond = 'n.nid = %d';
+        $arguments[] = $param;
+      }
+      elseif (is_array($param)) {
+        // Turn the conditions into a query.
+        foreach ($param as $key => $value) {
+          $cond[] = 'n.'. db_escape_table($key) ." = '%s'";
+          $arguments[] = $value;
+        }
+        $cond = implode(' AND ', $cond);
+      }
+      else {
+        return FALSE;
+      }
 
-  $time = time();
-  if (empty($node->created)) {
-    $node->created = $time;
-  }
-  // The changed timestamp is always updated for bookkeeping purposes (revisions, searching, ...)
-  $node->changed = $time;
+      // Retrieve a field list based on the site's schema.
+      $fields = drupal_schema_fields_sql('node', 'n');
+      $fields = array_merge($fields, drupal_schema_fields_sql('node_revisions', 'r'));
+      $fields = array_merge($fields, array('u.name', 'u.picture', 'u.data'));
+      // Remove fields not needed in the query: n.vid and r.nid are redundant,
+      // n.title is unnecessary because the node title comes from the
+      // node_revisions table.  We'll keep r.vid, r.title, and n.nid.
+      $fields = array_diff($fields, array('n.vid', 'n.title', 'r.nid'));
+      $fields = implode(', ', $fields);
+      // Rename timestamp field for clarity.
+      $fields = str_replace('r.timestamp', 'r.timestamp AS revision_timestamp', $fields);
+      // Change name of revision uid so it doesn't conflict with n.uid.
+      $fields = str_replace('r.uid', 'r.uid AS revision_uid', $fields);
+
+      // Retrieve the node.
+      // No db_rewrite_sql is applied so as to get complete indexing for search.
+      if ($revision) {
+        array_unshift($arguments, $revision);
+        $node = db_fetch_object(db_query('SELECT '. $fields .' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.nid = n.nid AND r.vid = %d WHERE '. $cond, $arguments));
+      }
+      else {
+        $node = db_fetch_object(db_query('SELECT '. $fields .' FROM {node} n INNER JOIN {users} u ON u.uid = n.uid INNER JOIN {node_revisions} r ON r.vid = n.vid WHERE '. $cond, $arguments));
+      }
 
-  $node->timestamp = $time;
-  $node->format = isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT;
+      if ($node && $node->nid) {
+        // Call the node specific callback (if any) and piggy-back the
+        // results to the node or overwrite some values.
+        if ($extra = node_invoke($node, 'load')) {
+          foreach ($extra as $key => $value) {
+            $node->$key = $value;
+          }
+        }
 
-  // Generate the node table query and the node_revisions table query.
-  if ($node->is_new) {
-    _node_save_revision($node, $user->uid);
-    drupal_write_record('node', $node);
-    db_query('UPDATE {node_revisions} SET nid = %d WHERE vid = %d', $node->nid, $node->vid);
-    $op = 'insert';
-  }
-  else {
-    drupal_write_record('node', $node, 'nid');
-    if (!empty($node->revision)) {
-      _node_save_revision($node, $user->uid);
-      db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
-    }
-    else {
-      _node_save_revision($node, $user->uid, 'vid');
-    }
-    $op = 'update';
-  }
+        if ($extra = node_invoke_nodeapi($node, 'load')) {
+          foreach ($extra as $key => $value) {
+            $node->$key = $value;
+          }
+        }
+        if ($cachable) {
+          $nodes[$node->nid] = is_object($node) ? drupal_clone($node) : $node;
+        }
+      }
 
-  // Call the node specific callback (if any).
-  node_invoke($node, $op);
-  node_invoke_nodeapi($node, $op);
+      return $node;
+    break;
+    /********** END LOAD NODE *************/
+
+    /********* START SAVE NODE ************/
+    case 'save':
+      // Let modules modify the node before it is saved to the database.
+      node_invoke_nodeapi($node, 'presave');
+      global $user;
+
+      $node->is_new = FALSE;
+
+      // Apply filters to some default node fields:
+      if (empty($node->nid)) {
+        // Insert a new node.
+        $node->is_new = TRUE;
+
+        // When inserting a node, $node->log must be set because
+        // {node_revisions}.log does not (and cannot) have a default
+        // value.  If the user does not have permission to create
+        // revisions, however, the form will not contain an element for
+        // log so $node->log will be unset at this point.
+        if (!isset($node->log)) {
+          $node->log = '';
+        }
 
-  // Update the node access table for this node.
-  node_access_acquire_grants($node);
+        // For the same reasons, make sure we have $node->teaser and
+        // $node->body.  We should consider making these fields nullable
+        // in a future version since node types are not required to use them.
+        if (!isset($node->teaser)) {
+          $node->teaser = '';
+        }
+        if (!isset($node->body)) {
+          $node->body = '';
+        }
+      }
+      elseif (!empty($node->revision)) {
+        $node->old_vid = $node->vid;
+      }
+      else {
+        // When updating a node, avoid clobberring an existing log entry with an empty one.
+        if (empty($node->log)) {
+          unset($node->log);
+        }
+      }
 
-  // Clear the page and block caches.
-  cache_clear_all();
+      // Set some required fields:
+      if (empty($node->created)) {
+        $node->created = time();
+      }
+      // The changed timestamp is always updated for bookkeeping purposes (revisions, searching, ...)
+      $node->changed = time();
+
+      $node->timestamp = time();
+      $node->format = isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT;
+
+      // Generate the node table query and the node_revisions table query.
+      if ($node->is_new) {
+        _node_save_revision($node, $user->uid);
+        drupal_write_record('node', $node);
+        db_query('UPDATE {node_revisions} SET nid = %d WHERE vid = %d', $node->nid, $node->vid);
+        $op = 'insert';
+      }
+      else {
+        drupal_write_record('node', $node, 'nid');
+        if (!empty($node->revision)) {
+          _node_save_revision($node, $user->uid);
+          db_query('UPDATE {node} SET vid = %d WHERE nid = %d', $node->vid, $node->nid);
+        }
+        else {
+          _node_save_revision($node, $user->uid, 'vid');
+        }
+        $op = 'update';
+      }
+
+      // Call the node specific callback (if any).
+      node_invoke($node, $op);
+      node_invoke_nodeapi($node, $op);
+
+      // Update the node access table for this node.
+      node_access_acquire_grants($node);
+      $nodes[$node->nid] = $node;
+      // Clear the page and block caches.
+      cache_clear_all();
+    break;
+    /********* END SAVE NODE ************/
+  }
 }
 
 /**
@@ -1263,10 +1285,10 @@ function node_search($op = 'search', $ke
         $join2 .= ' LEFT JOIN {node_counter} nc ON nc.nid = i.sid';
         $total += $weight;
       }
-      
-      // When all search factors are disabled (ie they have a weight of zero), 
-      // the default score is based only on keyword relevance and there is no need to 
-      // adjust the score of each item. 
+
+      // When all search factors are disabled (ie they have a weight of zero),
+      // the default score is based only on keyword relevance and there is no need to
+      // adjust the score of each item.
       if ($total == 0) {
         $select2 = 'i.relevance AS score';
         $total = 1;
@@ -1274,7 +1296,7 @@ function node_search($op = 'search', $ke
       else {
         $select2 = implode(' + ', $ranking) . ' AS score';
       }
-      
+
       // Do search.
       $find = do_search($keys, 'node', 'INNER JOIN {node} n ON n.nid = i.sid '. $join1, $conditions1 . (empty($where1) ? '' : ' AND '. $where1), $arguments1, $select2, $join2, $arguments2);
 
@@ -1702,7 +1724,7 @@ function node_feed($nids = FALSE, $chann
         $item->body = $content;
         unset($item->teaser);
       }
-    
+
       // Allow modules to modify the fully-built node.
       node_invoke_nodeapi($item, 'alter', $teaser, FALSE);
     }
