0

I need your help.

I would like to authors to be able to click a button on frontend to duplicate already existing posts on my page and modify and save the duplicated copy as their own.

However, I don't want them to edit the master posts nor delete them.

Is this possible? since duplicating post is more of editing? Is there any plugin or snippet to achieve this?

Thanks.

1
  • Your question is too abstract. This kinda questions as well as asking plugin suggestion generally prohibited here. – CodeMascot Jan 6 '17 at 4:03
0

Duplicating a post is a 3-step process:

  1. Create a new post using data from the source post.
  2. Copy the source post's metadata over to the new post.
  3. Copy the source post's terms over to the new post.

Since you're only reading from the source post, duplicating is not more of editing, as you suggest.

Here is a function can do that for you:

/**
 * Duplicate a post as a new draft, setting the current user as author. 
 * Redirect to the post edit screen when done.
 *
 * @param int|string $id A valid post id.
 */
function giant_duplicate_post($id)
{
    // Check for a valid post id.
    if (! is_numeric($id) || $id <= 0)
    {
        // Return, die() or throw an exception, depending on your own requirements.
        return;
    }

    // Get the source post.
    if (! $source = get_post($id))
    {
        // Return, die() or throw an exception, depending on your own requirements.
        return;
    }

    // Create an array suitable for wp_insert_post().
    // We are using data from the source post, but replacing the original author
    // id with the id of the current user.
    $args = array(
        'post_author'           => get_current_user_id(),
        'post_content'          => $source->post_content,
        'post_content_filtered' => $source->post_content_filtered,
        'post_title'            => $source->post_title,
        'post_excerpt'          => $source->post_excerpt,
        'post_status'           => 'draft',
        'post_type'             => $source->post_type,
        'comment_status'        => $source->comment_status,
        'ping_status'           => $source->ping_status,
        'post_password'         => $source->post_password,
        'to_ping'               => $source->to_ping,
        'pinged'                => $source->pinged,
        'post_parent'           => $source->post_parent,
        'menu_order'            => $source->menu_order,
    );

    $new_id = wp_insert_post($args);

    // Bail if post creation did not succeed.
    if (is_wp_error($new_id))
    {
        // Return, die() or throw an exception, depending on your own requirements.
        return;
    }

    // Copy the source post's taxonomies over to the newly created duplicate.
    foreach (get_object_taxonomies($source->post_type) as $taxonomy)
    {
        $terms = wp_get_object_terms($id, $taxonomy, array('fields' => 'slugs'));
        wp_set_object_terms($new_id, $terms, $taxonomy, false);
    }

    // Copy the source post's metadata over to the newly created duplicate.
    foreach (get_post_meta($id) as $key => $values)
    {
        foreach ($values as $value)
        {
            add_post_meta($new_id, $key, maybe_unserialize($value));
        }
    }

    // Optional: Redirect to the newly created post's edit page.
    wp_redirect(get_edit_post_link($new_id, null));
}

WordPress will happily assign any post you create programmatically to any user you specify.

Triggering the process

You ask that the trigger to the process is shown at the frontend. It could be a simple link or a form. For example, you could add this to single.php:

<form method="post">
    <input type="hidden" name="source_id" value="<?php echo esc_attr($post->ID) ?>">
    <input type="hidden" name="nonce" value="<?php echo wp_create_nonce("giant_duplicate_post_{$post->ID}") ?>">
    <input type="submit" value="Duplicate">
</form>

Submitting the form in the example above, will trigger a POST request which you will need to handle with something like the following:

function giant_handle_duplicate_post_request()
{
    $source_id = isset($_REQUEST['source_id']) ? $_REQUEST['source_id'] : null;
    $nonce = isset($_REQUEST['nonce']) ? $_REQUEST['nonce'] : null;

    // Check that the current user is authorised to duplicate posts 
    // and that the process was explicitly triggered from the front end.
    if (is_user_logged_in()
        && current_user_can('edit_posts')
        && $source_id
        && $nonce
        && wp_verify_nonce($nonce, "giant_duplicate_post_{$source_id}"))
    {
        giant_duplicate_post($source_id);
    }
}

add_action('parse_request', 'giant_handle_duplicate_post_request');

A word of caution

It cannot be stressed enough that YOU need to make sure that only authenticated users can trigger the duplication process!

In the examples above, we're checking that the user is logged in, has the edit_posts capability and a valid nonce has been supplied. Your requirements may be different, so take a minute to think it through and apply the required restrictions and safeguards.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.