Removing Comments in Branches

I propose a hook for deleting all child comments when a comment is deleted, i.e. we delete the comment and all its child comments are also deleted, as well as their child comments, and so on. In other words, when a comment is deleted, the entire branch of replies to it is also deleted.

To make "branch deletion" work, insert the code into the functions.php theme file.

/**
 * Deleting all child comments (entire tree) when a comment is deleted
 */
add_action( 'delete_comment', 'del_child_comments_on_del_comment' );

function del_child_comments_on_del_comment( $comment_id ) {
	global $wpdb;

	$child_comments = $wpdb->get_col(
		"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
	);

	// if there are no children, return
	if( ! $child_comments ){
		return;
	}

	foreach( $child_comments as $val ){
		wp_delete_comment( $val );
	}
}

Key points of the hook: filter - delete_comment and function - wp_delete_comment():

I spent quite a bit of time on the code because it uses recursion, and recursion can often be tricky and not my favorite...

In programming, recursion is the process of a function calling itself (simple recursion) or through other functions (complex or indirect recursion). For example, function A calls function B, and function B calls function A. The number of nested function or procedure calls is called the depth of recursion.

At first, I tried to use recursion naturally (wrote a function, hooked it to a hook, and called it from within itself) - but it didn't work out, and the code just kept growing. At one point, as I went to make myself a cup of tea, the Eureka moment came, and I understood everything: the closure will occur when the delete_comment hook is triggered during the successive calls of the wp_delete_comment() function, and there's no need to call the function from within the function in its pure form, i.e. there will be indirect recursion.

Honestly, I can't imagine a real situation on a regular blog where such comment deletion would be particularly necessary. However, it is logical and may be needed by someone. On this blog, I did it this way because if you delete a comment that has child comments, the meaning of the child comments will often be lost: there will be comments that are unclear. Using an allegory - these are comments on a post without the post itself. I think I don't need that here.

Moving to Trash

After the deletion task was solved, following the beaten path, I wrote the same moving comments to trash and restoring them from trash by branches.

The principle is the same, only now filters are used: trash_comment, untrash_comment and functions: wp_trash_comment(), wp_untrash_comment():

/**
 * Moving all child comments to trash (entire tree) when a comment is deleted
 */
add_action( 'trash_comment', 'trash_child_comments_on_trash_comment' );
function trash_child_comments_on_trash_comment( $comment_id ) {
	global $wpdb;

	// if there are no children, return
	$child_comments = $wpdb->get_col(
		"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
	);
	if( ! $child_comments ){
		return;
	}

	foreach( $child_comments as $val ){
		wp_trash_comment( $val );
	}
}

add_action( 'untrash_comment', 'untrash_child_comments_on_untrash_comment' );
function untrash_child_comments_on_untrash_comment( $comment_id ) {
	global $wpdb;

	// if there are no children, return
	$child_comments = $wpdb->get_col(
		"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
	);
	if( ! $child_comments ){
		return;
	}

	foreach( $child_comments as $val ){
		wp_untrash_comment( $val );
	}
}

Simplified Code for Moving to Trash

Here's a very interesting code for those who understand PHP: a simplified version of the above code (for the trash). Here, it's interesting to see how the current_filter() function can be used and an unusual dynamic function call in PHP using a variable ($use_function( $val )). In general, take a look for yourself:

/**
 * Moving all child comments to trash (entire tree) when a comment is deleted
 */
add_action( 'trash_comment', 'trash_untrash_child_comments_with_parent' );
add_action( 'untrash_comment', 'trash_untrash_child_comments_with_parent' );
function trash_untrash_child_comments_with_parent( $comment_id ) {
	global $wpdb;

	// if there are no children, return
	$child_comments = $wpdb->get_col(
		"SELECT comment_ID FROM $wpdb->comments WHERE comment_parent='$comment_id'"
	);
	if( ! $child_comments ){
		return;
	}

	foreach( $child_comments as $val ){
		// get wp_trash_comment or wp_untrash_comment
		$use_function = 'wp_' . current_filter();
		$use_function( $val );
	}
}