? LOCAL-REROLL.txt
? apc.php
? constants.pl
? exception.php
? head.kpf
? head.sql.gz
? patches
? test.php
? modules/field/field.delete.inc
? modules/field/modules/combo
? scripts/generate-autoload.pl
? sites/all/cck
? sites/all/pbs
? sites/all/modules/admin_menu
? sites/all/modules/cck
? sites/all/modules/devel
? sites/all/modules/taint
? sites/default/files
? sites/default/settings.php
Index: modules/field/modules/list/list.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/list/list.info,v
retrieving revision 1.2
diff -u -F^[fc] -r1.2 list.info
--- modules/field/modules/list/list.info	5 Feb 2009 03:42:57 -0000	1.2
+++ modules/field/modules/list/list.info	9 Mar 2009 19:42:29 -0000
@@ -4,3 +4,4 @@
 package = Core - fields
 core = 7.x
 files[]=list.module
+required = TRUE
Index: modules/field/modules/number/number.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/number/number.info,v
retrieving revision 1.2
diff -u -F^[fc] -r1.2 number.info
--- modules/field/modules/number/number.info	5 Feb 2009 03:42:57 -0000	1.2
+++ modules/field/modules/number/number.info	9 Mar 2009 19:42:29 -0000
@@ -4,3 +4,4 @@
 package = Core - fields
 core = 7.x
 files[]=number.module
+required = TRUE
Index: modules/field/modules/options/options.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/options/options.info,v
retrieving revision 1.1
diff -u -F^[fc] -r1.1 options.info
--- modules/field/modules/options/options.info	3 Feb 2009 17:30:11 -0000	1.1
+++ modules/field/modules/options/options.info	9 Mar 2009 19:42:29 -0000
@@ -4,3 +4,4 @@
 package = Core - fields
 core = 7.x
 files[]=options.module
+required = TRUE
Index: modules/field/modules/text/text.info
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.info,v
retrieving revision 1.2
diff -u -F^[fc] -r1.2 text.info
--- modules/field/modules/text/text.info	5 Feb 2009 03:42:57 -0000	1.2
+++ modules/field/modules/text/text.info	9 Mar 2009 19:42:29 -0000
@@ -4,3 +4,4 @@
 package = Core - fields
 core = 7.x
 files[]=text.module
