I had something similar going on when I tried to use the wp_editor()
function while inside a custom metabox. It was wanting to save multiple times.
Take a look at this.
// SAVE Metabox for admin response
add_action('post_updated', 'display_jwl_wp_etickets_response_meta_box_save');
function display_jwl_wp_etickets_response_meta_box_save( $post_id ){
if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
return;
if( !isset( $_POST['jwl_wp_etickets_editor_box_nonce_check'] ) || !wp_verify_nonce( $_POST['jwl_wp_etickets_editor_box_nonce_check'], 'jwl_wp_etickets_editor_box_nonce' ) )
return;
global $post;
$post_type_object = get_post_type_object( $post->post_type );
if ( !current_user_can( $post_type_object->cap->edit_post, $post->ID ) ) {
return;
}
//$values = get_post_custom( $post_id );
$editor_id = 'jwl_wp_etickets_response_editor';
$meta_key = 'jwl_wp_etickets_response_box_select';
$content_post = get_post($post_id);
$old_content = $content_post->post_content;
if(isset($_POST[$editor_id]) && !empty($_POST[$editor_id])) {
if ( !wp_is_post_revision( $post_id ) ){ //IMPORTANT - Can cause infinite loop otherwise : codex - wp_update_post (see note a few lines down)
$new_content="<div class="eMember_admin_div"><p class="eMember_adminname_response"><strong>Admin</strong> on <strong>".date('F j, Y @ g:i a').'</strong> said:</p>'.$_POST[$editor_id].'</div>';
$update_content = array(
'ID' => $post_id,
'post_content' => $new_content.$old_content
);
// IMPORTANT!!!!
//*****
//***** Apparently the 'post_updated' action likes to fire on every WP process while saving the content.
//***** Since we are also firing on 'wp_update_post'; we are getting stuck in a loop.
//***** To get around, unhook the function before sending the revised content with 'wp_update_post'.
//***** This will prevent clashes between 'post_updated' and 'wp_update_post" firing at the same time.
//***** DAMN YOU WORDPRESS!!
//*****
// Unhook this function so it doesn't loop infinitely
remove_action('post_updated', 'display_jwl_wp_etickets_response_meta_box_save');
// Update the post, which calls save_post again
wp_update_post( $update_content );
// Let's check the 'ticket state', and if queued... let's update it to 'in progress'
$terms_types = wp_get_post_terms( $post->ID, 'jwl_wp_etickets_states');
foreach ($terms_types as $term_type) {
if ($term_type == 'Queued' || !empty($term_type)) {
wp_set_post_terms( $post_id, __('In Progress','wp_etickets_lang'), 'jwl_wp_etickets_states' );
}
}
// Do the same for post meta for cool admin filtering
update_post_meta( $post_id, 'jwl_wp_etickets_states_box_select', __('In Progress','wp_etickets_lang'), __('Queued','wp_etickets_lang') );
// Re-hook this function
add_action('post_updated', 'display_jwl_wp_etickets_response_meta_box_save');
}
}
}
Look at line #43. See how I had to remove_action
the original function… run the update… and then add_action
back again?
That may be what you need to do as well.
Here is a quick “example” code:
add_action('post_updated', 'my_metabox_save');
function my_metabox_save() {
// Run checks
// Unhook this function so it doesn't loop infinitely
remove_action('post_updated', 'my_metabox_save');
// Run your update stuff
// Re-hook this function
add_action('post_updated', 'my_metabox_save');
}