Index: modules/comment/comment.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.install,v
retrieving revision 1.48
diff -u -p -r1.48 comment.install
--- modules/comment/comment.install	10 Oct 2009 13:37:10 -0000	1.48
+++ modules/comment/comment.install	13 Oct 2009 02:19:17 -0000
@@ -159,6 +159,26 @@ function comment_update_7007() {
 }
 
 /**
+ * Update preview setting variable to use new constants
+ */
+function comment_update_7008() {
+  foreach (node_type_get_types() as $type => $object) {
+    // There were only two comment modes in the past:
+    // - 1 was 'required' previously, convert into DRUPAL_REQUIRED (2).
+    // - 0 was 'optional' previously, convert into DRUPAL_OPTIONAL (1).
+    $original_preview = variable_get('comment_preview_' . $type, 1);
+    if ($original_preview) {
+      $preview = DRUPAL_REQUIRED;
+    }
+    else {
+      $preview = DRUPAL_OPTIONAL;
+    }
+    variable_set('comment_preview_' . $type, $preview);
+  }
+  return array();
+}
+
+/**
  * @} End of "defgroup updates-6.x-to-7.x"
  * The next series of updates should start at 8000.
  */
Index: modules/comment/comment.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.module,v
retrieving revision 1.783
diff -u -p -r1.783 comment.module
--- modules/comment/comment.module	10 Oct 2009 21:39:02 -0000	1.783
+++ modules/comment/comment.module	13 Oct 2009 02:31:50 -0000
@@ -71,16 +71,6 @@ define('COMMENT_NODE_CLOSED', 1);
 define('COMMENT_NODE_OPEN', 2);
 
 /**
- * Comment preview is optional.
- */
-define('COMMENT_PREVIEW_OPTIONAL', 0);
-
-/**
- * Comment preview is required.
- */
-define('COMMENT_PREVIEW_REQUIRED', 1);
-
-/**
  * Implement hook_help().
  */
 function comment_help($path, $arg) {
@@ -1007,9 +997,14 @@ function comment_form_node_type_form_alt
       '#default_value' => variable_get('comment_form_location_' . $form['#node_type']->type, COMMENT_FORM_BELOW),
     );
     $form['comment']['comment_preview'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Require preview'),
-      '#default_value' => variable_get('comment_preview_' . $form['#node_type']->type, COMMENT_PREVIEW_OPTIONAL),
+      '#type' => 'radios',
+      '#title' => t('Preview comment'),
+      '#default_value' => variable_get('comment_preview_' . $form['#node_type']->type, DRUPAL_OPTIONAL),
+      '#options' => array(
+        DRUPAL_DISABLED => t('Disabled'),
+        DRUPAL_OPTIONAL => t('Optional'),
+        DRUPAL_REQUIRED => t('Required'),
+      ),
     );
   }
 }
@@ -1864,16 +1859,16 @@ function comment_form($form, &$form_stat
   // already previewing the submission. However, if there are form errors,
   // we hide the save button no matter what, so that optional form elements
   // (e.g., captchas) can be updated.
-  if (!form_get_errors() && ((variable_get('comment_preview_' . $node->type, COMMENT_PREVIEW_OPTIONAL) == COMMENT_PREVIEW_OPTIONAL) || ($op == t('Preview')) || ($op == t('Save')))) {
-    $form['submit'] = array(
-      '#type' => 'submit',
-      '#value' => t('Save'),
-      '#weight' => 19,
-    );
-  }
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Save'),
+    '#access' => variable_get('comment_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_REQUIRED || (!form_get_errors() && isset($form_state['comment_preview'])),
+    '#weight' => 19,
+  );
   $form['preview'] = array(
     '#type' => 'submit',
     '#value' => t('Preview'),
+    '#access' => (variable_get('comment_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_DISABLED),
     '#weight' => 20,
     '#submit' => array('comment_form_build_preview'),
   );
Index: modules/comment/comment.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/comment/comment.test,v
retrieving revision 1.47
diff -u -p -r1.47 comment.test
--- modules/comment/comment.test	8 Oct 2009 08:16:54 -0000	1.47
+++ modules/comment/comment.test	13 Oct 2009 02:19:17 -0000
@@ -18,29 +18,51 @@ class CommentHelperCase extends DrupalWe
    * Post comment.
    *
    * @param object $node Node to post comment on.
-   * @param string $subject Comment subject.
    * @param string $comment Comment body.
-   * @param boolean $preview Should preview be required.
+   * @param string $subject Comment subject.
    * @param mixed $contact Set to NULL for no contact info, TRUE to ignore success checking, and array of values to set contact info.
    */
-  function postComment($node, $subject, $comment, $preview = FALSE, $contact = NULL) {
+  function postComment($node, $comment, $subject = '', $contact = NULL) {
     $edit = array();
-    $edit['subject'] = $subject;
     $edit['comment'] = $comment;
 
-    if ($contact !== NULL && is_array($contact)) {
-      $edit += $contact;
-    }
+    $preview_mode = variable_get('comment_preview_article', DRUPAL_OPTIONAL);
+    $subject_mode = variable_get('comment_subject_field_article', 1);
 
+    // Must get the page before we test for fields.
     if ($node !== NULL) {
       $this->drupalGet('comment/reply/' . $node->nid);
     }
 
-    if ($preview) {
-      $this->assertNoFieldByName('op', t('Save'), t('Save button not found.')); // Preview required so no save button should be found.
-      $this->drupalPost(NULL, $edit, t('Preview'));
+    if ($subject_mode == TRUE) {
+      $edit['subject'] = $subject;
+    }
+    else {
+      $this->assertNoFieldByName('subject', '', t('Subject field not found.'));
+    }
+
+    if ($contact !== NULL && is_array($contact)) {
+      $edit += $contact;
+    }
+    switch ($preview_mode) {
+      case DRUPAL_REQUIRED:
+        // Preview required so no save button should be found.
+        $this->assertNoFieldByName('op', t('Save'), t('Save button not found.'));
+        $this->drupalPost(NULL, $edit, t('Preview'));
+        // Don't break here so that we can test post-preview field presence and
+        // function below.
+      case DRUPAL_OPTIONAL:
+        $this->assertFieldByName('op', t('Preview'), t('Preview button found.'));
+        $this->assertFieldByName('op', t('Save'), t('Save button found.'));
+        $this->drupalPost(NULL, $edit, t('Save'));
+        break;
+
+      case DRUPAL_DISABLED:
+        $this->assertNoFieldByName('op', t('Preview'), t('Preview button not found.'));
+        $this->assertFieldByName('op', t('Save'), t('Save button found.'));
+        $this->drupalPost(NULL, $edit, t('Save'));
+        break;
     }
-    $this->drupalPost(NULL, $edit, t('Save'));
     $match = array();
     // Get comment ID
     preg_match('/#comment-([0-9]+)/', $this->getURL(), $match);
@@ -106,11 +128,24 @@ class CommentHelperCase extends DrupalWe
   /**
    * Set comment preview setting.
    *
-   * @param boolean $required
+   * @param int $mode
    *   Preview value.
    */
-  function setCommentPreview($required) {
-    $this->setCommentSettings('comment_preview', ($required ? '1' : '0'), 'Comment preview ' . ($required ? 'required' : 'optional') . '.');
+  function setCommentPreview($mode) {
+    switch ($mode) {
+      case DRUPAL_DISABLED:
+        $mode_text = 'disabled';
+        break;
+
+      case DRUPAL_OPTIONAL:
+        $mode_text = 'optional';
+        break;
+
+      case DRUPAL_REQUIRED:
+        $mode_text = 'required';
+        break;
+    }
+    $this->setCommentSettings('comment_preview', $mode, 'Comment preview ' . $mode_text . '.');
   }
 
   /**
@@ -221,31 +256,33 @@ class CommentInterfaceTest extends Comme
    * Test comment interface.
    */
   function testCommentInterface() {
-    // Set comments to not have subject.
+    // Set comments to have subject and preview disabled.
     $this->drupalLogin($this->admin_user);
-    $this->setCommentPreview(TRUE);
+    $this->setCommentPreview(DRUPAL_DISABLED);
     $this->setCommentForm(TRUE);
     $this->setCommentSubject(FALSE);
     $this->setCommentSettings('comment_default_mode', COMMENT_MODE_THREADED, t('Comment paging changed.'));
     $this->drupalLogout();
 
-    // Post comment without subject.
+    // Post comment #1 without subject or preview.
     $this->drupalLogin($this->web_user);
-    $this->drupalGet('comment/reply/' . $this->node->nid);
-    $this->assertNoFieldByName('subject', '', t('Subject field not found.'));
+    $comment_text = $this->randomName();
+    $comment = $this->postComment($this->node, $comment_text);
+    $comment_loaded = comment_load($comment->id);
+    $this->assertTrue($this->commentExists($comment), t('Comment found.'));
 
     // Set comments to have subject and preview to required.
     $this->drupalLogout();
     $this->drupalLogin($this->admin_user);
     $this->setCommentSubject(TRUE);
-    $this->setCommentPreview(TRUE);
+    $this->setCommentPreview(DRUPAL_REQUIRED);
     $this->drupalLogout();
 
-    // Create comment that requires preview.
+    // Create comment #2 that allows subject and requires preview.
     $this->drupalLogin($this->web_user);
     $subject_text = $this->randomName();
     $comment_text = $this->randomName();
-    $comment = $this->postComment($this->node, $subject_text, $comment_text, TRUE);
+    $comment = $this->postComment($this->node, $comment_text, $subject_text, TRUE);
     $comment_loaded = comment_load($comment->id);
     $this->assertTrue($this->commentExists($comment), t('Comment found.'));
 
@@ -254,17 +291,26 @@ class CommentInterfaceTest extends Comme
     $this->assertText($subject_text, t('Individual comment subject found.'));
     $this->assertText($comment_text, t('Individual comment body found.'));
 
-    // Reply to comment without a subject.
+    // Set comments to have subject and preview to optional.
+    $this->drupalLogout();
+    $this->drupalLogin($this->admin_user);
+    $this->setCommentSubject(TRUE);
+    $this->setCommentPreview(DRUPAL_OPTIONAL);
+    $this->drupalLogout();
+
+    // Reply to comment #2 creating comment #3 with optional preview and no
+    // subject though field enabled.
+    $this->drupalLogin($this->web_user);
     $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
     $this->assertText($subject_text, t('Individual comment-reply subject found.'));
     $this->assertText($comment_text, t('Individual comment-reply body found.'));
-    $reply = $this->postComment(NULL, '', $this->randomName(), TRUE);
+    $reply = $this->postComment(NULL, $this->randomName(), '', TRUE);
     $reply_loaded = comment_load($reply->id);
     $this->assertTrue($this->commentExists($reply, TRUE), t('Reply found.'));
     $this->assertEqual($comment->id, $reply_loaded->pid, t('Pid of a reply to a comment is set correctly.'));
     $this->assertEqual(rtrim($comment_loaded->thread, '/') . '.00/', $reply_loaded->thread, t('Thread of reply grows correctly.'));
 
-    // Second reply to comment
+    // Second reply to comment #3 creating comment #4.
     $this->drupalGet('comment/reply/' . $this->node->nid . '/' . $comment->id);
     $this->assertText($subject_text, t('Individual comment-reply subject found.'));
     $this->assertText($comment_text, t('Individual comment-reply body found.'));
@@ -280,7 +326,7 @@ class CommentInterfaceTest extends Comme
 
     // Correct link count
     $this->drupalGet('node');
-    $this->assertRaw('3 comments', t('Link to the 3 comments exist.'));
+    $this->assertRaw('4 comments', t('Link to the 4 comments exist.'));
 
     // Confirm a new comment is posted to the correct page.
     $this->setCommentsPerPage(2);
@@ -469,12 +515,12 @@ class CommentAnonymous extends CommentHe
     $this->drupalGet('comment/reply/' . $this->node->nid);
     $this->assertTrue($this->commentContactInfoAvailable(), t('Contact information available.'));
 
-    $anonymous_comment3 = $this->postComment($this->node, $this->randomName(), $this->randomName(), FALSE, TRUE);
+    $anonymous_comment3 = $this->postComment($this->node, $this->randomName(), $this->randomName(), TRUE);
     $this->assertText(t('E-mail field is required.'), t('E-mail required.')); // Name should have 'Anonymous' for value by default.
     $this->assertFalse($this->commentExists($anonymous_comment3), t('Anonymous comment with contact info (required) not found.'));
 
     // Post comment with contact info (required).
-    $anonymous_comment3 = $this->postComment($this->node, $this->randomName(), $this->randomName(), FALSE, array('mail' => 'tester@simpletest.org'));
+    $anonymous_comment3 = $this->postComment($this->node, $this->randomName(), $this->randomName(), array('mail' => 'tester@simpletest.org'));
     $this->assertTrue($this->commentExists($anonymous_comment3), t('Anonymous comment with contact info (required) found.'));
 
     // Unpublish comment.
@@ -556,9 +602,9 @@ class CommentPagerTest extends CommentHe
     // Create a node and three comments.
     $node = $this->drupalCreateNode(array('type' => 'article', 'promote' => 1));
     $comments = array();
-    $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), FALSE, TRUE);
-    $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), FALSE, TRUE);
-    $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), FALSE, TRUE);
+    $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
+    $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
+    $comments[] = $this->postComment($node, $this->randomName(), $this->randomName(), TRUE);
 
     $this->setCommentSettings('comment_default_mode', COMMENT_MODE_FLAT, t('Comment paging changed.'));
 
@@ -590,7 +636,7 @@ class CommentPagerTest extends CommentHe
     $replies = array();
     $oldest_comment = reset($comments);
     $this->drupalGet('comment/reply/' . $node->nid . '/' . $oldest_comment->id);
-    $reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), FALSE, TRUE);
+    $reply = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
 
     $this->setCommentsPerPage(2);
     // We are still in flat view - the replies should not be on the first page,
