I use save_post hook, and I have to know inside this hook function, whether it is a publishing ( draft to publish ) or is it an updating, like publish to publish or draft to draft.

Is there a way to check it?

I can not use draft_to_publish hook for this, and I'll explain why:
The users ask questions on the site, and questions are saved as draft posts. A site admin write an answer and then publish the post. A post has meta box "status" that can have next values: "not answered", "treatment", "answered". A site admin may change this value as he wants, but when he publish the post (draft to publish, or draft to private), this meta value must be changed automatically to "answered" (although that the input area on admin area has another value). So I have a function that fired on save_post hook, that save all values according to input area values. And also I tried to use draft_to_publish hook to assign "answered" to the meta value. The problem is that save_post always fired after draft_to_publish, so that the value ("answered" that assigned on draft_to_publish) is overridden by the value of input area.

  • I decided to use global variable. I assign $is_publishing_now = true in draft_to_publish hook, and by this way can know during save_post hook, that it is publishing now. Thank you for your answers.
    – Shimon S
    Jan 31, 2013 at 15:14

2 Answers 2


There are hooks specifically for this, actually. The codex has a pretty good overview.

Essentially every time WordPress saves a post (which it does through wp_insert_post) or alters the status of the post, it calls wp_transition_post_status which looks like this:

// in wp-includes/post.php
function wp_transition_post_status($new_status, $old_status, $post) {
    do_action('transition_post_status', $new_status, $old_status, $post);
    do_action("{$old_status}_to_{$new_status}", $post);
    do_action("{$new_status}_{$post->post_type}", $post->ID, $post);

So, if you want to check for a post moving from publish to publish you could do this...

add_action('transition_post_status', 'wpse83835_transition', 10, 3);
function wpse83835_transition($new, $old, $post)
    if ('publish' == $new && 'publish' == $old) {
        // do stuff

Or this...

add_action('publish_to_publish', 'wpse83835_transition_again');
function wpse83835_transition_again($post)
    // do stuff.
  • Thank you. But seems that I can not use this hook. I edited the question to explain it.
    – Shimon S
    Jan 31, 2013 at 13:37

You can use another hook to define action on update. The post_updated hook is defined as this:

do_action( 'post_updated', $post_ID, $post_after, $post_before);

and is not called on post creation. variable $update is set as follows:

   // Are we updating or creating?
    if ( !empty($ID) ) {
        $update = true;
        $post_ID = (int) $ID;
    } else {
        $update = false;
        $post_ID = 0;

And hook posts_updated is inside following if statement:

if ( $update ) {
        do_action('edit_post', $post_ID, $post);
        $post_after = get_post($post_ID);
        do_action( 'post_updated', $post_ID, $post_after, $post_before);

    do_action('save_post', $post_ID, $post);
    do_action('wp_insert_post', $post_ID, $post);

to check if it is draft to publish, you'll check on $post_before->post_status and on $post_after->post_status.

Just as an addendum here is a check for ommit autosave:

if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
  • Apparently that did not suit me. I edited the question to explain more.
    – Shimon S
    Jan 31, 2013 at 13:40

Your Answer

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

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