NB: Make sure you do a back up of your theme, files and database before attempting the tutorials

How to Duplicate Articles Without Plugins

---- Last modified : Oct 01 2022

Estimated reading time : 4 minutes, 37 seconds - 231 words

With this tutorial, we will use a function that will allow you to duplicate a WordPress post without using a plugin. Admins can easily duplicate a draft to save time.

It is important to understand that while duplicating is a time-saver, we have to be careful with the next post. We need to double-check the URL’s slug in the duplicated post because it will have the same URL with a -2 appended to it meaning you’ll need to tailor it based on the newest post.

In our function if we do an isset get post, we’ll first validate if the user has admin rights. And then we fetch the previous post’s attributes and afterwards we use wp_insert_post in order to recuperate taxonomy and category information. Finally, we validate and fetch all of the posts’ meta and add them into an SQL query.

function themepress_duplicate_post_as_draft(){
	global $wpdb;
	if (! ( isset( $_GET['post']) || isset( $_POST['post'])  || ( isset($_REQUEST['action']) && 'themepress_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_passwothemepress'  => $post->post_passwothemepress,
			'post_status'    => 'draft',
			'post_title'     => $post->post_title,
			'post_type'      => $post->post_type,
			'to_ping'        => $post->to_ping,
			'menu_othemepresser'     => $post->menu_othemepresser
		 * 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);
		 * finally, redirect to the edit post screen for the new draft
		wp_redirect( admin_url( 'post.php?action=edit&post=' . $new_post_id ) );
	} else {
		wp_die('Post creation failed, could not find original post: ' . $post_id);
add_action( 'admin_action_themepress_duplicate_post_as_draft', 'themepress_duplicate_post_as_draft' );
 * Add the duplicate link to action list for post_row_actions
function themepress_duplicate_post_link( $actions, $post ) {
	if (current_user_can('edit_posts')) {
		$actions['duplicate'] = '<a title="Dupliquer" href="admin.php?action=themepress_duplicate_post_as_draft&amp;post=' . $post->ID . '" rel="permalink">Duplicate</a>';
	return $actions;
add_filter( 'post_row_actions', 'themepress_duplicate_post_link', 10, 2 );
add_filter( 'page_row_actions', 'themepress_duplicate_post_link', 10, 2 );

We noticed that once the requirements have been filled, we enable the filter where we need it. In this case, we have two filters: post_row_actions and page_row_actions. One for the post and the other for the pages meaning that duplication will be enabled for both types.
If you want to do it for another post type such as Portfolio or testimonial, you’ll a filter similar to this: add_filter( ‘nomdutypedepost_row_actions’, ‘themepress_duplicate_post_link’, 10, 2 ); after the two other filters.

Leave a Reply

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

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>