0

I want to bulk delete child posts of a custom post type, and I've made it work. I'm in class context:

// In a register method which registers all hooks.
add_action( 'wp_trash_post', [ $this, 'delete_child_posts' ], 10 );

public function delete_child_posts( int $post_id ) {
  $current_post = get_post( $post_id );

  // Check if current post is in the documentation post type.
  if ( $current_post->post_type !== 'documentation' ) {
    return;
  }

  // Only trigger when deleting parent post.
  if ( $current_post->post_parent !== 0 ) {
    return;
  }

  $child_pages = [
    'post_parent' => $post_id,
  ];

  $children = get_children( $child_pages );

  if ( empty( $children ) ) {
    return;
  }

  foreach ( $children as $child_post ) {
    wp_trash_post( $child_post->ID );
  }
}

This works super when I'm deleting parent post, or a single post (even a child).

But if I select the parent and the children posts, and try to delete them I'll get

Error in moving to Trash.

I go back and I see the posts, then refresh the browser, and they are in the trash.

So, what happens is: the parent post is deleted, the logic goes through, and child posts are trashed in the foreach loop. Then the first child goes in the hook callback since it's being trashed and this action will be triggered, I can see the post ID, and it doesn't pass the

// Only trigger when deleting parent post.
if ( $current_post->post_parent !== 0 ) {
  return;
}

check. So the action should exit and that's that. But I get an error. I tried returning post id, post object null, checking if the post status is trash, but I always get an error.

What am I missing?

  • The way I see it happening here is that the parent is trashed, and as you have it designed it goes recursively 1 layer deep through all of the children and trashes them. Then, the initial bulk action you started moves onto the next post -- one of the children...which of course is already trashed. I imagine your post_parent !== 0 check is working. But just because you don't delete the post isn't stopping WP from deleting it. Basically you're calling wp_trash_post twice on the same post -- once via the bulk delete, and again via its parent's iteration of your function here. – tmdesigned Feb 6 at 10:10
  • But even though the post is trashed (post_type = trash), the post parent is still the original one (in the database, I've checked) so it's odd that it fails here. – dingo_d Feb 6 at 11:26
  • I think the problem is that I'm hooking to actions that are originally in wp_trash_post function, and that's causing the issue. – dingo_d Feb 6 at 11:32
  • 1
    The third condition, not argument, of wp_trash_post. Basically I just mean when you call that function, the third thing it does is check if the post is already trashed. If it is, it gives back that error message you see. – tmdesigned Feb 6 at 15:03
  • 1
    The only other thought I had was separating out your deletion from the default deletion. Instead of always deleting the children admin-wide, just add a new link on post list pages like "delete with children" and only run your code there. Then it won't compete with the default delete or the default bulk delete. – tmdesigned Feb 8 at 18:13

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.