@@ -608,7 +654,7 @@ class CommentPagerTest extends CommentHe
 
     // If (# replies > # comments per page) in threaded expanded view,
     // the overage should be bumped.
-    $reply2 = $this->postComment(NULL, $this->randomName(), $this->randomName(), FALSE, TRUE);
+    $reply2 = $this->postComment(NULL, $this->randomName(), $this->randomName(), TRUE);
     $this->drupalGet('node/' . $node->nid, array('query' => array('page' => 0)));
     $this->assertFalse($this->commentExists($reply2, TRUE), t('In threaded mode where # replies > # comments per page, the newest reply does not appear on page 1.'));
 
@@ -642,7 +688,7 @@ class CommentApprovalTest extends Commen
     // Post anonymous comment without contact info.
     $subject = $this->randomName();
     $body = $this->randomName();
-    $this->postComment($this->node, $subject, $body, FALSE, TRUE); // Set $contact to true so that it won't check for id and message.
+    $this->postComment($this->node, $body, $subject, TRUE); // Set $contact to true so that it won't check for id and message.
     $this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), t('Comment requires approval.'));
 
     // Get unapproved comment id.
@@ -679,7 +725,7 @@ class CommentApprovalTest extends Commen
     // Post anonymous comment without contact info.
     $subject = $this->randomName();
     $body = $this->randomName();
