I’m trying to fire two different actions on both publish and update. Neither should ever fire at the same time.
The problem is that publish_pm_task
is getting fired on update and save_post
is never getting fired? See anything wrong with this?
<?php
// Updated task notification
add_action( 'save_post', 'pm_updated_task_notification' );
// New task notification
add_action( 'publish_pm_task', 'pm_new_task_notification' );
function pm_new_task_notification() {
error_log('definitely a task');
}
function pm_updated_task_notification( $post_id ) {
$slug = 'pm_task';
/* check whether anything should be done */
$_POST += array("{$slug}_edit_nonce" => '');
if ($slug != $_POST['post_type']) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (!wp_verify_nonce($_POST["{$slug}_edit_nonce"], plugin_basename(__FILE__))) {
return;
}
error_log('updated a task');
}
1 Answer
First of all you have to understand that when we update a post, wp_update_post
function is called. But due to a bit not optimal design of WP core, the actual saving is processed by wp_insert_post
function. See it in trac on line 3006.
Ok, next lets see what is inside of wp_insert_post
function. As you can see, on line 2950, save_post
action is called each time the function is called, whenever it has been called directly or by wp_update_post
function. It means that it doesn’t suit to determine if post has been inserted/published or updated.
To find better action, lets take a look at wp_transition_post_status
function which is called almost just before save_post
action, see it on line 2942. This function does three actions transition_post_status
, {$old_status}_to_{$new_status}
and {$new_status}_{$post->post_type}
, see it on line 3273. Here we have nice action transition_post_status
, which passes old and new post statuses. This is what we need. So if new status is publish
and old status is not publish
, then the post is published. And if new status is publish
and old status is new
, then the post has been inserted. And finally if new status equals to old status, then the post has been just updated.
Here is your snippet:
add_action( 'transition_post_status', 'wpse_transition_post_status', 10, 3 );
function wpse_transition_post_status( $new_status, $old_status, $post ) {
if ( $new_status == 'publish' && $old_status == 'new' ) {
// the post is inserted
} else if ( $new_status == 'publish' && $old_status != 'publish' ) {
// the post is published
} else {
// the post is updated
}
}
P.S.: read the code of the WordPress core, each time when you in doubts, it will help you a lot!