Duplicating custom post type and its posts

Backup your database

You can do this pretty easily. I created a proof-of-concept for you to try out. I would backup the database before running this.

Run the plugin

Configure the plugin by setting $post_type_1 and $post_type_2 variables to your source and destination post types.

To run this plugin, you need to be logged in as an administrator. Then, visit:

http://yourdomain.com/wp-admin/?duplicate-posts=magic-password

/*
Plugin Name: Post Duplicator
Description: Duplicate posts to a new post type
Version: 0.1
Author: WPSE
Author URI: http://wordpress.stackexchange.com
License: GPL2
*/

add_action('admin_init', 'foo_duplicate_posts', 99999);
function foo_duplicate_posts(){

    # Only allow admins to run the script
    if(!current_user_can('manage_options'))
        return;

    # Check if keyword is set
    if(!isset($_GET['duplicate-posts']))
        return;

    # Check if keyword matches
    if($_GET['duplicate-posts'] !== 'magic-password')
        return;

    global $wpdb;

    # Configure post types
    $post_type_1 = 'foo';
    $post_type_2 = 'bar';

    $query = $wpdb->prepare("SELECT * FROM $wpdb->posts WHERE post_type="%s"", $post_type_1);
    $posts = $wpdb->get_results($query, ARRAY_A);
    foreach($posts as $post){

        # Post info is already stored in an array
        # Set the post_type to the new post type
        $post['post_type'] = $post_type_2;

        # Insert new post
        $new_post = wp_insert_post($post);

        # Proceed if new post was created
        if($new_post){
            # Print a success message to the screen
            show_message("{$post['post_title']} was duplicated from #$post['ID'] to #$new_post");

            # Get source post's post meta
            $post_meta = get_post_custom($post['ID']);

            # Convert all postmeta to new post
            if(is_array($post_meta))
                foreach($post_meta as $k => $v)
                    update_post_meta($new_post, $k, $v[0]);
        }
        else
            # Print an error message to the screen
            show_message("{$post['post_title']} was not duplicated.");
    }
    # Stop the admin area from loading to get a clean reading of our output messages
    exit;
}

This plugin accounts for the basic post information and its postmeta. It does not account for revisions, auto-drafts, or attachments. You can run similar loops within the foreach loop to duplicate those sub post types.

Leave a Comment