+required = TRUE
Index: modules/field/modules/text/text.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/modules/text/text.module,v
retrieving revision 1.3
diff -u -F^[fc] -r1.3 text.module
--- modules/field/modules/text/text.module	10 Feb 2009 03:16:15 -0000	1.3
+++ modules/field/modules/text/text.module	9 Mar 2009 19:42:29 -0000
@@ -175,7 +175,121 @@ function theme_field_formatter_text_plai
 function theme_field_formatter_text_trimmed($element) {
   $field = field_info_field($element['#field_name']);
   $instance = field_info_instance($element['#field_name'], $element['#bundle']);
-  return $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL;
+  return text_teaser($element['#item']['safe'], $instance['settings']['text_processing'] ? $element['#item']['format'] : NULL);
+}
+
+/**
+ * Generate a trimmed, formatted version of a text field value.
+ *
+ * If the end of the teaser is not indicated using the <!--break--> delimiter
+ * then we generate the teaser automatically, trying to end it at a sensible
+ * place such as the end of a paragraph, a line break, or the end of a
+ * sentence (in that order of preference).
+ *
+ * @param $body
+ *   The content for which a teaser will be generated.
+ * @param $format
+ *   The format of the content. If the content contains PHP code, we do not
+ *   split it up to prevent parse errors. If the line break filter is present
+ *   then we treat newlines embedded in $body as line breaks.
+ * @param $size
+ *   The desired character length of the teaser. If omitted, the default
+ *   value will be used. Ignored if the special delimiter is present
+ *   in $body.
+ * @return
+ *   The generated teaser.
+ */
+function text_teaser($body, $format = NULL, $size = NULL) {
+
+  if (!isset($size)) {
+    $size = variable_get('teaser_length', 600);
+  }
+
+  // Find where the delimiter is in the body
+  $delimiter = strpos($body, '<!--break-->');
+
+  // If the size is zero, and there is no delimiter, the entire body is the teaser.
+  if ($size == 0 && $delimiter === FALSE) {
+    return $body;
+  }
+
+  // If a valid delimiter has been specified, use it to chop off the teaser.
+  if ($delimiter !== FALSE) {
+    return substr($body, 0, $delimiter);
+  }
+
+  // We check for the presence of the PHP evaluator filter in the current
+  // format. If the body contains PHP code, we do not split it up to prevent
+  // parse errors.
+  if (isset($format)) {
+    $filters = filter_list_format($format);
+    if (isset($filters['php/0']) && strpos($body, '<?') !== FALSE) {
+      return $body;
+    }
+  }
+
+  // If we have a short body, the entire body is the teaser.
+  if (drupal_strlen($body) <= $size) {
+    return $body;
+  }
+
+  // If the delimiter has not been specified, try to split at paragraph or
+  // sentence boundaries.
+
+  // The teaser may not be longer than maximum length specified. Initial slice.
+  $teaser = truncate_utf8($body, $size);
+
+  // Store the actual length of the UTF8 string -- which might not be the same
+  // as $size.
+  $max_rpos = strlen($teaser);
+
+  // How much to cut off the end of the teaser so that it doesn't end in the
+  // middle of a paragraph, sentence, or word.
+  // Initialize it to maximum in order to find the minimum.
+  $min_rpos = $max_rpos;
+
+  // Store the reverse of the teaser. We use strpos on the reversed needle and
+  // haystack for speed and convenience.
+  $reversed = strrev($teaser);
+
+  // Build an array of arrays of break points grouped by preference.
+  $break_points = array();
+
+  // A paragraph near the end of sliced teaser is most preferable.
+  $break_points[] = array('</p>' => 0);
+
+  // If no complete paragraph then treat line breaks as paragraphs.
+  $line_breaks = array('<br />' => 6, '<br>' => 4);
+  // Newline only indicates a line break if line break converter
+  // filter is present.
+  if (isset($filters['filter/1'])) {
+    $line_breaks["\n"] = 1;
+  }
+  $break_points[] = $line_breaks;
+
+  // If the first paragraph is too long, split at the end of a sentence.
+  $break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
+
+  // Iterate over the groups of break points until a break point is found.
+  foreach ($break_points as $points) {
+    // Look for each break point, starting at the end of the teaser.
+    foreach ($points as $point => $offset) {
+      // The teaser is already reversed, but the break point isn't.
+      $rpos = strpos($reversed, strrev($point));
+      if ($rpos !== FALSE) {
+        $min_rpos = min($rpos + $offset, $min_rpos);
+      }
+    }
+
+    // If a break point was found in this group, slice and return the teaser.
+    if ($min_rpos !== $max_rpos) {
+      // Don't slice with length 0. Length must be <0 to slice from RHS.
+      return ($min_rpos === 0) ? $teaser : substr($teaser, 0, 0 - $min_rpos);
+    }
+  }
+
+  // If a break point was not found, still return a teaser.
+  return $teaser;
 }
 
 /**
Index: modules/node/node.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.install,v
retrieving revision 1.13
diff -u -F^[fc] -r1.13 node.install
--- modules/node/node.install	26 Feb 2009 07:30:27 -0000	1.13
+++ modules/node/node.install	9 Mar 2009 19:42:29 -0000
@@ -239,18 +239,6 @@ function node_schema() {
         'not null' => TRUE,
         'default' => '',
       ),
-      'body' => array(
-        'description' => 'The body of this version.',
-        'type' => 'text',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
-      'teaser' => array(
-        'description' => 'The teaser of this version.',
-        'type' => 'text',
-        'not null' => TRUE,
-        'size' => 'big',
-      ),
       'log' => array(
         'description' => 'The log entry explaining the changes in this version.',
         'type' => 'text',
@@ -326,7 +314,7 @@ function node_schema() {
         'default' => '',
       ),
       'has_body' => array(
-        'description' => 'Boolean indicating whether this type uses the {node_revision}.body field.',
+        'description' => 'Boolean indicating whether this type has the body field attached.',
         'type' => 'int',
         'unsigned' => TRUE,
         'not null' => TRUE,
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1028
diff -u -F^[fc] -r1.1028 node.module
--- modules/node/node.module	8 Mar 2009 04:25:04 -0000	1.1028
+++ modules/node/node.module	9 Mar 2009 19:42:29 -0000
@@ -46,6 +46,11 @@
 define('NODE_BUILD_PRINT', 5);
 
 /**
+ * Name of the default body field.
+ */
+define('NODE_BODY_FIELD', 'node_body');
+
+/**
  * Implementation of hook_help().
  */
 function node_help($path, $arg) {
@@ -290,186 +295,6 @@ function node_mark($nid, $timestamp) {
 }
 
 /**
- * See if the user used JS to submit a teaser.
- */
-function node_teaser_js(&$form, &$form_state) {
-  if (isset($form['#post']['teaser_js'])) {
-    // Glue the teaser to the body.
-    if (trim($form_state['values']['teaser_js'])) {
-      // Space the teaser from the body
-      $body = trim($form_state['values']['teaser_js']) . "\r\n<!--break-->\r\n" . trim($form_state['values']['body']);
-    }
-    else {
-      // Empty teaser, no spaces.
-      $body = '<!--break-->' . $form_state['values']['body'];
-    }
-    // Pass updated body value on to preview/submit form processing.
-    form_set_value($form['body'], $body, $form_state);
-    // Pass updated body value back onto form for those cases
-    // in which the form is redisplayed.
-    $form['body']['#value'] = $body;
-  }
-  return $form;
-}
-
-/**
- * Ensure value of "teaser_include" checkbox is consistent with other form data.
- *
- * This handles two situations in which an unchecked checkbox is rejected:
- *
- *   1. The user defines a teaser (summary) but it is empty;
- *   2. The user does not define a teaser (summary) (in this case an
- *      unchecked checkbox would cause the body to be empty, or missing
- *      the auto-generated teaser).
- *
- * If JavaScript is active then it is used to force the checkbox to be
- * checked when hidden, and so the second case will not arise.
- *
- * In either case a warning message is output.
- */
-function node_teaser_include_verify(&$form, &$form_state) {
-  $message = '';
-
-  // $form['#post'] is set only when the form is built for preview/submit.
-  if (isset($form['#post']['body']) && isset($form_state['values']['teaser_include']) && !$form_state['values']['teaser_include']) {
-    // "teaser_include" checkbox is present and unchecked.
-    if (strpos($form_state['values']['body'], '<!--break-->') === 0) {
-      // Teaser is empty string.
-      $message = t('You specified that the summary should not be shown when this post is displayed in full view. This setting is ignored when the summary is empty.');
-    }
-    elseif (strpos($form_state['values']['body'], '<!--break-->') === FALSE) {
-      // Teaser delimiter is not present in the body.
-      $message = t('You specified that the summary should not be shown when this post is displayed in full view. This setting has been ignored since you have not defined a summary for the post. (To define a summary, insert the delimiter "&lt;!--break--&gt;" (without the quotes) in the Body of the post to indicate the end of the summary and the start of the main content.)');
-    }
-
-    if (!empty($message)) {
-      drupal_set_message($message, 'warning');
-      // Pass new checkbox value on to preview/submit form processing.
-      form_set_value($form['teaser_include'], 1, $form_state);
-      // Pass new checkbox value back onto form for those cases
-      // in which form is redisplayed.
-      $form['teaser_include']['#value'] = 1;
-    }
-  }
-
-  return $form;
-}
-
-/**
- * Generate a teaser for a node body.
- *
- * If the end of the teaser is not indicated using the <!--break--> delimiter
- * then we generate the teaser automatically, trying to end it at a sensible
- * place such as the end of a paragraph, a line break, or the end of a
- * sentence (in that order of preference).
- *
- * @param $body
- *   The content for which a teaser will be generated.
- * @param $format
- *   The format of the content. If the content contains PHP code, we do not
- *   split it up to prevent parse errors. If the line break filter is present
- *   then we treat newlines embedded in $body as line breaks.
- * @param $size
- *   The desired character length of the teaser. If omitted, the default
- *   value will be used. Ignored if the special delimiter is present
- *   in $body.
- * @return
- *   The generated teaser.
- */
-function node_teaser($body, $format = NULL, $size = NULL) {
-
-  if (!isset($size)) {
-    $size = variable_get('teaser_length', 600);
-  }
-
-  // Find where the delimiter is in the body
-  $delimiter = strpos($body, '<!--break-->');
-
-  // If the size is zero, and there is no delimiter, the entire body is the teaser.
-  if ($size == 0 && $delimiter === FALSE) {
-    return $body;
-  }
-
-  // If a valid delimiter has been specified, use it to chop off the teaser.
-  if ($delimiter !== FALSE) {
-    return substr($body, 0, $delimiter);
-  }
-
-  // We check for the presence of the PHP evaluator filter in the current
-  // format. If the body contains PHP code, we do not split it up to prevent
-  // parse errors.
-  if (isset($format)) {
-    $filters = filter_list_format($format);
-    if (isset($filters['php/0']) && strpos($body, '<?') !== FALSE) {
-      return $body;
-    }
-  }
-
-  // If we have a short body, the entire body is the teaser.
-  if (drupal_strlen($body) <= $size) {
-    return $body;
-  }
-
-  // If the delimiter has not been specified, try to split at paragraph or
-  // sentence boundaries.
-
-  // The teaser may not be longer than maximum length specified. Initial slice.
-  $teaser = truncate_utf8($body, $size);
-
-  // Store the actual length of the UTF8 string -- which might not be the same
-  // as $size.
-  $max_rpos = strlen($teaser);
-
-  // How much to cut off the end of the teaser so that it doesn't end in the
-  // middle of a paragraph, sentence, or word.
-  // Initialize it to maximum in order to find the minimum.
-  $min_rpos = $max_rpos;
-
-  // Store the reverse of the teaser. We use strpos on the reversed needle and
-  // haystack for speed and convenience.
-  $reversed = strrev($teaser);
-
-  // Build an array of arrays of break points grouped by preference.
-  $break_points = array();
-
-  // A paragraph near the end of sliced teaser is most preferable.
-  $break_points[] = array('</p>' => 0);
-
-  // If no complete paragraph then treat line breaks as paragraphs.
-  $line_breaks = array('<br />' => 6, '<br>' => 4);
-  // Newline only indicates a line break if line break converter
-  // filter is present.
-  if (isset($filters['filter/1'])) {
-    $line_breaks["\n"] = 1;
-  }
-  $break_points[] = $line_breaks;
-
-  // If the first paragraph is too long, split at the end of a sentence.
-  $break_points[] = array('. ' => 1, '! ' => 1, '? ' => 1, '。' => 0, '؟ ' => 1);
-
-  // Iterate over the groups of break points until a break point is found.
-  foreach ($break_points as $points) {
-    // Look for each break point, starting at the end of the teaser.
-    foreach ($points as $point => $offset) {
-      // The teaser is already reversed, but the break point isn't.
-      $rpos = strpos($reversed, strrev($point));
-      if ($rpos !== FALSE) {
-        $min_rpos = min($rpos + $offset, $min_rpos);
-      }
-    }
-
-    // If a break point was found in this group, slice and return the teaser.
-    if ($min_rpos !== $max_rpos) {
-      // Don't slice with length 0. Length must be <0 to slice from RHS.
-      return ($min_rpos === 0) ? $teaser : substr($teaser, 0, 0 - $min_rpos);
-    }
-  }
-
-  // If a break point was not found, still return a teaser.
-  return $teaser;
-}
-
-/**
  * Builds a list of available node types, and returns all of part of this list
  * in the specified format.
  *
@@ -583,6 +408,7 @@ function node_type_save($info) {
     if (!empty($type->old_type) && $type->old_type != $type->type) {
       field_attach_rename_bundle($type->old_type, $type->type);
     }
+    node_configure_fields($type);
     module_invoke_all('node_type', 'update', $type);
     return SAVED_UPDATED;
   }
@@ -591,13 +417,57 @@ function node_type_save($info) {
     db_insert('node_type')->fields($fields)->execute();
 
     field_attach_create_bundle($type->type);
-
+    node_configure_fields($type);
     module_invoke_all('node_type', 'insert', $type);
     return SAVED_NEW;
   }
 }
 
 /**
+ * Manage the field(s) for a node type.
+ */
+function node_configure_fields($type) {
+  // Create body field if it does not exist yet.
+  $field = field_info_field(NODE_BODY_FIELD);
+  if (!isset($field)) {
+    $field['field_name'] = NODE_BODY_FIELD;
+    $field['type'] = 'text_long';
+    field_create_field($field);
+  }
+
+  // Create or remove a body field instance as appropriate.
+  $instance['field_name'] = NODE_BODY_FIELD;
+  $instance['bundle'] = $type->type;
+
+  if ($type->has_body) {
+    $instance['weight'] = -3;
+    $instance['label'] = $type->body_label;
+    $instance['required'] = $type->min_word_count > 0;
+    $instance['settings']['text_processing'] = TRUE;
+    $instance['widget']['type'] = 'text_textarea';
+    $instance['widget']['settings']['rows'] = 20;
+    $instance['display']['teaser']['label'] = 'hidden';
+    $instance['display']['teaser']['type'] = 'text_trimmed';
+    $instance['display']['full']['label'] = 'hidden';
+    $instance['display']['full']['type'] = 'text_default';
+    
+    $found = field_info_instance(NODE_BODY_FIELD, $type->type);
+    if (!isset($found)) {
+      field_create_instance($instance);
+    }
+    else {
+      field_update_instance($instance);
+    }
+  }
+  else {
+    $found = field_info_instance(NODE_BODY_FIELD, $type->type);
+    if (isset($found)) {
+      field_delete_instance($instance);
+    }
+  }
+}
+
+/**
  * Deletes a node type from the database.
  *
  * @param $type
@@ -974,7 +844,8 @@ function node_validate($node, $form = ar
 
   // Make sure the body has the minimum number of words.
   // TODO : use a better word counting algorithm that will work in other languages
-  if (!empty($type->min_word_count) && isset($node->body) && count(explode(' ', $node->body)) < $type->min_word_count) {
+  if (!empty($type->min_word_count) && isset($node->{NODE_BODY_FIELD}[0]['value']) && count(explode(' ', $node->{NODE_BODY_FIELD}[0]['value'])) < $type->min_word_count) {
+    // TODO: Use Field API to set this error.
     form_set_error('body', t('The body of your @type is too short. You need at least %words words.', array('%words' => $type->min_word_count, '@type' => $type->name)));
   }
 
@@ -1014,25 +885,6 @@ function node_submit($node) {
   // Convert the node to an object, if necessary.
   $node = (object)$node;
 
-  // Generate the teaser, but only if it hasn't been set (e.g. by a
-  // module-provided 'teaser' form item).
-  if (!isset($node->teaser)) {
-    if (isset($node->body)) {
-      $node->format = (!empty($node->body_format) ? $node->body_format : FILTER_FORMAT_DEFAULT);
-      $node->teaser = node_teaser($node->body, isset($node->format) ? $node->format : NULL);
-      // Chop off the teaser from the body if needed. The teaser_include
-      // property might not be set (eg. in Blog API postings), so only act on
-      // it, if it was set with a given value.
-      if (isset($node->teaser_include) && !$node->teaser_include && $node->teaser == substr($node->body, 0, strlen($node->teaser))) {
-        $node->body = substr($node->body, strlen($node->teaser));
-      }
-    }
-    else {
-      $node->teaser = '';
-      $node->format = 0;
-    }
-  }
-
   if (user_access('administer nodes')) {
     // Populate the "authored by" field.
     if ($account = user_load(array('name' => $node->name))) {
@@ -1072,16 +924,6 @@ function node_save(&$node) {
     if (!isset($node->log)) {
       $node->log = '';
     }
-
-    // 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;
@@ -1216,30 +1058,6 @@ function node_build($node, $teaser = FAL
 }
 
 /**
- * Apply filters and build the node's standard elements.
- */
-function node_prepare($node, $teaser = FALSE) {
-  // First we'll overwrite the existing node teaser and body with
-  // the filtered copies! Then, we'll stick those into the content
-  // array and set the read more flag if appropriate.
-  $node->readmore = (strlen($node->teaser) < strlen($node->body));
-
-  if ($teaser == FALSE) {
-    $node->body = check_markup($node->body, $node->format, $node->language, FALSE);
-  }
-  else {
-    $node->teaser = check_markup($node->teaser, $node->format, $node->language, FALSE);
-  }
-
-  $node->content['body'] = array(
-    '#markup' => $teaser ? $node->teaser : $node->body,
-    '#weight' => 0,
-  );
-
-  return $node;
-}
-
-/**
  * Builds a structured array representing the node's content.
  *
  * @param $node
@@ -1249,7 +1067,7 @@ function node_prepare($node, $teaser = F
  *
  * @return
  *   An structured array containing the individual elements
- *   of the node's body.
+ *   of the node's content.
  */
 function node_build_content($node, $teaser = FALSE) {
 
@@ -1258,21 +1076,33 @@ function node_build_content($node, $teas
     $node->build_mode = NODE_BUILD_NORMAL;
   }
 
-  // Remove the delimiter (if any) that separates the teaser from the body.
-  $node->body = isset($node->body) ? str_replace('<!--break-->', '', $node->body) : '';
-
   // The 'view' hook can be implemented to overwrite the default function
   // to display nodes.
   if (node_hook($node, 'view')) {
     $node = node_invoke($node, 'view', $teaser);
   }
-  else {
-    $node = node_prepare($node, $teaser);
-  }
 
   // Build fields content.
+  if (empty($node->content)) {
+    $node->content = array();
+  };
   $node->content += field_attach_view('node', $node, $teaser);
 
+  // Always display a read more link on teasers because we have no way
+  // to know when a teaser view is different than a full view.
+  $links = array();
+  if ($teaser) {
+    $links['node_readmore'] = array(
+      'title' => t('Read more'),
+      'href' => 'node/' . $node->nid,
+      'attributes' => array('rel' => 'tag', 'title' => strip_tags($node->title))
+    );
+  }
+  $node->content['links']['node'] = array(
+    '#type' => 'node_links',
+    '#value' => $links
+  );
+  
   // Allow modules to make their own additions to the node.
   node_invoke_node($node, 'view', $teaser);
 
@@ -1492,16 +1322,16 @@ function node_search($op = 'search', $ke
       // Load results.
       $results = array();
       foreach ($find as $item) {
-        // Build the node body.
+        // Render the node.
         $node = node_load($item->sid);
         $node->build_mode = NODE_BUILD_SEARCH_RESULT;
         $node = node_build_content($node, FALSE, FALSE);
-        $node->body = drupal_render($node->content);
+        $node->rendered = drupal_render($node->content);
 
         // Fetch comments for snippet.
-        $node->body .= module_invoke('comment', 'node', $node, 'update_index');
+        $node->rendered .= module_invoke('comment', 'node', $node, 'update_index');
         // Fetch terms for snippet.
-        $node->body .= module_invoke('taxonomy', 'node', $node, 'update_index');
+        $node->rendered .= module_invoke('taxonomy', 'node', $node, 'update_index');
 
         $extra = node_invoke_node($node, 'search_result');
 
@@ -1514,7 +1344,7 @@ function node_search($op = 'search', $ke
           'node' => $node,
           'extra' => $extra,
           'score' => $total ? ($item->calculated_score / $total) : 0,
-          'snippet' => search_excerpt($keys, $node->body),
+          'snippet' => search_excerpt($keys, $node->rendered),
         );
       }
       return $results;
@@ -1623,7 +1453,7 @@ function node_link($type, $node = NULL, 
   $links = array();
 
   if ($type == 'node') {
-    if ($teaser == 1 && $node->teaser && !empty($node->readmore)) {
+    if ($teaser == 1) {
       $links['node_read_more'] = array(
         'title' => t('Read more'),
         'href' => "node/$node->nid",
@@ -1928,24 +1758,11 @@ function node_feed($nids = FALSE, $chann
       if (node_hook($item, 'view')) {
         $item = node_invoke($item, 'view', $teaser, FALSE);
       }
-      else {
-        $item = node_prepare($item, $teaser);
-      }
 
       // Allow modules to change $node->content before the node is rendered.
       node_invoke_node($item, 'view', $teaser, FALSE);
 
-      // Set the proper node property, then unset unused $node property so that a
-      // bad theme can not open a security hole.
-      $content = drupal_render($item->content);
-      if ($teaser) {
-        $item->teaser = $content;
-        unset($item->body);
-      }
-      else {
-        $item->body = $content;
-        unset($item->teaser);
-      }
+      $item->rendered = drupal_render($item->content);
     
       // Allow modules to modify the fully-built node.
       node_invoke_node($item, 'alter', $teaser, FALSE);
@@ -1963,13 +1780,11 @@ function node_feed($nids = FALSE, $chann
     // Prepare the item description
     switch ($item_length) {
       case 'fulltext':
-        $item_text = $item->body;
+        $item_text = $item->rendered;
         break;
       case 'teaser':
-        $item_text = $item->teaser;
-        if (!empty($item->readmore)) {
-          $item_text .= '<p>' . l(t('read more'), 'node/' . $item->nid, array('absolute' => TRUE, 'attributes' => array('target' => '_blank'))) . '</p>';
-        }
+        $item_text = $item->rendered;
+        $item_text .= '<p>' . l(t('read more'), 'node/' . $item->nid, array('absolute' => TRUE, 'attributes' => array('target' => '_blank'))) . '</p>';
         break;
       case 'title':
         $item_text = '';
@@ -2102,12 +1917,12 @@ function _node_index_node($node) {
   // save the changed time of the most recent indexed node, for the search results half-life calculation
   variable_set('node_cron_last', $node->changed);
 
-  // Build the node body.
+  // Render the node.
   $node->build_mode = NODE_BUILD_SEARCH_INDEX;
   $node = node_build_content($node, FALSE, FALSE);
-  $node->body = drupal_render($node->content);
+  $node->rendered = drupal_render($node->content);
 
-  $text = '<h1>' . check_plain($node->title) . '</h1>' . $node->body;
+  $text = '<h1>' . check_plain($node->title) . '</h1>' . $node->rendered;
 
   // Fetch extra data normally not visible
   $extra = node_invoke_node($node, 'update_index');
@@ -2791,10 +2606,6 @@ function node_content_form($node, $form_
     );
   }
 
-  if ($type->has_body) {
-    $form['body_field'] = node_body_field($node, $type->body_label, $type->min_word_count);
-  }
-
   return $form;
 }
 
Index: modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.56
diff -u -F^[fc] -r1.56 node.pages.inc
--- modules/node/node.pages.inc	8 Mar 2009 04:25:04 -0000	1.56
+++ modules/node/node.pages.inc	9 Mar 2009 19:42:29 -0000
@@ -106,7 +106,7 @@ function node_form(&$form_state, $node) 
     $form['#prefix'] = $form_state['node_preview'];
   }
   $node = (object)$node;
-  foreach (array('body', 'title', 'format') as $key) {
+  foreach (array('title') as $key) {
     if (!isset($node->$key)) {
       $node->$key = NULL;
     }
@@ -267,48 +267,6 @@ function node_form(&$form_state, $node) 
 }
 
 /**
- * Return a node body field, with format and teaser.
- */
-function node_body_field(&$node, $label, $word_count) {
-
-  // Check if we need to restore the teaser at the beginning of the body.
-  $include = !isset($node->teaser) || ($node->teaser == substr($node->body, 0, strlen($node->teaser)));
-
-  $form = array(
-    '#after_build' => array('node_teaser_js', 'node_teaser_include_verify'));
-
-  $form['#prefix'] = '<div class="body-field-wrapper">';
-  $form['#suffix'] = '</div>';
-
-  $form['teaser_js'] = array(
-    '#type' => 'textarea',
-    '#rows' => 10,
-    '#teaser' => 'edit-body',
-    '#teaser_checkbox' => 'edit-teaser-include',
-    '#disabled' => TRUE,
-  );
-
-  $form['teaser_include'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Show summary in full view'),
-    '#default_value' => $include,
-    '#prefix' => '<div class="teaser-checkbox">',
-    '#suffix' => '</div>',
-  );
-
-  $form['body'] = array(
-    '#type' => 'textarea',
-    '#title' => check_plain($label),
-    '#default_value' => $include ? $node->body : ($node->teaser . $node->body),
-    '#rows' => 20,
-    '#required' => ($word_count > 0),
-    '#text_format' => isset($node->format) ? $node->format : FILTER_FORMAT_DEFAULT,
-  );
-
-  return $form;
-}
-
-/**
  * Button submit function: handle the 'Delete' button on the node form.
  */
 function node_form_delete_submit($form, &$form_state) {
@@ -369,16 +327,6 @@ function node_preview($node) {
 
     $node->changed = REQUEST_TIME;
 
-    // Extract a teaser, if it hasn't been set (e.g. by a module-provided
-    // 'teaser' form item).
-    if (!isset($node->teaser)) {
-      $node->teaser = empty($node->body) ? '' : node_teaser($node->body, $node->format);
-      // Chop off the teaser from the body if needed.
-      if (!$node->teaser_include && $node->teaser == substr($node->body, 0, strlen($node->teaser))) {
-        $node->body = substr($node->body, strlen($node->teaser));
-      }
-    }
-
     // Display a preview of the node.
     // Previewing alters $node so it needs to be cloned.
     if (!form_get_errors()) {
@@ -404,28 +352,20 @@ function theme_node_preview($node) {
   $output = '<div class="preview">';
 
   $preview_trimmed_version = FALSE;
-  // Do we need to preview trimmed version of post as well as full version?
-  if (isset($node->teaser) && isset($node->body)) {
-    $teaser = trim($node->teaser);
-    $body = trim(str_replace('<!--break-->', '', $node->body));
-
-    // Preview trimmed version if teaser and body will appear different;
-    // also (edge case) if both teaser and body have been specified by the user
-    // and are actually the same.
-    if ($teaser != $body || ($body && strpos($node->body, '<!--break-->') === 0)) {
-      $preview_trimmed_version = TRUE;
-    }
-  }
 
-  if ($preview_trimmed_version) {
+  $trimmed = drupal_render(node_build(clone $node, TRUE));
+  $full .= drupal_render(node_build($node, FALSE));
+
+  // Do we need to preview trimmed version of post as well as full version?
+  if ($trimmed != $full) {
     drupal_set_message(t('The trimmed version of your post shows what your post looks like when promoted to the main page or when exported for syndication.<span class="no-js"> You can insert the delimiter "&lt;!--break--&gt;" (without the quotes) to fine-tune where your post gets split.</span>'));
     $output .= '<h3>' . t('Preview trimmed version') . '</h3>';
-    $output .= drupal_render(node_build(clone $node, TRUE));
+    $output .= $trimmed;
     $output .= '<h3>' . t('Preview full version') . '</h3>';
-    $output .= drupal_render(node_build($node, FALSE));
+    $output .= $full;
   }
   else {
-    $output .= drupal_render(node_build($node, FALSE));
+    $output .= $full;
   }
   $output .= "</div>\n";
 
