0

To add a 'spam/delete' button to an individual comment, you can use code similar to this

$link = '<a class="comment-edit-link" href="' . get_edit_comment_link( $comment->comment_ID ) . '" title="' . __( 'Edit comment' ) . '">' . $link . '</a>';

$link = $link . ' <a href="'.admin_url("comment.php?action=cdc&dt=deletecomment&c=$id").'">Delete/Trash</a> ';

$link = $link . ' <a href="'.admin_url("comment.php?action=cdc&dt=spam&c=$id").'">Spam</a>';

$link = $before . $link . $after;

and add that code via the edit_comment_link filter. There is also this answer which adds the same capability via a plugin: https://wordpress.stackexchange.com/a/54122/29416 .

Either way, you are shown the admin page for that comment, where you can view the comment and then decide to spam/trash the comment. I have adjusted the code to only allow the admin to see those links.

How would this be enhanced to just 'do it', bypassing the admin page? In other words: hit the spam link (as admin), and the comment status is immediately changed to 'spam'.

Added

I need an enhancement - the links in the original answer by "Sally CJ" work, but reload the page. And since the comment that I clicked on doesn't exist, the browser displayed the entire page. I need it to position to the spot where the comment used to be. I've tried some Ajax code , but get an 'expired' notice (related to an incorrect nonce?), or get the comment moderation screen complaining that the "comment approved - do you want to spam it' message.

Ajax code used is roughly:

    $cid = $the_comment_id;
    $response = new WP_Ajax_Response;

    if(
            current_user_can( 'moderate_comments' ) &&
            check_ajax_referer( 'cwimc_idc-delete-'.$cid, 'nonce', false ) &&
                    wp_delete_comment( $cid,  true  )

) ;

I need the code to force a delete (in this case), which is why I added the 2nd parameter to wp_delete_comment). But that still brings me to the Moderation screen asking for a confirm on the delete.

So, I need to do an Ajax call to spam/delete/trash the comment, without getting to the Moderation screen. If I can get the Ajax call to work properly, then I can remove that comment with some 'parentnode/removechild', and the display will be at that point in the comment list.

1
  • I posted an answer, but one thing I didn't include, is that are you sure you want to use the edit_comment_link hook? Because IMO it's supposed to be just a link to edit the comment, so you should (or I would) try looking for a different hook to add the other action links like "Spam".
    – Sally CJ
    Jun 24 at 14:05

1 Answer 1

0

Update

So, I need to do an Ajax call to spam/delete/trash the comment

I would actually also use AJAX, and secondly, I would use JS instead to add the action links — and personally, I think an edit_comment_link callback should return just one link (i.e. one a element).. but anyway,

There are many ways to do the AJAX, but I would use the REST API: https://developer.wordpress.org/rest-api/reference/comments/.

You can find a full working example here on GitHub where the script file name is comment-ajax-actions.js, but the main parts that you need to know are:

  • Part 1:

    // Removes the spam/trashed/deleted comment's element from the DOM. Make sure
    // the selectors like LI.comment and .comment-body exist in your comments list.
    function removeComment( link ) {
        ... see code on GitHub.
    }
    
    // Updates a comment's status, or delete the comment, via the REST API.
    function commentApiRequest( link ) {
        var action     = $( link ).data( 'action' );
        var comment_id = $( link ).data( 'id' );
        var isDeleting = ( 'delete' === action );
    
        if ( confirmDeleteText && isDeleting && ! confirm( confirmDeleteText ) ) {
            return false;
        }
    
        wp.apiRequest( {
            path: 'wp/v2/comments/' + comment_id,
            method: isDeleting ? 'DELETE' : 'POST',
            data: isDeleting ? { force: true } : { status: action }
        } ).done( function () {
            removeComment( link );
        } );
    }
    
  • Part 2:

    // If you changed the action link's class (default: comment-ajax-action),
    // then be sure to also change the one below!
    $( '.comment-ajax-action' ).on( 'click', function ( e ) {
        e.preventDefault();
        commentApiRequest( this );
    } );
    

And note that the script uses jQuery and wp.apiRequest() (see wp-includes/js/api-request.js), so be sure to add jquery and wp-api-request as dependencies when enqueueing that AJAX script. E.g. where the script file is placed inside wp-content/themes/your-theme/assets/js:

wp_enqueue_script(
    'your-theme-comment-ajax-actions',
    get_template_directory_uri() . '/assets/js/comment-ajax-actions.js',
    array( 'jquery', 'wp-api-request' ),
    wp_get_theme()->get( 'Version' ),
    true
);

