Question

I'm using this bit to insert/update a custom post type from the front-end. The date is set from a custom jquery datepicker.

    if (strtotime($date) < strtotime('tomorrow')) {
            $newpostdata['post_status'] = 'publish';
    } elseif (strtotime($date) > strtotime('today')) {
            $newpostdata['post_status'] = 'future';
            $newpostdata['post_date'] = date('Y-m-d H:i:s', strtotime($date));
    }

    if ('insert' == $operation) {
        $err = wp_insert_post($newpostdata, true);
    } elseif ('edit' == $operation) {
        $newpostdata['ID'] = $post_id;
        $err = wp_update_post($newpostdata);
    }

This works when first publishing the post, setting it correctly as publish or future, with the correct date.

This doesn't work when editing the same post, neither from publish to future nor the other way around. Everything else is properly updated, except for the post status/future_date.

UPDATE Oct. 9th I'm starting to think this might be a bug, so i started a conversation at the wp-hackers mailing list, about this. There's some fresh install test results on the link.


OTHER FAILED ATTEMPTS:

i've tried leaving post_status decisions to wp_insert_post() using:

elseif ('edit' == $operation) {
        $newpostdata['post_status'] = '';
        $newpostdata['ID'] = $post_id;
        $err = wp_update_post($newpostdata);
    }

And this sets the post status to draft while maintaning the requested dates.

I've also tried calling wp_transition_post_status() again (it's called once inside wp_insert_post()):

elseif ('edit' == $operation) {
        $newpostdata['ID'] = $post_id;
        $err = wp_update_post($newpostdata);
        wp_transition_post_status($old_status, $status, $post_id);
    }

but that also didn't seem to work.

I'm running out of ideas here. Any clues?

Was it helpful?

Solution

Answer couldn't be simpler.

As pointed out by Otto at the wp-hackers list, problem was me not setting post_date_gmt when using wp_update_post().

Final code looks like this:

if ( $post_date < strtotime( "tomorrow" ) ) {
        $status = 'publish';    
        $newpostdata['post_status'] = $status;
        $newpostdata['post_date'] = date( 'Y-m-d H:i:s',  $post_date );

        // Also pass 'post_date_gmt' so that WP plays nice with dates
        $newpostdata['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $post_date );

    } elseif ( $post_date > strtotime( 'today' ) ) {
        $status = 'future';    
        $newpostdata['post_status'] = $status;
        $newpostdata['post_date'] = date( 'Y-m-d H:i:s', $post_date );

        // Also pass 'post_date_gmt' so that WP plays nice with dates
        $newpostdata['post_date_gmt'] = gmdate( 'Y-m-d H:i:s', $post_date );
    }

    if ('insert' == $operation) {
        $err = wp_insert_post($newpostdata, true);
    } elseif ('edit' == $operation) {
        $newpostdata['ID'] = $post_id;
        $err = wp_update_post($newpostdata);
    }

OTHER TIPS

I also tried the above code using wp_update_post() , but it doesn't work well with WordPress 3.9, it makes post_status empty and deleted all custom fields. I therefore created a custom query using the wpdb class. I hope this will work for all of you:

$wpdb->query( 
    $wpdb->prepare( 
        "UPDATE $wpdb->posts SET post_status = 'draft' WHERE ID = %d", 
        $post_id 
    )
);    

and this worked well on my localhost and hosting too.

We update the post status all the time, here is an example of how we allow users (on the front end editor that was built) to "pause" ads by changing them to draft:

if ($action == 'pause') {
        $my_post = array();
        $my_post['ID'] = $aid;
        $my_post['post_status'] = 'draft';
        wp_update_post($my_post);
        $action_msg = __('Ad has been paused', 'mytheme');
}

$newpostdata['post_date'] = date( 'Y-m-d H:i:s', $post_date );

This will return fisrt intial date of php 1970, use strtotime to convert string to time

$newpostdata['post_date'] = date( 'Y-m-d H:i:s', strtotime($post_date) );

You need to add "edit_date" => true in wp_update_post array

Not the OP's issue, but as a notable point of reference for others finding their way here researching a similar issue where wp_update_post() doesn't update post_status ...

As @adrianthedev noted above in a comment on the OP, note that the maximum length of a custom post status is 20 chars.

https://developer.wordpress.org/reference/functions/register_post_status/#comment-3927

When 20 chars are exceeded, you are able to register the custom post status using register_post_status(), but currently unable to set a post as using it with wp_update_post(), at least as of WordPress v5.5.1

Licensed under: CC-BY-SA with attribution
Not affiliated with wordpress.stackexchange
scroll top