-    $this->postComment($this->node, $subject, $body, FALSE, TRUE); // Set $contact to true so that it won't check for id and message.
+    $this->postComment($this->node, $body, $subject, TRUE); // Set $contact to true so that it won't check for id and message.
     $this->assertText(t('Your comment has been queued for review by site administrators and will be published after approval.'), t('Comment requires approval.'));
 
     // Get unapproved comment id.
@@ -737,7 +783,7 @@ class CommentBlockFunctionalTest extends
     // Add some test comments, one without a subject.
     $comment1 = $this->postComment($this->node, $this->randomName(), $this->randomName());
     $comment2 = $this->postComment($this->node, $this->randomName(), $this->randomName());
-    $comment3 = $this->postComment($this->node, '', $this->randomName());
+    $comment3 = $this->postComment($this->node, $this->randomName());
 
     // Test that a user without the 'access comments' permission can not see the block.
     $this->drupalLogout();
Index: modules/node/content_types.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/content_types.inc,v
retrieving revision 1.96
diff -u -p -r1.96 content_types.inc
--- modules/node/content_types.inc	9 Oct 2009 01:00:00 -0000	1.96
+++ modules/node/content_types.inc	13 Oct 2009 02:24:49 -0000
@@ -160,7 +160,7 @@ function node_type_form($form, &$form_st
       DRUPAL_OPTIONAL => t('Optional'),
       DRUPAL_REQUIRED => t('Required'),
     ),
