diff -r 48c4eec2b7e6 -r 8c2e4d02f4ef wp/wp-admin/includes/class-wp-comments-list-table.php --- a/wp/wp-admin/includes/class-wp-comments-list-table.php Fri Sep 05 18:40:08 2025 +0200 +++ b/wp/wp-admin/includes/class-wp-comments-list-table.php Fri Sep 05 18:52:52 2025 +0200 @@ -357,6 +357,10 @@ protected function get_bulk_actions() { global $comment_status; + if ( ! current_user_can( 'moderate_comments' ) ) { + return array(); // Return an empty array if the user doesn't have permission + } + $actions = array(); if ( in_array( $comment_status, array( 'all', 'approved' ), true ) ) { @@ -705,18 +709,18 @@ $output = ''; - $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "delete-comment_$comment->comment_ID" ) ); - $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( "approve-comment_$comment->comment_ID" ) ); + $approve_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'approve-comment_' . $comment->comment_ID ) ); + $del_nonce = esc_html( '_wpnonce=' . wp_create_nonce( 'delete-comment_' . $comment->comment_ID ) ); - $url = "comment.php?c=$comment->comment_ID"; + $action_string = 'comment.php?action=%s&c=' . $comment->comment_ID . '&%s'; - $approve_url = esc_url( $url . "&action=approvecomment&$approve_nonce" ); - $unapprove_url = esc_url( $url . "&action=unapprovecomment&$approve_nonce" ); - $spam_url = esc_url( $url . "&action=spamcomment&$del_nonce" ); - $unspam_url = esc_url( $url . "&action=unspamcomment&$del_nonce" ); - $trash_url = esc_url( $url . "&action=trashcomment&$del_nonce" ); - $untrash_url = esc_url( $url . "&action=untrashcomment&$del_nonce" ); - $delete_url = esc_url( $url . "&action=deletecomment&$del_nonce" ); + $approve_url = sprintf( $action_string, 'approvecomment', $approve_nonce ); + $unapprove_url = sprintf( $action_string, 'unapprovecomment', $approve_nonce ); + $spam_url = sprintf( $action_string, 'spamcomment', $del_nonce ); + $unspam_url = sprintf( $action_string, 'unspamcomment', $del_nonce ); + $trash_url = sprintf( $action_string, 'trashcomment', $del_nonce ); + $untrash_url = sprintf( $action_string, 'untrashcomment', $del_nonce ); + $delete_url = sprintf( $action_string, 'deletecomment', $del_nonce ); // Preorder it: Approve | Reply | Quick Edit | Edit | Spam | Trash. $actions = array( @@ -737,7 +741,7 @@ if ( 'approved' === $the_comment_status ) { $actions['unapprove'] = sprintf( '%s', - $unapprove_url, + esc_url( $unapprove_url ), "delete:the-comment-list:comment-{$comment->comment_ID}:e7e7d3:action=dim-comment&new=unapproved", esc_attr__( 'Unapprove this comment' ), __( 'Unapprove' ) @@ -745,7 +749,7 @@ } elseif ( 'unapproved' === $the_comment_status ) { $actions['approve'] = sprintf( '%s', - $approve_url, + esc_url( $approve_url ), "delete:the-comment-list:comment-{$comment->comment_ID}:e7e7d3:action=dim-comment&new=approved", esc_attr__( 'Approve this comment' ), __( 'Approve' ) @@ -754,7 +758,7 @@ } else { $actions['approve'] = sprintf( '%s', - $approve_url, + esc_url( $approve_url ), "dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=approved", esc_attr__( 'Approve this comment' ), __( 'Approve' ) @@ -762,7 +766,7 @@ $actions['unapprove'] = sprintf( '%s', - $unapprove_url, + esc_url( $unapprove_url ), "dim:the-comment-list:comment-{$comment->comment_ID}:unapproved:e7e7d3:e7e7d3:new=unapproved", esc_attr__( 'Unapprove this comment' ), __( 'Unapprove' ) @@ -772,7 +776,7 @@ if ( 'spam' !== $the_comment_status ) { $actions['spam'] = sprintf( '%s', - $spam_url, + esc_url( $spam_url ), "delete:the-comment-list:comment-{$comment->comment_ID}::spam=1", esc_attr__( 'Mark this comment as spam' ), /* translators: "Mark as spam" link. */ @@ -781,7 +785,7 @@ } elseif ( 'spam' === $the_comment_status ) { $actions['unspam'] = sprintf( '%s', - $unspam_url, + esc_url( $unspam_url ), "delete:the-comment-list:comment-{$comment->comment_ID}:66cc66:unspam=1", esc_attr__( 'Restore this comment from the spam' ), _x( 'Not Spam', 'comment' ) @@ -791,7 +795,7 @@ if ( 'trash' === $the_comment_status ) { $actions['untrash'] = sprintf( '%s', - $untrash_url, + esc_url( $untrash_url ), "delete:the-comment-list:comment-{$comment->comment_ID}:66cc66:untrash=1", esc_attr__( 'Restore this comment from the Trash' ), __( 'Restore' ) @@ -801,7 +805,7 @@ if ( 'spam' === $the_comment_status || 'trash' === $the_comment_status || ! EMPTY_TRASH_DAYS ) { $actions['delete'] = sprintf( '%s', - $delete_url, + esc_url( $delete_url ), "delete:the-comment-list:comment-{$comment->comment_ID}::delete=1", esc_attr__( 'Delete this comment permanently' ), __( 'Delete Permanently' ) @@ -809,7 +813,7 @@ } else { $actions['trash'] = sprintf( '%s', - $trash_url, + esc_url( $trash_url ), "delete:the-comment-list:comment-{$comment->comment_ID}::trash=1", esc_attr__( 'Move this comment to the Trash' ), _x( 'Trash', 'verb' ) @@ -847,7 +851,16 @@ ); } - /** This filter is documented in wp-admin/includes/dashboard.php */ + /** + * Filters the action links displayed for each comment in the Comments list table. + * + * @since 2.6.0 + * + * @param string[] $actions An array of comment actions. Default actions include: + * 'Approve', 'Unapprove', 'Edit', 'Reply', 'Spam', + * 'Delete', and 'Trash'. + * @param WP_Comment $comment The comment object. + */ $actions = apply_filters( 'comment_row_actions', array_filter( $actions ), $comment ); $always_visible = false;