diff --git a/comment_goodness.module b/comment_goodness.module
index dcf1c2f..4a5c104 100644
--- a/comment_goodness.module
+++ b/comment_goodness.module
@@ -2,8 +2,8 @@
 
 /**
  * @file
- *
  * Comment goodness provides newest to oldest comment sorting
+ * and delete/unpublish action fro comment owner and admin
  *
  * This module extends the sort_comments module by blackice78
  * @see http://drupal.org/project/sort_comments
@@ -12,10 +12,14 @@
 /**
  *  Constants
  */
-define('comment_goodness_OLDER_FIRST', 1); // default
-define('comment_goodness_NEWER_FIRST', 2);
-define('comment_goodness_COMMENT_SECTION_LABEL', t('Comments'));
-define('comment_goodness_COMMENT_FORM_LABEL', t('Post new comment'));
+// Default comment sort order.
+define('COMMENT_GOODNESS_OLDER_FIRST', 1);
+define('COMMENT_GOODNESS_NEWER_FIRST', 2);
+define('COMMENT_GOODNESS_COMMENT_SECTION_LABEL', t('Comments'));
+define('COMMENT_GOODNESS_COMMENT_FORM_LABEL', t('Post new comment'));
+define('COMMENT_GOODNESS_DELETE_ACTION_NONE', 0);
+define('COMMENT_GOODNESS_DELETE_ACTION_ERASE', 1);
+define('COMMENT_GOODNESS_DELETE_ACTION_UNPUBLISH', 2);
 
 /**
  * Implements hook_form_FORM_ID_alter().
@@ -25,22 +29,57 @@ define('comment_goodness_COMMENT_FORM_LABEL', t('Post new comment'));
 function comment_goodness_form_node_type_form_alter(&$form, $form_state) {
   $form['comment']['comment_default_sorting'] = array(
     '#title' => t('Sort order'),
-    '#type' => 'select',
-    '#options' => array(1 => t('Older first'),
-                       2 => t('Newer first')),
-    '#default_value' => variable_get('comment_default_sorting_' . $form['#node_type']->type, comment_goodness_OLDER_FIRST),
+    '#type' => 'radios',
+    '#options' => array(
+      1 => t('Older first'),
+      2 => t('Newer first'),
+    ),
+    '#default_value' => variable_get('comment_default_sorting_' . $form['#node_type']->type, COMMENT_GOODNESS_OLDER_FIRST),
   );
   $form['comment']['comment_section_label'] = array(
     '#title' => t('Comment section label'),
     '#type' => 'textfield',
-    '#default_value' => variable_get('comment_section_label_' . $form['#node_type']->type, comment_goodness_COMMENT_SECTION_LABEL),
+    '#default_value' => variable_get('comment_section_label_' . $form['#node_type']->type, COMMENT_GOODNESS_COMMENT_SECTION_LABEL),
   );
   $form['comment']['comment_form_label'] = array(
     '#title' => t('New comment form label'),
     '#type' => 'textfield',
-    '#default_value' => variable_get('comment_form_label_' . $form['#node_type']->type, comment_goodness_COMMENT_FORM_LABEL),
+    '#default_value' => variable_get('comment_form_label_' . $form['#node_type']->type, COMMENT_GOODNESS_COMMENT_FORM_LABEL),
+  );
+  $form['comment']['comment_delete'] = array(
+    '#title' => t('Delete actions'),
+    '#description'=> t('What actions will be performed when comment owner or admin clicks on comment delete link.<br />Select "None" to hide delete link.'),
+    '#type' => 'fieldset',
+  );
+  $form['comment']['comment_delete']['comment_delete_owner_action'] = array(
+    '#title' => t('Delete action for comment owner'),
+    '#description'=> t('Don\'t forget to give "Delete own comments" permission to users.'),
+    '#type' => 'radios',
+    '#options' => array(
+      COMMENT_GOODNESS_DELETE_ACTION_NONE => t('None') . ' <em>' . t('(default)') . '</em>',
+      COMMENT_GOODNESS_DELETE_ACTION_ERASE => t('Delete'),
+      COMMENT_GOODNESS_DELETE_ACTION_UNPUBLISH => t('Unpublish'),
+    ),
+    '#default_value' => variable_get('comment_delete_owner_action_' . $form['#node_type']->type, COMMENT_GOODNESS_DELETE_ACTION_NONE),
   );
+  $form['comment']['comment_delete']['comment_delete_admin_action'] = array(
+    '#title' => t('Delete action for admin'),
+    '#type' => 'radios',
+    '#options' => array(
+      COMMENT_GOODNESS_DELETE_ACTION_ERASE => t('Delete') . ' <em>' . t('(default)') . '</em>',
+      COMMENT_GOODNESS_DELETE_ACTION_UNPUBLISH => t('Unpublish'),
+    ),
+    '#default_value' => variable_get('comment_delete_admin_action_' . $form['#node_type']->type, COMMENT_GOODNESS_DELETE_ACTION_ERASE),
+  );
+  $form['comment']['comment_delete']['comment_hide_unpublish'] = array(
+    '#title' => t('Hide unpublished comments in thread for admin'),
+    '#description'=> t('By default unpublished comments are shown to admin.<br />This config allows to hide them in comment thread.'),
+    '#type' => 'checkbox',
+    '#default_value' => variable_get('comment_hide_unpublish_' . $form['#node_type']->type, FALSE),
+  );
+
 }
+
 /**
  * Implements hook_query_TAG_alter().
  *
@@ -72,13 +111,20 @@ function comment_goodness_form_node_type_form_alter(&$form, $form_state) {
  * 1.1.1
  *
  */
