### Eclipse Workspace Patch 1.0
#P drupal_test_7
Index: modules/comment/comment.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.admin.inc,v
retrieving revision 1.26
diff -u -r1.26 comment.admin.inc
--- modules/comment/comment.admin.inc	1 Jul 2009 20:39:20 -0000	1.26
+++ modules/comment/comment.admin.inc	16 Jul 2009 02:28:25 -0000
@@ -201,7 +201,7 @@
     foreach ($form_state['values']['comments'] as $cid => $value) {
       $comment = comment_load($cid);
       // Perform the actual comment deletion.
-      _comment_delete_thread($comment);
+      comment_delete($comment->cid);
       _comment_update_node_statistics($comment->nid);
     }
     cache_clear_all();
@@ -216,7 +216,7 @@
  * @param $cid
  *   The comment to be deleted.
  */
-function comment_delete($cid = NULL) {
+function comment_delete_page($cid = NULL) {
   $comment = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comment} c INNER JOIN {users} u ON u.uid = c.uid WHERE c.cid = :cid', array(':cid' => $cid))->fetch();
   $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
   $output = '';
@@ -257,38 +257,10 @@
   drupal_set_message(t('The comment and all its replies have been deleted.'));
   $comment = $form['#comment'];
   // Delete the comment and its replies.
-  _comment_delete_thread($comment);
+  comment_delete($comment->cid);
   _comment_update_node_statistics($comment->nid);
   // Clear the cache so an anonymous user sees that his comment was deleted.
   cache_clear_all();
 
   $form_state['redirect'] = "node/$comment->nid";
 }
-
-/**
- * Perform the actual deletion of a comment and all its replies.
- *
- * @param $comment
- *   An associative array describing the comment to be deleted.
- */
-function _comment_delete_thread($comment) {
-  if (!is_object($comment) || !is_numeric($comment->cid)) {
-    watchdog('content', 'Cannot delete non-existent comment.', array(), WATCHDOG_WARNING);
-
-    return;
-  }
-
-  // Delete the comment.
-  db_delete('comment')
-    ->condition('cid', $comment->cid)
-    ->execute();
-  watchdog('content', 'Comment: deleted %subject.', array('%subject' => $comment->subject));
-  module_invoke_all('comment_delete', $comment);
-
-  // Delete the comment's replies.
-  $result = db_query('SELECT c.*, u.name AS registered_name, u.uid FROM {comment} c INNER JOIN {users} u ON u.uid = c.uid WHERE pid = :cid', array(':cid' => $comment->cid));
-  foreach ($result as $comment) {
-    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-    _comment_delete_thread($comment);
-  }
-}
Index: modules/comment/comment.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.pages.inc,v
retrieving revision 1.21
diff -u -r1.21 comment.pages.inc
--- modules/comment/comment.pages.inc	1 Jul 2009 20:39:20 -0000	1.21
+++ modules/comment/comment.pages.inc	16 Jul 2009 02:28:26 -0000
@@ -19,6 +19,7 @@
   $comment = drupal_unpack($comment);
   $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
 
+  field_attach_load('comment', array($comment->cid => $comment));
   if (comment_access('edit', $comment)) {
     return theme('comment_form_box', (array)$comment);
   }
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.740
diff -u -r1.740 comment.module
--- modules/comment/comment.module	10 Jul 2009 05:50:08 -0000	1.740
+++ modules/comment/comment.module	16 Jul 2009 02:28:26 -0000
@@ -164,7 +164,7 @@
   );
   $items['comment/delete'] = array(
     'title' => 'Delete comment',
-    'page callback' => 'comment_delete',
+    'page callback' => 'comment_delete_page',
     'access arguments' => array('administer comments'),
     'type' => MENU_CALLBACK,
   );
