I have a custom post type called 'directory' and it includes a few meta/custom fields. The script below is meant to just change the post status only when run. This isn't on the admin panel where you save the post. This is a stand alone script run by itself.

global $wpdb;
global $post;

$directories = get_posts( $get_directories );
foreach ($directories as $directory){
 wp_update_post(array('ID' => $directory->ID,'post_status' => 'draft'));

The status is updated fine, but the custom meta data is deleted.

I've seen other's with similar problems adding an update on the admin edit page, but this is its own file.

  • 1
    There's already an answer here stackoverflow.com/a/5722555/3910932 – Samuel Elh May 25 '16 at 16:05
  • @SamuelElh that seems to me as something specific to third party code, I would be hesitant to say it's a general answer (though it very well might be the same in this case). – Rarst May 25 '16 at 16:18
  • @SamuelElh, I did see that question and the poster seems to have the problem as me. But the answer was how to update post meta. I'm looking to update the post status. – Rafael May 25 '16 at 16:43
  • @Rarst, its not so much third party code. I just have a normal CPT called 'directory' and I am trying to create a php file that's part of a plug in that when loaded will execute this status update. – Rafael May 25 '16 at 16:45

Not sure about the problem with wp_update_post but it is a simple enough SQL query:

global $wpdb;
$query = "UPDATE ".$wpdb->prefix."posts SET post_status='draft' WHERE ID = '".$directory->ID."'";
  • This worked just fine. Only change was that my code was inside a function and I needed to redeclare 'global $wpdb;' inside the function. Just not sure why the wp_update_post wouldn't work. – Rafael May 25 '16 at 19:10
  • 1
    I believe @cybmeta is probably right on that one, it is likely in the 3rd party code hooking into a save action (eg. where a nonce is checked but the failure clears the fields instead of returning without touching them.) – majick May 26 '16 at 2:35
  • or it could also be something hooked to the transition action which is also run by wp_transition_post_status: codex.wordpress.org/Post_Status_Transitions – majick May 26 '16 at 2:38

I don't think this should happen by default. From quick look through the code the only case in which update call should affect meta is if you provide meta_input in arguments to apply.

As per comment the case might be that you are trying to interact with third party CPT and its code doesn't handle situation well.

Note that "own file" doesn't matter much (and is pretty bad practice while at it), the WP core will still boot and load all the plugins.

  • I definitely agree it shouldn't happen, and there is no meta_input at all. And I added in the comment that there is no third party CPT, it is a normal CPT within my custom plugin on the wordpress installation. And own file just means that it is a regular PHP file within my custom plugin that when run will execute the status update. – Rafael May 25 '16 at 16:46

Based on the source code of wp_publish_post(), you could update the post status without touching meta data and, at the same time, without losing post transition actions (you are missing them in your code) with something like this:

global $wpdb;
// Unkown $get_directories, you have not set it
// in your sample code, I assume it is correct
$directories = get_posts( $get_directories );
foreach( $directories as $directory ){
    // Skip already draft posts
    if( $directory->post_status != 'draft' ) {
        $wpdb->update( $wpdb->posts, array( 'post_status' => 'draft' ), array( 'ID' => $directory->ID ) );
        clean_post_cache( $directory->ID );
        $old_status = $directory->post_status;
        $directory->post_status = 'draft';
        // Perform transition actions
        wp_transition_post_status( 'draft', $old_status, $directory );

You could include also other actinos triggered when a post is updated:

do_action( 'edit_post', $directory->ID, $post );
do_action( "save_post_{$directory->post_type}", $directory->ID, $directory, true );
do_action( 'save_post', $directory->ID, $directory, true );
do_action( 'wp_insert_post', $directory->ID, $directory, true );

But, as @Rast said, it is very probably that your problem is with some of these actions hooked by third party code (from another plugin or from the theme). These actions are triggered by wp_update_post() and it is commonly used to update post meta fields, specially save_post action. It is very probably that when these actions are triggered without meta information, like your code does, the third party code deletes the meta fields.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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