Duplicate Post, Page and CPTs

Adds functionality to duplicate posts, pages and CPTs.

PHP
/**
 * Snippet Name:     Duplicate Post, Page and CPTs
 * Snippet Author:   coding-bunny.com
 * Description:      Adds functionality to duplicate posts, pages and CPTs.
 */

// Duplicate the post as a draft
function cb_duplicate_post_as_draft() {
    global $wpdb;
    
    // Check if the 'post' parameter is provided in the GET or POST request
    if (!isset($_GET["post"]) && !isset($_POST["post"])) {
        wp_die("No post to duplicate has been provided!");
    }

    // Verify nonce for security
    if (!isset($_GET["duplicate_nonce"]) || !wp_verify_nonce($_GET["duplicate_nonce"], basename(__FILE__))) {
        return;
    }

    // Get the post ID and confirm it's an integer
    $post_id = isset($_GET["post"]) ? absint($_GET["post"]) : absint($_POST["post"]);

    // Fetch the post object and check if it exists
    $post = get_post($post_id);
    if (!$post) {
        wp_die("Failed to create post, original post not found: " . esc_html($post_id));
    }

    // Set current user as the new post author
    $current_user = wp_get_current_user();
    $new_post_author = $current_user->ID;

    // Prepare the post arguments
    $args = [
        "comment_status" => $post->comment_status,
        "ping_status"    => $post->ping_status,
        "post_author"    => $new_post_author,
        "post_content"   => $post->post_content,
        "post_excerpt"   => $post->post_excerpt,
        "post_name"      => $post->post_name,
        "post_parent"    => $post->post_parent,
        "post_password"  => $post->post_password,
        "post_status"    => "draft",
        "post_title"     => $post->post_title . " (Copy)",
        "post_type"      => $post->post_type,
        "to_ping"        => $post->to_ping,
        "menu_order"     => $post->menu_order
    ];

    // Insert the new post into the database
    $new_post_id = wp_insert_post($args);

    // Copy taxonomies (categories, tags, etc.) from the original post
    $taxonomies = get_object_taxonomies($post->post_type);
    foreach ($taxonomies as $taxonomy) {
        $post_terms = wp_get_object_terms($post_id, $taxonomy, ["fields" => "slugs"]);
        wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
    }

    // Copy all post meta data from the original post
    $post_meta_infos = $wpdb->get_results(
        $wpdb->prepare("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id = %d", $post_id)
    );
    if (!empty($post_meta_infos)) {
        foreach ($post_meta_infos as $meta_info) {
            $meta_key   = $meta_info->meta_key;
            $meta_value = sanitize_meta($meta_key, $meta_info->meta_value, "post");
            $wpdb->insert($wpdb->postmeta, [
                "post_id"    => $new_post_id,
                "meta_key"   => $meta_key,
                "meta_value" => $meta_value
            ]);
        }
    }

    // Redirect to the post list screen and show a success message
    $redirect_url = admin_url("edit.php?post_type=" . $post->post_type);
    wp_redirect(add_query_arg("message", "101", $redirect_url));
    exit();
}
add_action("admin_action_duplicate_post_as_draft", "cb_duplicate_post_as_draft");

// Add 'Duplicate' link to post actions
function cb_duplicate_post_link($actions, $post) {
    if (current_user_can("edit_posts")) {
        $actions["duplicate"] = '<a href="' .
            wp_nonce_url("admin.php?action=duplicate_post_as_draft&post=" . $post->ID, basename(__FILE__), "duplicate_nonce") .
            '" title="Duplicate this item" rel="permalink">Duplicate</a>';
    }
    return $actions;
}
add_filter("post_row_actions", "cb_duplicate_post_link", 10, 2);
add_filter("page_row_actions", "cb_duplicate_post_link", 10, 2);

// Apply 'Duplicate' link to custom post types
function cb_apply_duplicate_post_link_to_cpts() {
    $post_types = get_post_types(["public" => true], "names");
    foreach ($post_types as $post_type) {
        add_filter("{$post_type}_row_actions", "cb_duplicate_post_link", 10, 2);
    }
}
add_action("admin_init", "cb_apply_duplicate_post_link_to_cpts");

// Display success message after duplication
function cb_show_duplicate_admin_notice() {
    if (isset($_GET['message']) && $_GET['message'] === '101') {
        echo '<div class="notice notice-success is-dismissible"><p>' . esc_html('Post duplicated successfully.') . '</p></div>';
    }
}
add_action('admin_notices', 'cb_show_duplicate_admin_notice');

How To Implement This Solution?

Leave a Reply

Your email address will not be published. Required fields are marked *

My Agile Privacy
This site uses technical and profiling cookies. You can accept, decline or customize cookies by pressing the desired buttons. By closing this policy you will continue without accepting.

Need help?

Choose one of the following options:

Powered by CodingBunny