Hello,

I am trying to allow my users to delete their own comments, but I have only been able to allow them to delete their own nodes. I have tried the Users_Tweaks module, but it did not work.

I know that users are not supposed to be able to delete their own comments because of comment threading, but my site does not allow users to respond to other comments, only the node, so this is not an issue.

Any tips/suggestions?

Thanks.

Comments

shamio’s picture

Go to admin -> people -> permissions and then below Comment section, change permission for Edit own comments and allow authenticated user to have this permission.

rawrzors’s picture

Hi,
I am trying to allow them to delete their own comments. I already have it set up to allow them to edit.

shamio’s picture

OK, if you are using Drupal 6, have a look at this module that does exactly it for you: http://drupal.org/project/comment_delete
And for Drupal 7 , have a look at this module too: http://drupal.org/project/commentaccess

rawrzors’s picture

I am using Drupal 7. Comment access only allows the user to delete comments on the nodes that they create. I would like to allow users to delete their own comments anywhere.

Thanks

WorldFallz’s picture

Due to threading, it can be a little complex to do this right-- that's why comment_delete was created. What's really needed is a d7 version of that module. It's not very big and doesn't seem too complex, maybe trying porting it (the coder_upgrade module does much of the heavy lifting). Even posting a patch of the coder changes to the issue queue might spur the port.

rawrzors’s picture

Since comment_delete is for D6, it seems I am running out of options.
Is there a way to bypass this rule? My site does not use comment threading, so it should not cause any issue anyways.

WorldFallz’s picture

As with anything, it can be custom coded. Probably using hook_menu_alter on the 'comment/delete' path.

ericprado’s picture

Users wouldn't bother to delete their comments. Based on my experience, I just edit my comment to make it more engaging and allow users to learn from my comments. We comment basically to exchange information. I advise that everyone should be mindful to make their comments related to the topic discussed.

aaronaverill’s picture

The following is a solution for D7. I really consider this to be a bug in core - a user should be allowed to delete their own comments if there are no replies.

A word of caution. All comments in D7 are threaded. When you turn off threading, you really only turn off the presentation of threaded comments. In the database, the threading ability still exists. If you use this approach any user can delete their own comments, and this will also delete replies to that comment!! So if you use this code you need to make absolutely sure you've turned off the comment reply links.

Step 1) Create a link to the delete from the comment block. I'm doing this in a custom theme, but there are many ways to skin this cat. Here I override the comment preprocess to create a new link if the user is the comment author (in theme template.php):

function YOURTHEME_preprocess_comment(&$variables) {
  $comment = $variables['comment'];
  // Add a delete menu if the user posted the comment
  global $user;
  if ($user->uid == $comment->uid) {
    $variables['content']['links']['comment']['#links']['comment-delete'] = array(
      'title' => t('delete'),
      'href' => 'comment/' . $comment->cid . '/delete',
      'html' => TRUE,
    );
  }

So this will link to /comment/CID/delete - but we still haven't added access to this for non admins - clicking the link for a non-admin will result in a access denied error. You'll need to do this in a custom module:

Step 2) Customize the comment delete menu handler to call your overridden access function:

function YOURMODULE_menu_alter(&$items) {
  $items['comment/%/delete']['access callback'] = 'YOURMODULE_comment_delete_access';
  $items['comment/%/delete']['access arguments'] = array(1);
}

Step 3) Implement the access function (self explanatory from comments):

function YOURMODULE_comment_delete_access($cid) {
  if (user_access('administer comments')) return TRUE; // Allow admin to delete any comments
  global $user;
  $comment = comment_load($cid);
  if (!$comment) return FALSE; // Sanity check; disallow delete if comment doesn't exist
  if ($comment->uid != $user->uid) return FALSE; // Disallow if user is not comment author
  // Check if comment mode for this node type is flat
  $node = node_load($comment->nid);
  if (!$node) return FALSE; // Sanity check; disallow delete if node doesn't exist
  $comment_mode = variable_get('comment_default_mode_' . $node->type, COMMENT_MODE_THREADED);
  if ($comment_mode == COMMENT_MODE_FLAT) return TRUE;
  return FALSE;
}

There are several improvements we can (and should) make in a production environment:

1) Disallow access to the menu handler that replies to a specific comment - REALLY preventing threaded replies

This is a difficult task since the node reply menu callback handles replies to a node (non threaded) AND replies to a comment. In theory this can be done using a similar approach by altering the menu callback handlers, but you're going to end up pulling a lot of core code into your module.

Assuming you hide the links to reply to a specific comment, the only way to access this is if the user enters a URL manually. In this scenario if the original poster deletes their own comment, all the replies are deleted too.

2) Check to see if the comment has actual replies instead of looking at the node comment threading default

There are a lot of edge cases this doesn't handle. For example, you allow threaded replies, then at some point turn them off. The code here will not check if those previously entered comments have threaded replies. Thus a user can delete a comment and it will again delete other's replies.

To do this properly you need to write a function that both the theme calls (to create the "delete" link) and the access calls (to allow the delete to proceed). I'm not an expert on the database structure of comment, so I can't comment on how to do this.

If you end up using this, please let others know whether it works or not. This seems like a common use case.

Louis Bob’s picture

Thanks a lot for this solution!
I had tried different ones (including the user tweaks module), but only that one works for me.

MaxF’s picture

Nice walk-through, would be really worth a D7-module, I think!

For the security team not to jump on your head, you might think how to handle uid == 0:

   // [...]
   if ( ! user_is_logged_in() ) return FALSE; // Anonymous users shouldn't delete any comments
   if ($comment->uid != $user->uid) return FALSE; // Disallow if user is not comment author
   // [...]

