Updating wp_options with an array on save_post results in duplicated entries

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');
}

Leave a Comment