Duplicating Posts from One Site to Another in Multisite

Origin Story

We had two sites on a multisite installation. The desire was for site A (or any number of sites) to have posts in a certain category duplicated to site B. In many scenarios we’d just use Feed WordPress but in this case both sites were private. There may be a way to get that working in FeedWordPress but I am not aware of it.

These two functions will copy content from one site to another when it is published. It won’t sync up editing or anything like that but it’s a decent start for doing that if it was desired. The explanation is mainly in the code comments. I’m not sure if that’s useful but I also realize that the audience for what I write1 is mostly me and I’m ok with it.

function copy_post_replicator($ID, $post) {
	
    $author = $post->post_author; //
    $title = $post->post_title;
    $content = $post->post_content;
    
	$destination = 3; //THE ID OF THE SITE WHERE YOU WANT THE COPY TO GO
	if (in_category('copy-me')){ //ONLY THIS CATEGORY COPIES
		switch_to_blog( $destination );//SWITCH TO NEW SITE
		$copy_cat_id = get_category_by_slug('copy-me')->term_id;//GET THE ID FOR THE SHARED CATEGORy ON THE DESTINATION SITE -- for each loop needed if multiple categories

		$new_post = array(
		  'post_title'    => $title,
		  'post_content'  => $content,
		  'post_status'   => 'publish',
		  'post_author'   => $author,
		  'post_category' => array( $copy_cat_id ), //yes, intentional
		);
		 
		// Insert the post into the database
		remove_action('publish_post', 'copy_post_replicator');//CURSED LOOP!!!!!!!
		wp_insert_post( $new_post );
		add_action('publish_post', 'copy_post_replicator');//probably unnecessary but I was unwilling to mess with it further

    	restore_current_blog();
	}
}
add_action( 'publish_post', 'copy_post_replicator', 10, 2 );

Now you could change add_action( ‘publish_post’, ‘copy_post_replicator’, 10, 2 ); to add_action( ‘update_post’, ‘copy_post_replicator’, 10, 2 ); and it’ll run on any post update. The problem there is that edits to the posts will result in duplicates on the destination site. If we wanted to get fancy, we could record the post ID of the duplicate post as a custom field on the original and do some updating function based on that but this was a very fast response rather than a full blown project.

Do pay close attention to the remove_action portion. My kids were highly amused when I created several thousand posts because I didn’t have this included. I still don’t quite get why it behaved the way it did (loop on the destination site) . . . but I do know how to stop it now.

If you’re creating the post via Gravity Forms, you’d end up with a copying pattern more like this.

add_action( 'gform_after_submission', 'gform_onl_post_replicator', 10, 2 );//note different action trigger

function gform_onl_post_replicator( $entry, $form ) {
    $post = get_post( $entry['post_id'] );
    $author = $post->post_author;
    $title = $post->post_title;
 	$content = $post->post_content;
 	$image_url = get_the_post_thumbnail_url($entry['post_id']);
 	$all_cats = [];
 	if ($entry['9']){
	 		$copy_group = sanitize_title(trim_cat_to_text($entry['9']));//specific form elements with categories in them
 		}
 	if ($entry['2']){
 		 	$focus = sanitize_title(trim_cat_to_text($entry['2'])); //specific form elements with categories in them		 
 	}	

 	$destination = 666; //destination blog ID

	if (in_category('copy-me', $entry['post_id'])){
		switch_to_blog( $destination );
		if(get_category_by_slug('pbl-group-work')){
			$copy_cat_id = get_category_by_slug('copy-me')->term_id;
			array_push($all_cats, (int)$copy_cat_id);
		} else {
			$copy_cat_id = 1;
			array_push($all_cats, $copy_cat_id);			
		}
		if(get_category_by_slug($copy_group)){
			$copy_group_id = get_category_by_slug($copy_group)->term_id;
			array_push($all_cats, (int)$copy_group_id);
		}
		if(get_category_by_slug($focus)){
			$focus_id = get_category_by_slug($focus)->term_id;
			array_push($all_cats, (int)$focus_id);
		}
		//$group_cat_id = get_category_by_slug('category-slug'); //need to get this from blog url
		$new_post = array(
		  'post_title'    => $title,
		  'post_content'  => '<img src="'.$image_url.'">' . $content,//I was lazy about setting up a featured image and instead just put it in the post which worked for this theme
		  'post_status'   => 'publish',
		  'post_author'   => $author,
		  'post_category' => $all_cats,
		);
		 
		// Insert the post into the database
		wp_insert_post( $new_post );

    	restore_current_blog();
	}
   
}

//gforms returns a weird category name structure and this trims it to the slug
function trim_cat_to_text($text){
	$length = strlen($text);
	$colon = strpos($text, ':');
	$text = substr($text, 0, $colon);
	return $text;
}


1 Except for the footnotes. The footnotes have up to 4 people who read them.

Comments on this post

  1. Jennifer said on October 2, 2019 at 7:26 pm

    I feel seen by that footnote.

    • Tom Woodward said on October 3, 2019 at 7:35 pm

      No question that you represent 25 to 75% of that demographic.

Leave a Reply to Jennifer Cancel reply

Trackbacks and Pingbacks on this post

No trackbacks.

TrackBack URL