How to merge two or more WordPress posts?

I need to be able to merge two or more posts. What is the exact query (or queries) to make this happen?

The scenario is multiple recommendations that need to be merged into one. I have already sorted out comments merging and meta merging.

Read More

Let’s say a user recommends Bill Gates, another one Gates Bill and another one makes a typo and adds Bil Gates. I need to merge these three posts and choose the destination one.

UPDATE:

What I need is a complete SQL query for deleting a post and all references to that post. Something like this pseudo-code:

DELETE FROM wp_posts WHERE id = X;
DELETE FROM wp_posts_meta WHERE id = X;
DELETE FROM wp_another_table WHERE id = X;
DELETE FROM wp_yet_another_table WHERE id = X;

where X is the ID of my post.

The code (or plugin) shouldn’t auto-detect duplicates. I will present the user a dropdown with a list of posts and the “Delete” option. Before deleting, I will copy the post content from one post to the other using an SQL UPDATE query.

UPDATE 2:

I think I found something, I’ll have to check though:

    $custom_field_keys = get_post_custom_keys($postid);
    foreach($custom_field_keys as  $key => $value) {
        $valuet = trim($value);
        if('_' != $valuet{0} ){
               delete_post_meta($postid, $key, '');
        }
   }
   $result = wp_delete_post($postid);

Related posts

Leave a Reply

1 comment

  1. The requirements you are describing require much more of an explanation than is really suitable here. A simple solution might be to mark the duplicate posts as duplicates via a meta box on the post screen. This meta box would have one input: A reference to another post.

    Check out this tutorial on how to build a custom meta box.

    Suppose you’ve set up a meta box that will allow the user to mark a post that is a duplicate of another post. Say the duplicate post is marked with a meta key _duplicate_of_post, whose meta value is the canonical post’s post ID.

    You can then on filter the_posts filter to pull together any duplicates, folding the the canonical post together with any of its duplicates:

    function my_the_posts_filter( $posts, $query ) {
        // Only operate on the main query.
        if( !$query->is_main_query() )
             return $posts;
    
        // Store canonical posts here. 
        $canonicals = array();
    
        // Store the duplicates here, keyed by canonical post ID
        $duplicates = array();
    
        foreach( $posts as $post ) {
            if( $dupe_id = get_post_meta( $post->ID, '_duplicate_of_post', true ) ) {
               $canonicals[] = get_post( $dupe_id ); 
    
               $duplicates[$dupe_id] = get_posts( array( 'meta_key' => '_duplicate_of_post', 'meta_value' => $dupe_id, 'posts_per_page' => -1, 'post__not_in' => $post->ID ) );
            }
            else {
               $canonicals[] = $post;
    
               // Get all posts who have this marked as duplicate
               $duplicates[$post->ID] = get_posts( array( 'meta_key' => '_duplicate_of_post', 'meta_value' => $post->ID, 'posts_per_page' => -1 ) );
            }
        }
    
        // Append all of the other post content to the canonicals separated
        // by two newlines
        foreach( $canonicals as $post )
           $post->post_content .= array_join( "nn", wp_list_pluck( $duplicates[$dupe_id], 'post_content' ) );
    
        return $canonicals;
    }
    add_filter( 'the_posts', 'my_the_posts_filter', 10, 2 );
    

    One caveat in implementation of the post reference meta box is that you’d have to implement the logic to ensure that you can’t set a post as a duplicate post is if it’s already marked as a “master” post by another post. Without that restriction, the example above will break in unexpected ways.

    Update

    You can also hook on save_post, combine, then trash posts marked as duplicates:

    function my_save_post( $post ) {
        // Don't do on autosave
        if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return;
    
        if( isset( $_POST['_duplicate_of_post'] ) && ( $dupe_of_id = (int) $_POST['_duplicate_of_post'] ) && ( $source = get_post( $dupe_of_id ) ) ) {  
           // Add this post's content to the canonical version               
           $update = array( 'ID' => $source->ID, 'post_content' => $source->post_content );
           $update['post_content'] .= "nn" . $post->post_content;
    
           // Update canonical
           wp_update_post( $update );
    
           // Trash this post
           wp_trash_post( $post->ID );
        }
    }
    add_action( 'save_post', 'my_save_post' );
    

    This is the most basic of examples. It’s expecting a form field on the edit post screen named _duplicate_of_post which contains the canonical post’s ID. Note that I’m using ONLY the WordPress API, which is something you should always aspire to do while developing theme and plugin code.