Last but not least, the script has been tested with WordPress v6.0 and the Twenty Twenty-One and Twenty Twenty-Two themes (the latter is a block-based theme and as of writing, it uses wp-includes/theme-compat/comments.php which is deprecated, but Twenty Twenty-Two suppressed the deprecation notice).

Original Answer

In the comments list table at wp-admin/edit-comments.php, the URL for the "Spam" link as of writing looks like this:

https://example.com/wp-admin/comment.php?c=123&action=spamcomment&_wpnonce=xxxxxxxxxx

where 123 is the comment ID and the _wpnonce value is a nonce with delete-comment_<comment ID> being the action.

And the "Trash" and "Delete" links also follow the same format, except that the action value is trashcomment and deletecomment respectively.

So you should use the same format and visiting the link would just 'do it', i.e. bypassing the "Moderate Comment" admin page. And by default, after successfully marking the comment as spam or after trashing/deleting the comment, you would be sent back to where you were or otherwise then it defaults to wp-admin/edit-comments.php.

And with your code, you'd just need to change this part:

$link = $link . ' <a href="'.admin_url("comment.php?action=cdc&dt=deletecomment&c=$id").'">Delete/Trash</a> ';

$link = $link . ' <a href="'.admin_url("comment.php?action=cdc&dt=spam&c=$id").'">Spam</a>';

to the following, but note that you should always escape a URL when displaying it to the user:

$del_nonce = wp_create_nonce( "delete-comment_$id" );

$link = $link . ' <a href="'.admin_url("comment.php?c=$id&action=deletecomment&_wpnonce=$del_nonce").'">Delete/Trash</a> ';

$link = $link . ' <a href="'.admin_url("comment.php?c=$id&action=spamcomment&_wpnonce=$del_nonce").'">Spam</a>';

See WP_Comments_List_Table::handle_row_actions() for the current URL format for the above links.

And just for reference, this is the full code I used:

add_filter( 'edit_comment_link', function ( $link, $comment_id ) {
    if ( ! current_user_can( 'edit_comment', $comment_id ) ) {
        return $link;
    }

    $del_nonce = wp_create_nonce( "delete-comment_$comment_id" );

    $url = admin_url( "comment.php?c=$comment_id&action=spamcomment&_wpnonce=$del_nonce" );
    $link .= ' | <a href="' . esc_url( $url ) . '">Spam</a>';

    $url = admin_url( "comment.php?c=$comment_id&action=trashcomment&_wpnonce=$del_nonce" );
    $link .= ' | <a href="' . esc_url( $url ) . '">Trash</a>';

    $url = admin_url( "comment.php?c=$comment_id&action=deletecomment&_wpnonce=$del_nonce" );
    $link .= ' | <a href="' . esc_url( $url ) . '">Delete</a>';

    return $link;
}, 10, 2 );
9
  • Thanks for the sample code, which works quite well. I could see the link in the admin screen to do the choice, but was hung up on the nonce value. My assumption was that I had to get a 'comment nonce' value somehow, rather than creating the nonce to use in the link, as you have done. My next issue is how to redisplay the comment list with a positioning of the browser viewpoint at the spot where the comment used to be. I cant's use the comment ID to reposition, as that comment is no longer visible. Thanks. Jun 25 at 21:09
  • see question addition. Jun 28 at 20:38
  • Hi, sorry for the late reply. Have you solved that "reposition" thing? If not, can you clarify if you need an AJAX solution to delete a comment, or that you simply wanted the browser to, after page reload, "jump" to where the deleted comment was?
    – Sally CJ
    Jul 3 at 8:05
  • After the initial look at the problem, and your solution, it would appear that I do indeed need an Ajax solution to spam/delete/trash the comment, and then Javascript to 'undisplay' the removed comment. I've figured out the JS undisplay thing, but having no success with the Ajax command to to this link: example.com/wp-admin/… (which is what WP does). Probably related to my limited understanding of how to do Ajax. And probably need to create another question for that. All the answers I've found here on Ajax have not helped. Jul 4 at 17:28
  • Maybe I can add an additional answer specific to that AJAX thing, but I thought it would be helpful to know what theme are you using (a child theme of a default/core theme; a custom theme?) - is it a block(-based) theme? Or have you already found a working AJAX solution/code?
    – Sally CJ
    Jul 5 at 22:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.