-    );
+  );
   $form['submission']['help']  = array(
     '#type' => 'textarea',
     '#title' => t('Explanation or submission guidelines'),
Index: modules/node/node.pages.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.pages.inc,v
retrieving revision 1.87
diff -u -p -r1.87 node.pages.inc
--- modules/node/node.pages.inc	11 Oct 2009 03:07:18 -0000	1.87
+++ modules/node/node.pages.inc	13 Oct 2009 02:28:07 -0000
@@ -263,13 +263,13 @@ function node_form($form, &$form_state, 
   $form['buttons']['#weight'] = 100;
   $form['buttons']['submit'] = array(
     '#type' => 'submit',
-    '#access' => variable_get('node_preview_' . $node->type, 1) != DRUPAL_REQUIRED || (!form_get_errors() && isset($form_state['node_preview'])),
+    '#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_REQUIRED || (!form_get_errors() && isset($form_state['node_preview'])),
     '#value' => t('Save'),
     '#weight' => 5,
     '#submit' => array('node_form_submit'),
   );
   $form['buttons']['preview'] = array(
-    '#access' => variable_get('node_preview_' . $node->type, 1) != DRUPAL_DISABLED,
+    '#access' => variable_get('node_preview_' . $node->type, DRUPAL_OPTIONAL) != DRUPAL_DISABLED,
     '#type' => 'submit',
     '#value' => t('Preview'),
     '#weight' => 10,
Index: modules/search/search.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/search/search.test,v
retrieving revision 1.38
diff -u -p -r1.38 search.test
--- modules/search/search.test	11 Oct 2009 03:07:19 -0000	1.38
+++ modules/search/search.test	13 Oct 2009 02:19:17 -0000
@@ -468,7 +468,7 @@ class SearchCommentTestCase extends Drup
   function testSearchResultsComment() {
     $comment_body = $this->randomName(5);
 
-    variable_set('comment_preview_article', COMMENT_PREVIEW_OPTIONAL);
+    variable_set('comment_preview_article', DRUPAL_OPTIONAL);
     // Enable check_plain() for 'Filtered HTML' text format.
     $edit = array(
       'filters[filter_html_escape][status]' => 1,
Index: modules/user/user.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/user/user.test,v
retrieving revision 1.64
diff -u -p -r1.64 user.test
--- modules/user/user.test	12 Oct 2009 18:37:31 -0000	1.64
+++ modules/user/user.test	13 Oct 2009 02:19:43 -0000
@@ -525,7 +525,7 @@ class UserCancelTestCase extends DrupalW
 
     // Create comment.
     module_load_include('test', 'comment');
-    $comment = CommentHelperCase::postComment($node, '', $this->randomName(32), FALSE, TRUE);
+    $comment = CommentHelperCase::postComment($node, $this->randomName(32), '', TRUE);
     $this->assertTrue(comment_load($comment->id), t('Comment found.'));
 
     // Create a node with two revisions, the initial one belonging to the