-function comment_goodness_query_comment_filter_alter(QueryAlterableInterface $query){
+function comment_goodness_query_comment_filter_alter(QueryAlterableInterface $query) {
   if (($node = $query->getMetaData('node')) && (get_class($query) == 'PagerDefault')) {
+    // By default unpublished comments are shown to admin.
+    // This config allows to hide them in comment thread.
+    if (variable_get('comment_hide_unpublish_' . $node->type, FALSE) && user_access('administer comments')) {
+      $query->condition('c.status', COMMENT_PUBLISHED);
+      $query->getCountQuery()->condition('c.status', COMMENT_PUBLISHED);
+    }
+
     // Get the configured default sort ordering for this node type.
-    $sort = variable_get('comment_default_sorting_' . $node->type, comment_goodness_OLDER_FIRST);
+    $sort = variable_get('comment_default_sorting_' . $node->type, COMMENT_GOODNESS_OLDER_FIRST);
     // The default ordering is ASC (older on top). If the configured sorting is
     // newer on top, change the ordering to DESC.
-    if ($sort == comment_goodness_NEWER_FIRST) {
+    if ($sort == COMMENT_GOODNESS_NEWER_FIRST) {
       $orderby = &$query->getOrderBy();
       $expressions = &$query->getExpressions();
       // Sorting for threaded comments.
@@ -137,7 +183,7 @@ function comment_goodness_menu_alter(&$items) {
  * Override the core comment-wrapper template with the template in this module.
  */
 function comment_goodness_theme_registry_alter(&$theme_registry) {
-  if(isset($theme_registry['comment_wrapper'])) {
+  if (isset($theme_registry['comment_wrapper'])) {
     $comment_wrapper = $theme_registry['comment_wrapper'];
     // If the current template belongs to the core comment module, replace it.
     if (isset($comment_wrapper['template']) && $comment_wrapper['template'] === 'modules/comment/comment-wrapper') {
@@ -165,7 +211,17 @@ function comment_goodness_permission() {
 function comment_goodness_delete_comment_access($comment) {
   global $user;
 
-  $access = ($user->uid && $user->uid == $comment->uid && $comment->status == COMMENT_PUBLISHED && (user_access('delete own comments') || user_access('administer comments')));
+  // What delete actions are available.
+  $delete_action = _comment_goodness_get_delete_action($comment->node_type);
+
+  if (user_access('administer comments')) {
+    $access = $delete_action;
+  }
+  else {
+    // If comments of this content type can be deleted by owner.
+    $access = $delete_action && ($user->uid && $user->uid == $comment->uid && $comment->status == COMMENT_PUBLISHED && user_access('delete own comments'));
+  }
+
   // Deletion is not allowed if any comment has this comment as a parent.
   return $access && (0 == db_query("SELECT COUNT(cid) FROM {comment} WHERE pid = :cid", array(':cid' => $comment->cid))->fetchField());
 }
@@ -174,8 +230,16 @@ function comment_goodness_delete_comment_access($comment) {
  * Implements hook_comment_view().
  */
 function comment_goodness_comment_view($comment, $view_mode, $langcode) {
-  // We only need to add the delete link if it's not there.
-  if (!isset($comment->content['links']['comment']['#links']['comment-delete']) && comment_goodness_delete_comment_access($comment)) {
+  if (user_access('administer comments')) {
+    // Check delete action for admin.
+    $delete_action = _comment_goodness_get_delete_action($comment->node_type);
+    if ($delete_action == COMMENT_GOODNESS_DELETE_ACTION_UNPUBLISH) {
+      // Chnage default delete action to unpublish.
+      $comment->content['links']['comment']['#links']['comment-delete']['href'] = "comment/$comment->cid/delete-own";
+    }
+  }
+  elseif (comment_goodness_delete_comment_access($comment)) {
+    // Add delete link for comment owner.
     $comment->content['links']['comment']['#links']['comment-delete'] = array(
       'title' => t('delete'),
       'href' => "comment/$comment->cid/delete-own",
@@ -198,14 +262,20 @@ function comment_goodness_confirm_delete($form, &$form_state, $comment) {
     '#type' => 'value',
     '#value' => $comment->cid,
   );
-  return confirm_form(
-    $form,
-    t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject)),
-    'node/' . $comment->nid,
-    t('This action cannot be undone.'),
-    t('Delete'),
-    t('Cancel'),
-    'comment_goodness_confirm_delete');
+
+  $delete_action = _comment_goodness_get_delete_action($comment->node_type);
+  if ($delete_action == COMMENT_GOODNESS_DELETE_ACTION_UNPUBLISH) {
+    $confirm = t('Are you sure you want to unpublish the comment %title?', array('%title' => $comment->subject));
+    $message = t('This action can be undone.');
+    $action  = t('Unpublish');
+  }
+  else {
+    $confirm = t('Are you sure you want to delete the comment %title?', array('%title' => $comment->subject));
+    $message = t('This action cannot be undone.');
+    $action  = t('Delete');
+  }
+
+  return confirm_form($form, $confirm, 'node/' . $comment->nid, $message, $action, t('Cancel'), 'comment_goodness_confirm_delete');
 }
 
 /**
@@ -217,10 +287,35 @@ function comment_goodness_confirm_delete_submit($form, &$form_state) {
   global $user;
 
   $comment = $form['#comment'];
-  // Delete the comment and its replies.
-  comment_delete($comment->cid);
-  drupal_set_message(t('The comment has been deleted.'));
-  watchdog('content', 'User %name (@uid) deleted own comment @cid.', array('%name' => $user->name, '@uid' => $user->uid, '@cid' => $comment->cid));
+  $watchdog = '';
+
+  // Delete the comment and its replies or unpublish it.
+  $delete_action = _comment_goodness_get_delete_action($comment->node_type);
+  switch ($delete_action) {
+    case COMMENT_GOODNESS_DELETE_ACTION_UNPUBLISH:
+      $comment->status = COMMENT_NOT_PUBLISHED;
+      comment_save($comment);
+      drupal_set_message(t('The comment has been unpublished.'));
+      $watchdog = 'User %name (@uid) unpublished %author comment @cid.';
+      break;
+
+    case COMMENT_GOODNESS_DELETE_ACTION_ERASE:
+      comment_delete($comment->cid);
+      drupal_set_message(t('The comment has been deleted.'));
+      $watchdog = 'User %name (@uid) deleted %author comment @cid.';
+      break;
+
+  }
+
+  if ($watchdog) {
+    watchdog('content', $watchdog, array(
+      '%name' => $user->name,
+      '@uid' => $user->uid,
+      '@cid' => $comment->cid,
+      '%name' => ($user->uid == $comment->uid) ? t('own') : $comment->name,
+    ));
+  }
+
   // Clear the cache so an anonymous user sees that his comment was deleted.
   cache_clear_all();
 
@@ -248,7 +343,7 @@ function comment_goodness_form_comment_form_alter(&$form, &$form_state, $form_id
 /**
  * Form submit handler.
  *
- * @see comment_goodness_form_comment_form_alter().
+ * @see comment_goodness_form_comment_form_alter()
  */
 function comment_goodness_form_submit($form, &$form_state) {
   $node = $form['#node'];
@@ -261,7 +356,10 @@ function comment_goodness_form_submit($form, &$form_state) {
       $query['page'] = $page;
     }
     // Redirect to the newly posted comment.
-    $form_state['redirect'] = array('node/' . $node->nid, array('query' => $query, 'fragment' => 'comment-' . $comment->cid));
+    $form_state['redirect'] = array('node/' . $node->nid, array(
+      'query' => $query,
+      'fragment' => 'comment-' . $comment->cid,
+      ));
   }
 }
 
@@ -278,16 +376,16 @@ function comment_goodness_preprocess_comment_wrapper(&$variables) {
   // Bottom placement of the comment form is the Drupal default.
   $variables['comment_form_placement'] = 'bottom';
   // Get the configured default sort ordering for this node type.
-  $sort = variable_get('comment_default_sorting_' . $variables['node']->type, comment_goodness_OLDER_FIRST);
+  $sort = variable_get('comment_default_sorting_' . $variables['node']->type, COMMENT_GOODNESS_OLDER_FIRST);
   // Indicate that the comment form should be rendered above the comments
   // if the sort order is newest to oldest (ASC).
-  if ($sort == comment_goodness_NEWER_FIRST) {
+  if ($sort == COMMENT_GOODNESS_NEWER_FIRST) {
     $variables['comment_form_placement'] = 'top';
   }
-  // Get the section labels
-  $comment_section_label = variable_get('comment_section_label_' . $variables['node']->type, comment_goodness_COMMENT_SECTION_LABEL);
-  $comment_form_label = variable_get('comment_form_label_' . $variables['node']->type, comment_goodness_COMMENT_FORM_LABEL);
-  // Add the labels to the page variables
+  // Get the section labels.
+  $comment_section_label = variable_get('comment_section_label_' . $variables['node']->type, COMMENT_GOODNESS_COMMENT_SECTION_LABEL);
+  $comment_form_label = variable_get('comment_form_label_' . $variables['node']->type, COMMENT_GOODNESS_COMMENT_FORM_LABEL);
+  // Add the labels to the page variables.
   $variables['labels'] = array(
     'section_label' => check_plain($comment_section_label),
     'form_label' => check_plain($comment_form_label),
@@ -300,11 +398,12 @@ function comment_goodness_preprocess_comment_wrapper(&$variables) {
  * Finds the correct page number for a comment taking into account display,
  * paging settings and sort order.
  *
- * @param $cid
+ * @param int $cid
  *   The comment ID.
- * @param $node_type
+ * @param string $node_type
  *   The node type the comment is attached to.
- * @return
+ *
+ * @return int
  *   The page number.
  * @see comment_get_display_page
  */
@@ -325,9 +424,10 @@ function comment_goodness_get_display_page($cid, $node_type) {
  * calculates the page number based on current comment settings and returns
  * the full comment view with the pager set dynamically.
  *
- * @param $cid
+ * @param int $cid
  *   A comment identifier.
- * @return
+ *
+ * @return string
  *   The comment listing set to the page on which the comment appears.
  *
  * @see comment_permalink()
@@ -355,11 +455,12 @@ function comment_goodness_permalink($cid) {
  * Count the number of comments which appear before the comment we want to
  * display, taking into account display settings, threading and sort order.
  *
- * @param $cid
+ * @param int $cid
  *   The comment ID.
- * @param $node_type
+ * @param string $node_type
  *   The node type of the comment's parent.
- * @return
+ *
+ * @return string
  *   The display ordinal for the comment.
  *
  * @see comment_get_display_ordinal()
@@ -376,8 +477,8 @@ function comment_goodness_get_display_ordinal($cid, $node_type) {
   }
 
   // Get the configured default sort ordering for this node type.
-  $sort = variable_get('comment_default_sorting_' . $node_type, comment_goodness_OLDER_FIRST);
-  $operation = ($sort == comment_goodness_NEWER_FIRST) ? '>' : '<';
+  $sort = variable_get('comment_default_sorting_' . $node_type, COMMENT_GOODNESS_OLDER_FIRST);
+  $operation = ($sort == COMMENT_GOODNESS_NEWER_FIRST) ? '>' : '<';
   $mode = variable_get('comment_default_mode_' . $node_type, COMMENT_MODE_THREADED);
 
   if ($mode == COMMENT_MODE_FLAT) {
@@ -388,7 +489,7 @@ function comment_goodness_get_display_ordinal($cid, $node_type) {
   }
   else {
     // For threaded comments, the c.thread column is used for ordering.
-    if ($sort == comment_goodness_NEWER_FIRST) {
+    if ($sort == COMMENT_GOODNESS_NEWER_FIRST) {
       // For newer to older sorted comments, we look for how many comments have
       // a higher thread value than the current comment.
       $query->where('c1.thread ' . $operation . ' c2.thread');
@@ -404,3 +505,12 @@ function comment_goodness_get_display_ordinal($cid, $node_type) {
   return $query->execute()->fetchField();
 }
 
+/**
+ * Return delete action for specified comment node type and user type
+ */
+function _comment_goodness_get_delete_action($comment_type) {
+  $user_type = (user_access('administer comments') ? 'admin' : 'owner');
+  $node_type = str_replace('comment_node_', '', $comment_type);
+
+  return variable_get('comment_delete_' . $user_type . '_action_' . $node_type, FALSE);
+}
