WordPress - Add Duplicating Function to Posts and Pages Without a Plugin | Hook Agency

Construction Marketing

WordPress – Add Duplicating Function to Posts and Pages Without a Plugin

Why doesn’t WordPress allow you to clone or duplicate posts and pages? Well, I’m not exactly sure why this function was left out of the core WordPress, but I do find the…

Estimated Read Time:  4 minutes

Share: 

WordPress Post Duplication - Clone Without Plugin

Why doesn’t WordPress allow you to clone or duplicate posts and pages? Well, I’m not exactly sure why this function was left out of the core WordPress, but I do find the need to add it to WordPress to most sites I create as duplicating/cloning posts and pages comes up a lot.

There’s nothing inherantly wrong with using a plugin (Duplicate Post Plugin, or Duplicator Plugin) to do this, but I like to try to keep plugins light on websites I develop. If you do too – Here is a code snippet that will help you do this quickly.

WordPress Post Duplication - Clone Without Plugin

Just add this snippet to your website theme‘s function.php file.


/*
 * Function creates post duplicate as a draft and redirects then to the edit post screen
 */
function rd_duplicate_post_as_draft(){
	global $wpdb;
	if (! ( isset( $_GET['post']) || isset( $_POST['post'])  || ( isset($_REQUEST['action']) && 'rd_duplicate_post_as_draft' == $_REQUEST['action'] ) ) ) {
		wp_die('No post to duplicate has been supplied!');
	}
 
	/*
	 * get the original post id
	 */
	$post_id = (isset($_GET['post']) ? $_GET['post'] : $_POST['post']);
	/*
	 * and all the original post data then
	 */
	$post = get_post( $post_id );
 
	/*
	 * if you don't want current user to be the new post author,
	 * then change next couple of lines to this: $new_post_author = $post->post_author;
	 */
	$current_user = wp_get_current_user();
	$new_post_author = $current_user->ID;
 
	/*
	 * if post data exists, create the post duplicate
	 */
	if (isset( $post ) && $post != null) {
 
		/*
		 * new post data array
		 */
		$args = array(
			'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,
			'post_type'      => $post->post_type,
			'to_ping'        => $post->to_ping,
			'menu_order'     => $post->menu_order
		);
 
		/*
		 * insert the post by wp_insert_post() function
		 */
		$new_post_id = wp_insert_post( $args );
 
		/*
		 * get all current post terms ad set them to the new post draft
		 */
		$taxonomies = get_object_taxonomies($post->post_type); // returns array of taxonomy names for post type, ex array("category", "post_tag");
		foreach ($taxonomies as $taxonomy) {
			$post_terms = wp_get_object_terms($post_id, $taxonomy, array('fields' => 'slugs'));
			wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false);
		}
 
		/*
		 * duplicate all post meta just in two SQL queries
		 */
		$post_meta_infos = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$post_id");
		if (count($post_meta_infos)!=0) {
			$sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) ";
			foreach ($post_meta_infos as $meta_info) {
				$meta_key = $meta_info->meta_key;
				$meta_value = addslashes($meta_info->meta_value);
				$sql_query_sel[]= "SELECT $new_post_id, '$meta_key', '$meta_value'";
			}
			$sql_query.= implode(" UNION ALL ", $sql_query_sel);
			$wpdb->query($sql_query);
		}
 
 
		/*
		 * finally, redirect to the edit post screen for the new draft
		 */
		wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_post_id ) );
		exit;
	} else {
		wp_die('Post creation failed, could not find original post: ' . $post_id);
	}
}
add_action( 'admin_action_rd_duplicate_post_as_draft', 'rd_duplicate_post_as_draft' );
 
/*
 * Add the duplicate link to action list for post_row_actions
 */
function rd_duplicate_post_link( $actions, $post ) {
	if (current_user_can('edit_posts')) {
		$actions['duplicate'] = '<a href="admin.php?action=rd_duplicate_post_as_draft&amp;post=' . $post->ID . '" title="Duplicate this item" rel="permalink">Duplicate</a>';
	}
	return $actions;
}
 
add_filter( 'post_row_actions', 'rd_duplicate_post_link', 10, 2 );
add_filter( 'page_row_actions', 'rd_duplicate_post_link', 10, 2); /* for pages */
add_filter( 'portfolio_row_actions', 'rd_duplicate_post_link', 10, 2); /* a custom post called portfolio */

So why didn’t the duplicate post and page functionality get added to the core of WordPress? – It’s lightweight, doesn’t affect how fast a website runs and seems to be relatively unobtrusive. I tweeted at @WordPress on Twitter, and will add that curiosity to this post if or when they tweet me back.

Subscribe
Notify of
guest
6 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments
stephanie czajkowski
stephanie czajkowski
3 years ago

Hi Tim, thanks so much for sharing such a great solution! Very useful. Just wondering, I love that it duplicates acf fields as well, but is it possible to only duplicate the fields, but without their content filled in?

MarceloXP
MarceloXP
3 years ago

Awesome solution! Thank you.

Greg Arnold
4 years ago

Great work! Completely agree the duplicate feature should be core functionality. Thank you!

Tim Brown
Tim Brown
4 years ago
Reply to  Greg Arnold

Appreciate you taking the time to comment. Have a great Sunday Greg 🙂

Kim
Kim
4 years ago

Awesome solution! Thank you.

Tim Brown
Tim Brown
4 years ago
Reply to  Kim

You’re welcome, thanks for commenting 🙂

Contractors Hook Better Leads with a Google Specialized Team

Let's Start the Conversation

 Highly-Rated

 Award-Winning

 Industry-Vetted