I am creating a plugin which syncs both standard WP data and custom fields within a custom meta box on post edit pages, to an external resource using SQL queries. However my functions are currently only working when managing single posts and I am trying to add support for existing bulk actions (Move to Trash, Restore From Trash, and Edit). Right now my sync function is hooked into save_post and I have added support for deleting from my external resource using ‘wp_trash_post’ and reinserting using ‘untrashed_post’ (although the this only works when clicking Restore from within the Trash, and not when clicking Undo in the admin notice after Trashing). Here is the code which is located in the __construct for my add metabox class:
add_action( 'save_post', array( $this, 'save_post_function' ) ); //which eventually calls myOtherClass::runs_sync_to_external_resource_SQL_query($post_id);
add_action( 'wp_trash_post', 'my_delete_function' );
function my_delete_function( $post_id ){
myClass::runs_delete_from_resource_SQL_query($post_id);
}
add_action( 'untrashed_post', 'my_undelete_function' );
function my_undelete_function($post_id) {
myOtherClass::runs_sync_to_external_resource_SQL_query($post_id);
}
I have read this blog post about adding custom bulk actions (which seems to be the go to reference on the topic), but it is not quite what I am looking for as I do not need to modify the bulk actions select drop down and add a custom action, but simply hook into the existing trash and restore bulk actions.
Additionally, I am going to need to hook into the Edit bulk action because some the data being synced to my external resource can be edited from that action (categories, tags, post format and post status).
Lastly, I need to get the Undo button to run my restore function. I suspect that it doesn’t work because its tied to bulk actions though.
Any advice? Thanks in advance
EDIT: Here is the revised code from above using status transition hooks:
add_action( 'save_post', array( $this, 'save_post_function' ) ); //which eventually calls pluginname_sync::pluginname_syncpost($post->ID);
add_action( 'transition_post_status', 'cp_sync', 10, 3 );
function cp_sync( $new_status, $old_status, $post ) {
if ( $old_status == 'publish' && $new_status != 'publish' ) {
pluginname_sync::pluginname_delete($post->ID);
}
if ( $old_status != 'publish' && $new_status == 'publish' ) {
pluginname_sync::pluginname_syncpost($post->ID);
}
}
As you describe, you want to sync data when a post is trashed, edited or untrashed. You are trying with save_post
action, but it fires only on post edit screens (according with codex, this action fires on import, post/page edit form, xmlrpc, or post by email), so you think you need to hook also on bulk actions and quick edit but you are wrong. There are not specific saving actions that are triggered when a post is edited through bulk actions or quick edit (the link you posted about adding custom bulck actions is for that, to add custom bulk actions, not for perform tasks on predefined bulk actions).
From my point of view, there is nothing more appropiate for post status transitions than syncing data.
You have tried post status transitions but with wrong logic. For example, you run de delete sync function when a post transits from be published to not published, but this situation doesn’t mean a post is deleted: a not published post can be trashed, a draft, a future post, etc.
Let’s see some examples:
add_action( 'transition_post_status', 'cp_sync', 10, 3 );
function cp_sync( $new_status, $old_status, $post ) {
// Check $old_status also if you need specific actions
// when the post transits from a specific status
if ( $new_status == 'draft' ) {
// The post is now draft, no matter what status it had previously
// sync draft posts here
}
if ( $new_status == 'publish' ) {
// The post is now published, no matter what status it had previously
// sync published posts here
}
if ( $new_status == 'trashed' ) {
// The post is now in the trash, no matter what status it had previously
// sync trashed posts here
}
// Cotinue checking more post statues if you need (future, private, etc)
// For a complete list, see https://codex.wordpress.org/Post_Status_Transitions
}
There is not status transition for deleted post, you must use any of the actions described in the docs for delete_post
action; I would use before_delete_post
if you need to catch all the post data:
add_action( 'before_delete_post', 'my_func' );
function my_func( $postid ){
// Post has been deleted
pluginname_sync::pluginname_delete( $postid );
}
EDIT
Exmpale: Sync only published posts, delete the rest from external database:
add_action( 'transition_post_status', 'cp_sync', 10, 3 );
function cp_sync( $new_status, $old_status, $post ) {
// This will cover the transition from any status to published,
// including published to published.
if ( $new_status == 'publish' ) {
pluginname_sync::pluginname_syncpost($post->ID);
} else {
pluginname_sync::pluginname_delete($post->ID);
}
}
add_action( 'before_delete_post', 'my_func' );
function my_func( $postid ){
pluginname_sync::pluginname_delete( $postid );
}