Otherwise, anonymous users can delete all anonymous users' comments.

adammalone’s picture

I've written a callback for my site which allows anonymous deletion of comments.

The issue was:
I would get emails notifying me of new comments on my website, I wished to be able to instantly delete spam comments without having to sign in from my phone. (Yes call it laziness - but laziness breeds innovation!)

My solution:
I added a token to email notifications sent out based on $cid (comment ID) this generated a unique link that would allow me to delete a comment from my site without logging in.

I was considering having a drupal_set_message pop up after people comment so they are able to take note of their unique link and delete it if they so wish (and as long as it is within the time limit.) I'd be interested if people took a look at the code and where possible point out any security risks or other things that I have not taken into account.

function mymodule_menu() {
  $items['comment/%/fastdelete/%'] = array(
    'title' => 'Fast Comment Deletion',
    'page callback' => 'mymodule_comment_fastdelete',
    'page arguments' => array(1, 3),
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Authentication function for menu callback determining if the
 * comment should be deleted
 */
function mymodule_comment_fastdelete($cid, $hash) {
  $comment = comment_load($cid);
  // First check to see if the comment actually exists
  if ($comment) {
    // Add in a timeout so the comment can be deleted only in the
    // first 24 hours after posting.
    $timeout = variable_get('user_password_reset_timeout', 86400);
    $current = REQUEST_TIME;
    if ($current - $timeout > $comment->created) {
      drupal_set_message(t('You have tried to use a comment delete link that has expired. To have the comment deleted please contact the site administrator.'), 'warning');
      drupal_goto('contact-me');
    }
    else {
      $author = mymodule_node_author_pass_from_cid($cid);
      if ($hash == user_pass_rehash($cid, $comment->created, $author->pass) && $current >= $comment->created) {
        watchdog('mymodule', 'Comment Autodelete link used', array(), WATCHDOG_NOTICE);
        comment_delete($cid);
        drupal_set_message('Comment successfully deleted!');
        drupal_goto('node/' . $comment->nid);
      }
      else {
        drupal_set_message('You have tried to use an invalid comment deletion link.', 'warning');
        drupal_goto('node/' . $comment->nid);
      }
    }
  }
  else {
    drupal_set_message('You have tried to use an invalid comment deletion link.', 'warning');
    drupal_goto('');
  }
}

/**
 * Generates the deletion link for a specific comment.
 */
function mymodule_comment_fastdelete_link($cid) {
  $comment = comment_load($cid);
  $author = mymodule_node_author_pass_from_cid($cid);
  return url("comment/$cid/fastdelete/" . user_pass_rehash($cid, $comment->created, $author->pass), array('absolute' => TRUE));
}

/**
 * returns the hashed password of the node author the comment is posted on.
 * used for an unknown part of the hash that an anonymous user could not guess
 */
function mymodule_node_author_pass_from_cid($cid) {
  $result = db_query('SELECT u.pass FROM {comment} c JOIN {node} n on n.nid = c.nid JOIN {users} u ON n.uid = u.uid WHERE c.cid = :cid', array(':cid' => $cid));
  return $result->fetchObject();
}

/**
 * Implements hook_token_info_alter()
 */
function mymodule_token_info_alter(&$data) {
  $data['tokens']['comment']['comment_fastdelete_link'] = array(
    'name' => t("Comment Delete Link"),
    'description' => t("A link to immediately delete a comment."),
  );
}

/**
 * Implements hook_tokens()
 *
 */
function mymodule_tokens($type, $tokens, array $data = array(), array $options = array()) {
  $replacements = array();
  if ($type == 'comment') {
    foreach ($tokens as $name => $original) {
      switch ($name) {
        case 'comment_fastdelete_link':
          $cid = $data['comment']->cid;
          $link = mymodule_comment_fastdelete_link($cid);
          if (isset($cid)) {
            $replacements[$original] = $link;
          }
          else {
            $replacements[$original] = '';
          }
          break;
      }
    }
  }
  return $replacements;
}

Two issues I do acknowledge are:

  • Since the node author would know their own password and potentially the comment creation time - they could potentially run user_pass_rehash and obtain the link to delete comments even if they don't have the administer comment permission.
  • Deleting a comment would delete any child comments if the deleted comment is the parent. Perhaps an option would just be to have the comment body change to 'Comment deleted by author' or similar.
adammalone’s picture

I've allowed this functionality on this node of my site: http://www.adammalone.net/post/allowing-anonymous-comment-deletion-rights

Feel free to test it out!

geerlingguy’s picture

Please follow this issue in Drupal 8 core and help get it fixed, so comment deletion by comment authors can be used by anyone: http://drupal.org/node/10700

__________________
Personal site: www.jeffgeerling.com

mrgoodcheese’s picture

I had the same need to allow a user the ability to delete her own comments. I was surprised to realize that permission wasn't built into the core. After reading here and some other places about possible solutions, I got it to work with the
Comment Access module . The module adds permissions (to all content types) to allow "delete comments of own content". My user didn't own the content because I had created the page. So I simply change the author of the page from me to her, turned on that "delete comments of own content" permission for her role, and it worked. She can now delete her comments only on that page.

I hope this helps someone.

tanius’s picture

I'm surprised that this solution was not yet mentioned in the thread:

comment_goodness 7.x-1.4 and later contains the requested feature. It introduces a permission so you can allow users to delete their own comments if they do not have replies yet. The project page does not mention this feature yet, but I just tested it and it works well.

See also Drupal issue #1540924, where this feature was introduced into comment_goodness.

rahim123’s picture

Thanks so much for mentioning comment_goodness! It's a real life saver in my migration from D6.