@@ -201,6 +201,32 @@
 }
 
 /**
+ * Implement hook_fieldable_info().
+ */
+function comment_fieldable_info() {
+  $return = array(
+    'comment' => array(
+      'label' => t('Comment'),
+      'object keys' => array(
+        'id' => 'cid',
+        'bundle' => 'node_type',
+      ),
+      'bundle keys' => array(
+        'bundle' => 'type',
+      ),
+      'bundles' => array(),
+    ),
+  );
+  foreach (node_type_get_names() as $type => $name) {
+    $return['comment']['bundles']['comment_node_' . $type] = array(
+      'label' => $name,
+    );
+  }
+  return $return;
+}
+
+
+/**
  * Implement hook_node_type().
  */
 function comment_node_type($op, $info) {
@@ -215,7 +241,18 @@
   );
 
   switch ($op) {
+    case 'insert':
+      field_attach_create_bundle('comment_node_' . $info->type);
+      break;
+
+    case 'update':
+      if (!empty($info->old_type) && $info->type != $info->old_type) {
+        field_attach_rename_bundle('comment_node_' . $info->old_type, 'comment_node_' . $info->type);
+      }
+      break;
+
     case 'delete':
+       field_attach_delete_bundle('comment_node_' . $info->type);
       foreach ($settings as $setting) {
         variable_del($setting . '_' . $info->type);
       }
@@ -728,9 +765,10 @@
  * Implement hook_node_delete().
  */
 function comment_node_delete($node) {
-  db_delete('comment')
-    ->condition('nid', $node->nid)
-    ->execute();
+  $cids = db_query('SELECT cid FROM {comment} WHERE nid = :nid', array(':nid' => $node->nid))->fetchCol();
+  foreach ($cids as $cid) {
+    comment_delete($cid);
+  }
   db_delete('node_comment_statistics')
     ->condition('nid', $node->nid)
     ->execute();
@@ -805,7 +843,7 @@
       foreach ($result as $cid) {
         $comment = comment_load($cid);
         // Delete the comment and its replies.
-        _comment_delete_thread($comment);
+        comment_delete($comment->cid);
         _comment_update_node_statistics($comment->nid);
       }
       break;
@@ -855,6 +893,9 @@
       $comment->$key = $default;
     }
   }
+  $node = node_load($comment->nid);
+  $comment->node_type = 'comment_node_' . $node->type;
+  field_attach_presave('comment', $comment);
   if ($comment->cid) {
     // Update the comment in the database.
     db_update('comment')
@@ -871,6 +912,7 @@
       ))
       ->condition('cid', $comment->cid)
       ->execute();
+    field_attach_update('comment', $comment);
     // Allow modules to respond to the updating of a comment.
     module_invoke_all('comment_update', $comment);
     // Add an entry to the watchdog log.
@@ -948,6 +990,8 @@
     // saved node to be propagated to the slave.
     db_ignore_slave();
 
+    field_attach_insert('comment', $comment);
+
     // Tell the other modules a new comment has been submitted.
     module_invoke_all('comment_insert', $comment);
     // Add an entry to the watchdog log.
