Skip to content

Instantly share code, notes, and snippets.

@eduwass
Last active September 17, 2024 15:16
Show Gist options
  • Save eduwass/90c36565c41ac01cafe3 to your computer and use it in GitHub Desktop.
Save eduwass/90c36565c41ac01cafe3 to your computer and use it in GitHub Desktop.
Programmatically duplicating a WordPress post
<?php
/**
* Duplicates a post & its meta and returns the new duplicated Post ID.
*
* @param int $post_id The Post ID you want to clone.
* @return int The duplicated Post ID.
*/
function duplicate_post(int $post_id): int
{
$old_post = get_post($post_id);
if (!$old_post) {
// Invalid post ID, return early.
return 0;
}
$title = $old_post->post_title;
// Create new post array.
$new_post = [
'post_title' => $title,
'post_name' => sanitize_title($title),
'post_status' => 'draft',
'post_type' => $old_post->post_type,
];
// Insert new post.
$new_post_id = wp_insert_post($new_post);
// Copy post meta.
$post_meta = get_post_custom($post_id);
foreach ($post_meta as $key => $values) {
foreach ($values as $value) {
add_post_meta($new_post_id, $key, maybe_unserialize($value));
}
}
// Copy post taxonomies.
$taxonomies = get_post_taxonomies($post_id);
foreach ($taxonomies as $taxonomy) {
$term_ids = wp_get_object_terms($post_id, $taxonomy, ['fields' => 'ids']);
wp_set_object_terms($new_post_id, $term_ids, $taxonomy);
}
// Return new post ID.
return $new_post_id;
}
@pixelbart
Copy link

@IPD8

The issue lies with the get_post_custom function, which disregards meta fields starting with an underscore. Page builders often store their data in fields with underscores, such as _elementor_X. To resolve this, you should utilize wpdb and the postmeta table. By doing so, everything should function correctly.

An example that I haven't tested myself could look like the one provided. It might help solve your issues. I just wrote this example, so you don't need to provide any references or citations here.

function duplicate($post_id)
{
    $title = get_the_title($post_id);
    $oldpost = get_post($post_id);

    $post = [
        'post_title' => $title,
        'post_name' => sanitize_title($title),
        'post_status' => 'draft',
        'post_type' => $oldpost->post_type,
    ];

    $new_post_id = wp_insert_post($post);

    global $wpdb;

    $table = $wpdb->postmeta;

    $meta_data = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT meta_key, meta_value FROM $table WHERE post_id = %d",
            $post_id,
        )
    );

    foreach ($meta_data as $meta) {
        $meta_key = $meta->meta_key;
        $meta_value = maybe_unserialize($meta->meta_value);
        add_post_meta($new_post_id, $meta_key, $meta_value);
    }

    $taxonomies = get_post_taxonomies($post_id);

    if ($taxonomies) {
        foreach ($taxonomies as $taxonomy) {
            wp_set_object_terms(
                $new_post_id,
                wp_get_object_terms(
                    $post_id,
                    $taxonomy,
                    ['fields' => 'ids']
                ),
                $taxonomy
            );
        }
    }

    return $new_post_id;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment