Pay money and get answers for your WordPress questions (more info)

Create 'duplicate my posts' functionality

  • SOLVED

I have a competition entry site that stores users' entries as a custom type post with a custom meta_key (entryyear) storing the year (2012). I would like to set up a function that would (a) get all the current user's posts (of specific post type - "contestentry"), and (b) clone/dup all these posts, but change that (entryyear) meta_key's value to 2013, and set the post status to published. I would need to be able to create a link on a page for a logged-in user that would call the function.

I had thought of starting from the code of a plugin like [[LINK href="http://wordpress.org/extend/plugins/duplicate-post/"]]Duplicate Posts[[/LINK]] and tweaking to my purposes. Anyone interested in whipping this up?

Thanks!!

Answers (3)

2013-01-28

Naveen Chand answers:

Hi Adam,

Here is the important code that extracts posts of the current user from the custom post type and then duplicates it and then adds a new metakey to the newly created post. Here is it:


if ( is_user_logged_in() ):

global $wpdb, $current_user;
get_currentuserinfo();
$user_contestentries = $wpdb->get_results(
"
SELECT *
FROM $wpdb->posts
WHERE post_type = 'contestentry'
AND post_author = $current_user->ID;
"
);

foreach ( $user_contestentries as $user_contestentry )
{
$new_post_title = $user_contestentry->post_title;
$new_post_content = $user_contestentry->post_content;
$new_post_type = $user_contestentry->post_type;
$new_post_author = $user_contestentry->post_author;

//here is where we create our new post - a duplicate of the above
// Create post object
$new_post = array(
'post_title' => $new_post_title,
'post_content' => $new_post_content',
'post_status' => 'publish',
'post_type' => $new_post_type,
'post_author' => $new_post_author

$new_post_id = wp_insert_post( $new_post, $wp_error );

add_post_meta($new_post_id, 'entryyear', '2013', true);

);

}

else :

echo "not logged in";

endif;


I have to create a link that user clicks. I will be doing that and updating this code shortly. You can wait until then and meanwhile you can study this code. You would need to enter this in a template file - preferably in a new page template and assign that template to a page which users can access. Let me get back to you with the completed code.


Naveen Chand comments:

Hi Adam,

Here is the revised code. What it does is this:

1. First it checks if user is logged in or not.
2. If user is logged in, it gives him a link to the same page but with a GET variable attached to the link.
3. If the user clicks on the link, it checks if the GET variable has action=duplicate and then begins the process.
4. The process begins by checking if the user has already duplicated in the past. If so it will not continue ahead.
5. If it is the very first time the user is carrying out this action, then the code runs to pull the data, duplicate them, assign the custom field and at the end .. creates a user meta to declare and store that duplicate action is done.

Here is the code that you MUST insert inside the loop - as I suggested earlier, use this inside the new page template!


if ( is_user_logged_in() ):
echo "<a href=" .get_page_link() ."?action=duplicate>Click here to duplicate previous posts</a>";

if($_GET["action"]='duplicate') {

global $wpdb, $current_user;
get_currentuserinfo();
$check_if_done = get_user_meta($current_user->ID, 'duplicate_action', true);

if (empty($check_if_done)) {

$user_contestentries = $wpdb->get_results(
"
SELECT *
FROM $wpdb->posts
WHERE post_type = 'contestentry'
AND post_author = $current_user->ID;
"
);

foreach ( $user_contestentries as $user_contestentry )
{
$new_post_title = $user_contestentry->post_title;
$new_post_content = $user_contestentry->post_content;
$new_post_type = $user_contestentry->post_type;
$new_post_author = $user_contestentry->post_author;

//here is where we create our new post - a duplicate of the above
// Create post object
$new_post = array(
'post_title' => $new_post_title,
'post_content' => $new_post_content',
'post_status' => 'publish',
'post_type' => $new_post_type,
'post_author' => $new_post_author

$new_post_id = wp_insert_post( $new_post, $wp_error );

add_post_meta($new_post_id, 'entryyear', '2013', true);

);

}
add_user_meta( $new_post_author, 'duplicate_action', 'done', true); //to keep a record that user has already duplicated

} //end of if empty check_if_done

else { echo "You have already duplicated the posts once"; }

} //end of get if

else :

echo "not logged in";

endif;


Adam Bundy comments:

@Naveen, looks great! You have understood perfectly what I was looking for - the added user_meta field was even a bonus that I was going to add later! I will test this, but would it be possible to wrap this in a named function declaration, like nc_duplicate_userposts(); so that I could put this in my functions.php and call it anywhere on a template? Thank you!


Adam Bundy comments:

@Naveen, I tried to use the above code, but it appears there might be some syntax or formatting errors. Could you please make a couple modifications for me and try this in a sandbox environment to make sure formatting is correct?

1. could the check_if_done occur above the insert for the link so that if it has been done, the link doesn't appear?

2. I have a few custom taxonomies and custom post_meta keys that aren't being copied over. Is there a way to get those for the existing posts and set them for the new posts comprehensively, or does that have to be done one-by-one?

Thanks Naveen! If I can get these couple things completed I'll be happy to call it good and award the cash.


Naveen Chand comments:

Sure Adam, I'll try this in my demo site and get back to you. I'll wrap it in a function and test it. I think it is possible to get the custom taxonomies and custom post_meta. Firstly, let me check for syntax errors. I've coded that in a hurry.


Adam Bundy comments:

@Naveen, thanks! I look forward to it. I had hoped it was possible to get all the post_meta as an array and assign it to the dup posts all at once rather than having to assign each manually.


Naveen Chand comments:

@Adam,

I have rectified the syntax errors. The code is working without any errors. I have tried in a sandbox and it duplicated successfully a post in a custom post-type after I clicked the link. Here is the modified code:

<?php
if ( is_user_logged_in() ) {

echo "<a href='" .get_page_link() ."?action=duplicate'>Click here to duplicate previous posts</a>";

if($_GET["action"]='duplicate') {

global $wpdb, $current_user;
get_currentuserinfo();
$check_if_done = get_user_meta($current_user->ID, 'duplicate_action', true);

if (empty($check_if_done)) {

$user_contestentries = $wpdb->get_results(

"
SELECT *
FROM $wpdb->posts
WHERE post_type = 'trading-calls'
AND post_author = $current_user->ID;
"
);

foreach ( $user_contestentries as $user_contestentry )

{
$new_post_title = $user_contestentry->post_title;
$new_post_content = $user_contestentry->post_content;
$new_post_type = $user_contestentry->post_type;
$new_post_author = $user_contestentry->post_author;

//here is where we create our new post - a duplicate of the above

// Create post object
$new_post = array(
'post_title' => $new_post_title,
'post_content' => $new_post_content,
'post_status' => 'publish',
'post_type' => $new_post_type,
'post_author' => $new_post_author
);

$new_post_id = wp_insert_post( $new_post, $wp_error ); //inserted a new post
add_post_meta($new_post_id, 'entryyear', '2013', true); //inserted post meta to the newly created post
}

add_user_meta( $new_post_author, 'duplicate_action', 'done', true); //to keep a record that user has already duplicated

} //end of if empty check_if_done


else { echo "You have already duplicated the posts once"; }

} //end of get if

} // end of user logged in if-condition
else {

echo "not logged in";

} //end of if user is not logged in else-condition
?>


I will now work on wrapping it in a function and then getting all custom taxonomies attached to original posts. Meanwhile, you can have a look at the code.


Naveen Chand comments:

Adams,

Here is the code wrapped in a function which you can call from anywhere. I have also slightly modified the code by echoing the link after checking for check_if_done. Also, in my previous post, I have used my own post_type (trading-calls) that I have in my demo site. But in this code below I have changed it to 'contestentry'.


function duplicate_custom_posts() {

if ( is_user_logged_in() ) {

global $wpdb, $current_user;
get_currentuserinfo();
$check_if_done = get_user_meta($current_user->ID, 'duplicate_action', true);

if (empty($check_if_done)) {

echo "<a href='" .get_page_link() ."?action=duplicate'>Click here to duplicate previous posts</a>";
if ( isset( $_GET['action'] ) && !empty( $_GET['action'] ) && ($_GET['action']=="duplicate") ) {

$user_contestentries = $wpdb->get_results(

"
SELECT *
FROM $wpdb->posts
WHERE post_type = 'contestentry'
AND post_author = $current_user->ID;
"
);

foreach ( $user_contestentries as $user_contestentry )

{
$new_post_title = $user_contestentry->post_title;
$new_post_content = $user_contestentry->post_content;
$new_post_type = $user_contestentry->post_type;
$new_post_author = $user_contestentry->post_author;

//here is where we create our new post - a duplicate of the above

// Create post object
$new_post = array(
'post_title' => $new_post_title,
'post_content' => $new_post_content,
'post_status' => 'publish',
'post_type' => $new_post_type,
'post_author' => $new_post_author
);

$new_post_id = wp_insert_post( $new_post, $wp_error ); //inserted a new post
add_post_meta($new_post_id, 'entryyear', '2013', true); //inserted post meta to the newly created post
}

add_user_meta( $new_post_author, 'duplicate_action', 'done', true); //to keep a record that user has already duplicated

} //end of get if

} //end of if check_if_done is empty

else { echo "You have already duplicated the posts once"; }

} // end of user logged in if-condition
else {

echo "not logged in";

} //end of if user is not logged in else-condition

} //end of the function duplicate_custom_posts


Using this below code, you can now call this function anywhere (<em>preferably within any existing wp loop because it uses "get_page_link()"</em>):

<?php duplicate_custom_posts();?>


Adam Bundy comments:

@Naveen - awesome. We're really close. I just need to get it to copy over the settings for one custom taxonomy (entrycategory) and, if possible, all of the post's post_meta. If that can't be done all in one shot, I can provide a list of those meta keys.

Also, your formatting is pretty tough for me to read. Would you mind formatting like this pastebin?

http://pastebin.com/aRdaDKYu

Thank you Naveen!


Naveen Chand comments:

@Adam,

Here is the code for getting all of the post's meta and attaching them to the newly created posts.


//Get all the post meta for the existing post that is being processed and attach them to the newly created posts
$existing_post_id = $user_contestentry->ID;
$existing_postmeta_query = $wpdb->get_results( "SELECT * FROM $wpdb->postmeta WHERE post_id = $existing_post_id;");
foreach ( $existing_postmeta as $epm ) {
add_post_meta($new_post_id, $epm->meta_key, $epm->meta_value, true);
}


You must insert above code after this line:

$new_post_id = wp_insert_post( $new_post, $wp_error ); //inserted a new post


If this works, then let me attempt a similar coding for getting the taxonomy settings.

And, Sorry about the formatting.

Thanks,
Naveen


Naveen Chand comments:

@Adam,

Sorry, there is a small error in my previous post. Please change <strong>$existing_postmeta_query</strong> to <strong>$existing_postmeta</strong>. Thanks.


Adam Bundy comments:

Thanks Naveen - that required a little shuffling but it works! Here is my revised function:

http://pastebin.com/aRdaDKYu

If we can get the taxonomy licked, we're done. Thanks!


Naveen Chand comments:

Adam,

These two lines should do the taxonomy trick.

$term_list = wp_get_post_terms($existing_post_id, 'entrycategory', array("fields" => "ids"));
wp_set_post_terms( $new_post_id, $term_list, 'entrycategory', true );


$term_list will pull all the term_ids (under 'entrycategory') attached to the existing post. And then we use wp_set_post_terms function to insert this array for our newly created post.

Let me know if it throws any bugs.


Adam Bundy comments:

Done! Thanks Naveen!

2013-01-28

Kiet Luong answers:

Hi, Let me help you do this.
skype: [[LINK href="http://wpquestions.com/user/profile/id/10125"]]kioluong[[/LINK]]

Regards !


Adam Bundy comments:

@Kiet, do you need any additional info? I think the necessary steps are outlined in the original question. Let me know if you have any questions.


Kiet Luong comments:

yes I need some more things such as site..., did you use skype or gmail ? can we discuss via chatting app ?
Regards !


Adam Bundy comments:

@Kiet, I'd rather not give access to the site. I would prefer to have a generic function created that does the outlined tasks.


Kiet Luong comments:

yes I understand, basic logged-in user can call that function to clone/dup their posts with changed meta value.

2013-01-28

Arnav Joy answers:

so you want that when ever user logged in , show lists of posts that belongs to that user with a link which when clicked change post status to publish and meta key to year 2013?

I have one question , why you want to duplicate post ? you can also change the post status to publish , please clear this.


Arnav Joy comments:

create a page and select "Create Duplicate Post" as its post template then use following code:-

<?php
/*
Template Name: Create Duplicate Post
*/

if ( is_user_logged_in() && $_POST['submit'] ) {
global $current_user;
get_currentuserinfo();
$args=array(
'author' => $current_user->ID,
'post_type' => 'contestentry',
'post_status' => 'draft',
'posts_per_page' => -1,
'caller_get_posts'=> 1
);
$my_query = null;
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {

while ($my_query->have_posts()) : $my_query->the_post(); ?>
<?php
$already_done = get_post_meta( get_the_ID(),'already_done',true );
if( $already_done != 1 ) {
$new_post = array(
'menu_order' => $post->menu_order,
'comment_status' => $post->comment_status,
'ping_status' => $post->ping_status,
'post_author' => $current_user->ID,
'post_content' => $post->post_content,
'post_excerpt' => $post->post_excerpt ,
'post_mime_type' => $post->post_mime_type,
'post_parent' => $post->post_parent ,
'post_password' => $post->post_password,
'post_status' => 'publish',
'post_title' => $post->post_title.time(),
'post_type' => $post->post_type,
);
$new_post_id = wp_insert_post($new_post);

$post_meta_keys = get_post_custom_keys($post->ID);

if( !empty( $post_meta_keys ) ){
foreach ($post_meta_keys as $meta_key) {
$meta_values = get_post_custom_values($meta_key, $post->ID);
foreach ($meta_values as $meta_value) {
$meta_value = maybe_unserialize($meta_value);
if( $meta_key == 'entryyear' )
add_post_meta( $new_post_id, $meta_key, 2013 );
else
add_post_meta( $new_post_id, $meta_key, $meta_value );
}
}
}
update_post_meta( $new_post_id, 'already_done', 1 );
}

endwhile;
}
wp_reset_query();
}

get_header();

?>
<div>
<?php
if ( is_user_logged_in() ) {
global $current_user;
get_currentuserinfo();
$args=array(
'author' => $current_user->ID,
'post_type' => 'contestentry',
'post_status' => 'draft',
'posts_per_page' => -1,
'caller_get_posts'=> 1
);
$my_query = null;
$my_query = new WP_Query($args);
if( $my_query->have_posts() ) {
echo 'Your Posts';
while ($my_query->have_posts()) : $my_query->the_post(); ?>

<p><?php the_title(); ?></p>
<?php
endwhile;
}
wp_reset_query();
?>
<form action="" method="post">
<input type="submit" name="submit" value="Create Post" />
</form>
<?php
}
else
echo 'Please login to see this page.';
?>
</div>
<?php get_footer(); ?>