@@ -963,6 +1007,32 @@
 }
 
 /**
+ * Delete a comment and all its replies.
+ *
+ * @param $comment
+ *   The comment to delete.
+ */
+function comment_delete($cid) {
+  $comment = comment_load($cid);
+  if ($comment) {
+
+    // Delete the comment.
+    db_delete('comment')
+      ->condition('cid', $comment->cid)
+      ->execute();
+    watchdog('content', 'Comment: deleted %subject.', array('%subject' => $comment->subject));
+    field_attach_delete('comment', $comment);
+    module_invoke_all('comment_delete', $comment);
+
+    // Delete the comment's replies.
+    $result = db_query('SELECT cid FROM {comment} WHERE pid = :cid', array(':cid' => $comment->cid));
+    foreach ($result as $row) {
+      comment_delete($row->cid);
+    }
+  }
+}
+
+/**
  * Implement hook_link().
  */
 function comment_link($type, $object, $build_mode) {
@@ -1268,7 +1338,9 @@
   if ($cids || $conditions) {
     $query = db_select('comment', 'c');
     $query->innerJoin('users', 'u', 'c.uid = u.uid');
+    $query->innerJoin('node', 'n', 'c.nid = n.nid');
     $query->addField('u', 'name', 'registered_name');
+    $query->addField('n', 'type', 'node_type');
     $query
       ->fields('c', array('cid', 'nid', 'pid', 'comment', 'subject', 'format', 'timestamp', 'name', 'mail', 'homepage', 'status', 'thread'))
       ->fields('u', array( 'uid', 'signature', 'picture', 'data', 'status'));
@@ -1287,8 +1359,10 @@
     $comments = $query->execute()->fetchAllAssoc('cid');
   }
 
-  // Invoke hook_comment_load().
   if (!empty($comments)) {
+    // Attach fields.
+    field_attach_load('comment', $comments);
+    // Invoke hook_comment_load().
     module_invoke_all('comment_load', $comments);
   }
   return $comments;
@@ -1303,7 +1377,8 @@
  *   The comment object.
  */
 function comment_load($cid) {
-  return current(comment_load_multiple(array($cid)));
+  $comment = comment_load_multiple(array($cid));
+  return $comment ? $comment[$cid] : FALSE;;
 }
 
 /**
@@ -1432,14 +1507,26 @@
  */
 function comment_form(&$form_state, $edit, $title = NULL) {
   global $user;
+
   $op = isset($_POST['op']) ? $_POST['op'] : '';
   $node = node_load($edit['nid']);
 
   if (!$user->uid && variable_get('comment_anonymous_' . $node->type, COMMENT_ANONYMOUS_MAYNOT_CONTACT) != COMMENT_ANONYMOUS_MAYNOT_CONTACT) {
     drupal_add_js(drupal_get_path('module', 'comment') . '/comment.js');
   }
+
+  // Take into account multi-step rebuilding.
+  if (isset($form_state['comment'])) {
+    $edit = $form_state['comment'] + $edit;
+  }
   $edit += array('name' => '', 'mail' => '', 'homepage' => '');
 
+  $form = array();
+  if (isset($form_state['comment_preview'])) {
+    $form += $form_state['comment_preview'];
+  }
+  // @todo: do we want $comment->in_preview ?
+
   if ($user->uid) {
     if (!empty($edit['cid']) && user_access('administer comments')) {
       if (!empty($edit['author'])) {
@@ -1636,6 +1723,10 @@
     '#type' => 'value',
     '#value' => !empty($edit['uid']) ? $edit['uid'] : 0,
   );
+  $form['node_type'] = array(
+    '#type' => 'value',
+    '#value' => 'comment_node_' . $node->type,
+  );
 
   // Only show the save button if comment previews are optional or if we are
   // already previewing the submission. However, if there are form errors,
@@ -1649,20 +1740,25 @@
     );
   }
   $form['preview'] = array(
-    '#type' => 'button',
+    '#type' => 'submit',
     '#value' => t('Preview'),
     '#weight' => 20,
+    '#submit' => array('comment_form_build_preview'),
   );
   $form['#token'] = 'comment' . $edit['nid'] . (isset($edit['pid']) ? $edit['pid'] : '');
 
-  if ($op == t('Preview')) {
-    $form['#after_build'] = array('comment_form_add_preview');
-  }
-
   if (empty($edit['cid']) && empty($edit['pid'])) {
     $form['#action'] = url('comment/reply/' . $edit['nid']);
   }
 
+  // The non-Javascript handler for fields 'add more' button needs the name of
+  // a builder function.
+  $form['#builder_function'] = 'comment_form_submit_build_comment';
+
+  $comment = (object) $edit;
+  $comment->node_type = 'comment_node_' . $node->type;
+  field_attach_form('comment', $comment, $form, $form_state);
+
   return $form;
 }
 
@@ -1683,25 +1779,24 @@
 }
 
 /**
- * Form builder; Generate and validate a comment preview form.
- *
- * @ingroup forms
+ * Build a preview from submitted form values.
+ */
+function comment_form_build_preview($form, &$form_state) {
+  $comment = comment_form_submit_build_comment($form, $form_state);
+  $form_state['comment_preview'] = comment_preview($comment);
+}
+
+/**
+ * Generate a comment preview.
  */
-function comment_form_add_preview($form, &$form_state) {
+function comment_preview($comment) {
   global $user;
-  $edit = $form_state['values'];
+
   drupal_set_title(t('Preview comment'), PASS_THROUGH);
-  $output = '';
-  $node = node_load($edit['nid']);
 
-  // Invoke full validation for the form, to protect against cross site
-  // request forgeries (CSRF) and setting arbitrary values for fields such as
-  // the text format. Preview the comment only when form validation does not
-  // set any errors.
-  drupal_validate_form($form['form_id']['#value'], $form, $form_state);
+  $node = node_load($comment->nid);
+
   if (!form_get_errors()) {
-    _comment_form_submit($edit);
-    $comment = (object)$edit;
     $comment->format = $comment->comment_format;
 
     // Attach the user and time information.
@@ -1721,7 +1816,10 @@
     }
 
     $comment->timestamp = !empty($edit['timestamp']) ? $edit['timestamp'] : REQUEST_TIME;
-    $output .= theme('comment_view', $comment, $node);
+    $output = theme('comment_view', $comment, $node);
+  }
+  else {
+    $output = '';
   }
 
   $form['comment_preview'] = array(
@@ -1731,25 +1829,23 @@
     '#suffix' => '</div>',
   );
 
-  $output = ''; // Isn't this line a duplication of the first $output above?
-
-  if ($edit['pid']) {
-    $comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array(
-      ':cid' => $edit['pid'],
+  if ($comment->pid) {
+    $parent_comment = db_query('SELECT c.*, u.uid, u.name AS registered_name, u.signature, u.picture, u.data FROM {comment} c INNER JOIN {users} u ON c.uid = u.uid WHERE c.cid = :cid AND c.status = :status', array(
+      ':cid' => $comment->pid,
       ':status' => COMMENT_PUBLISHED,
       ))->fetchObject();
-    $comment = drupal_unpack($comment);
-    $comment->name = $comment->uid ? $comment->registered_name : $comment->name;
-    $output .= theme('comment_view', $comment, $node);
+    $parent_comment = drupal_unpack($parent_comment);
+    $parent_comment->name = $parent_comment->uid ? $parent_comment->registered_name : $parent_comment->name;
+    $output_below = theme('comment_view', $parent_comment, $node);
   }
   else {
     $suffix = empty($form['#suffix']) ? '' : $form['#suffix'];
     $form['#suffix'] = $suffix . drupal_render(node_build($node));
-    $edit['pid'] = 0;
+    $output_below = '';
   }
 
   $form['comment_preview_below'] = array(
-    '#markup' => $output,
+    '#markup' => $output_below,
     '#weight' => 100,
   );
 
@@ -1761,6 +1857,11 @@
  */
 function comment_form_validate($form, &$form_state) {
   global $user;
+  $comment = (object) $form_state['values'];
+  $node = node_load($comment->nid);
+  $comment->node_type = 'comment_node_' . $node->type;
+  field_attach_form_validate('comment', $comment, $form, $form_state);
+
   if ($user->uid === 0) {
     foreach (array('name', 'homepage', 'mail') as $field) {
       // Set cookie for 365 days.
@@ -1853,14 +1954,26 @@
 }
 
 /**
+ * Build a comment by processing form values and prepare for a form rebuild.
+ */
+function comment_form_submit_build_comment($form, &$form_state) {
+  _comment_form_submit($form_state['values']);
+  $comment = (object) $form_state['values'];
+
+  field_attach_submit('comment', $comment, $form, $form_state);
+
+  $form_state['comment'] = (array)$comment;
+  $form_state['rebuild'] = TRUE;
+  return $comment;
+}
+
+/**
  * Process comment form submissions; prepare the comment, store it, and set a redirection target.
  */
 function comment_form_submit($form, &$form_state) {
-  $edit = $form_state['values'];
-  $node = node_load($edit['nid']);
-  _comment_form_submit($edit);
+  $comment = comment_form_submit_build_comment($form, $form_state);
+  $node = node_load($comment->nid);
   if (user_access('post comments') && (user_access('administer comments') || $node->comment == COMMENT_NODE_OPEN)) {
-    $comment = (object) $edit;
     comment_save($comment);
     // Explain the approval queue if necessary.
     if ($comment->status == COMMENT_NOT_PUBLISHED) {
@@ -1881,6 +1994,7 @@
   }
 
   // Redirect the user to the node they're commenting on.
+  unset($form_state['rebuild']);
   $form_state['redirect'] = $redirect;
 }
 
Index: modules/field/field.form.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/field/field.form.inc,v
retrieving revision 1.11
diff -u -r1.11 field.form.inc
--- modules/field/field.form.inc	11 Jul 2009 00:56:45 -0000	1.11
+++ modules/field/field.form.inc	16 Jul 2009 02:28:26 -0000
@@ -36,8 +36,6 @@
     'field' => $field,
     'instance' => $instance,
   );
-  // TODO : why do we need this ?
-  $form['#cache'] = FALSE;
 
   // Populate widgets with default values if we're creating a new object.
   if (empty($items) && empty($id) && !empty($instance['default_value_function'])) {
@@ -183,8 +181,6 @@
 
     // Add AHAH add more button, if not working with a programmed form.
     if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED && empty($form_state['programmed'])) {
-      // Make sure the form is cached so ahah can work.
-      $form['#cache'] = TRUE;
       $bundle_name_url_str = str_replace('_', '-', $instance['bundle']);
       $field_name_url_str = str_replace('_', '-', $field_name);
 
