0

I have a Custom post type in wordpress in which when creating a new post 3 child subposts are created automatically. For example, I create the post and assign it some status 'Publish', 'pending', 'draft' or another:

Post Company 1

-Subpost 1 (it is created automatically)  
-Subpost 2 (it is created automatically)  
-Subpost 3 (it is created automatically)

Removing the parent (moves to 'trash' ) will also remove the subposts. But when you restore them, they should be in the state they were saved in before ('pending', 'draft', 'auto-draft' or something else).

How could I do that to restore the posts (parent and children) with their 'post-status' that they had defined before being moved to 'trash'?

This is my code that I am using to create the 3 child subposts automatically:

function add_children_custom_post_type( $post_id ) {
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
    return;

if ( !wp_is_post_revision( $post_id ) && 'companies' == get_post_type( $post_id ) && 'publish' == get_post_status( $post_id ) ) {
    $show = get_post( $post_id );
    if( 0 == $show->post_parent ){
        $children =& get_children(
            array(
                'post_parent' => $post_id,
                'post_type' => 'companies'
            )
        );
        if( empty( $children ) ){
            //Children pages
            $titles = ['Subpost1', 'Subpost2', 'Subpost3'];
            foreach ($titles as $key=>$title) {
                $child = array(
                    'post_type' => 'companies',
                    'post_title' => $title,
                    'post_content' => '',
                    'post_status' => 'publish',
                    'post_parent' => $post_id,
                    'post_author' => get_post_field('post_author', $post_id),
                    'menu_order' => $key
                );
                wp_insert_post( $child );
            }
        }
     }
  }
}
add_action( 'save_post', 'add_children_custom_post_type' );

And this is the one I use to move the child posts of a parent post when the parent is deleted:

// Move to Trash
function trash_post_children($post_id) {
$parent_ID = $post_id;

$args = array(
    'post_type' => 'companies',
    'post_parent' => $parent_ID,
    'posts_per_page' => -1,
    'post_status' => array('publish', 'pending', 'draft', 'auto-draft', 'future', 'private', 'inherit', 'trash')
);
  $children = get_posts($args);
  if($children) {
      foreach($children as $p){
        wp_trash_post($p->ID, true);
      }
   }
}
add_action('trashed_post', 'trash_post_children');

And this other one is to restore the posts but they are always restored in 'draft' state:

// RestorePost
function restore_post_children($post_id) {
   $parent_ID = $post_id;
    $args = array(
       'post_type' => 'companies',
       'post_parent' => $parent_ID,
       'posts_per_page' => -1,
       'post_status' => 'trash'
   );
   $children = get_posts($args);
   if($children) {
    foreach($children as $p) {
        wp_untrash_post($p->ID);
    }
  }
}
add_action('untrash_post', 'restore_post_children');
7
  • 1
    wp_untrash_post should already do this and has code that does exactly what you're asking how to do built into it, the 9th line of code of that function fetches the post status from before it was trashed. Note that trashed posts are garbage collected on a schedule, if you're doing this just to hide the posts then that is a dangerous strategy to take. Also wp_trash_post does not have a second parameter but you've passed true, is there a particular reason you've done this?
    – Tom J Nowell
    Commented Mar 21, 2022 at 23:38
  • @TomJNowell Thanks. But wp_untrash_post always restores my posts as 'draft'.
    – JoseFranc
    Commented Mar 21, 2022 at 23:43
  • @TomJNowell I need to restore the posts with their previous state, be it 'draft', 'pending' or another
    – JoseFranc
    Commented Mar 21, 2022 at 23:46
  • I already understand that, and if you look at wp_untrash_post it does this by retrieving the post meta _wp_trash_meta_status, though I see that you call wp_untrash_post inside an untrash post filter, which will call the filter again. Something else not mentioned in your question is happening. Are you using the wp_untrash_post_status filter? The canonical answer to your question is that wp_untrash_post already does this, no additional work is necessary, either something else in your codebase is interfering, or the post was a draft before it was deleted for unknown reasons
    – Tom J Nowell
    Commented Mar 22, 2022 at 1:04
  • 1
    I understood that, if you look at the code for the wp_untrash_post it has the answer to your question in a comment just above the call to the wp_untrash_post_status filter I mentioned, detailing why this happens and what you need to do
    – Tom J Nowell
    Commented Mar 22, 2022 at 1:08

1 Answer 1

0

The reason it is a draft, and what you need to do to get what you wanted is spelt out in the source code for wp_untrash_post and in the documentation for wp_untrash_post_status:

https://github.com/WordPress/WordPress/blob/bbf017e550b02f5d11e409b07e689d45c984054d/wp-includes/post.php#L3668-L3685

    $new_status = ( 'attachment' === $post->post_type ) ? 'inherit' : 'draft';

    /**
     * Filters the status that a post gets assigned when it is restored from the trash (untrashed).
     *
     * By default posts that are restored will be assigned a status of 'draft'. Return the value of `$previous_status`
     * in order to assign the status that the post had before it was trashed. The `wp_untrash_post_set_previous_status()`
     * function is available for this.
     *
     * Prior to WordPress 5.6.0, restored posts were always assigned their original status.
     *
     * @since 5.6.0
     *
     * @param string $new_status      The new status of the post being restored.
     * @param int    $post_id         The ID of the post being restored.
     * @param string $previous_status The status of the post at the point where it was trashed.
     */
    $post_status = apply_filters( 'wp_untrash_post_status', $new_status, $post_id, $previous_status );

https://developer.wordpress.org/reference/hooks/wp_untrash_post_status/

By default posts that are restored will be assigned a status of ‘draft’. Return the value of $previous_status in order to assign the status that the post had before it was trashed. The wp_untrash_post_set_previous_status() function is available for this.

Prior to WordPress 5.6.0, restored posts were always assigned their original status.

So use that filter and add wp_untrash_post_set_previous_status to it which was built specifically for this problem: https://developer.wordpress.org/reference/functions/wp_untrash_post_set_previous_status/

Notice its source code is super simple

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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