Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lionrajkumar/13413970176694fe04015355bd032e4c to your computer and use it in GitHub Desktop.
Save lionrajkumar/13413970176694fe04015355bd032e4c to your computer and use it in GitHub Desktop.
Copy Pages between Sites in Multisite Network.md

Copy Pages between Sites in Multisite Network

In this tutorial I will show you an easy way to duplicate WordPress pages to any of your sites within a multisite network.

There are different ways to implement that but we going to use WordPress bulk actions.

Copy Pages between Sites within WordPress Multisite network

As an example I decided to use Pages and we do not only copy them, but move between sites. If you need to create duplicates, you will have to change just one line of code.

And of course, if you don’t want to code, I can also recommend an even better solution, it is my plugin developed specifically to copy posts and pages between sites.

The ready code for your theme functions.php:

/**
 * WordPress Multisite: Copy or Move Pages between Sites
 *
 * @author Misha Rudrastyh
 * @link https://rudrastyh.com/wordpress-multisite/move-posts-between-blogs.html
 */
// add bulk actions
add_filter( 'bulk_actions-edit-page', 'rudr_my_bulk_multisite_actions' );
function rudr_my_bulk_multisite_actions( $bulk_array ) {

	$sites = get_sites( array(
		// 'site__in' => array( 1,2,3 )
		'site__not_in' => get_current_blog_id(), // excluding current blog
		'number' => 50,
	) );
	
	if( $sites ) {
		foreach( $sites as $site ) {
			$bulk_array[ 'move_to_' . $site->blog_id ] = 'Move to "' . $site->blogname . '"';
		}
	}
	return $bulk_array;
}

// move or Copy posts 
add_filter( 'handle_bulk_actions-edit-page', 'rudr_bulk_action_multisite_handler', 10, 3 );
function rudr_bulk_action_multisite_handler( $redirect, $doaction, $object_ids ) {

	// we need query args to display correct admin notices
	$redirect = remove_query_arg( array( 'misha_posts_moved', 'misha_blogid' ), $redirect );

 	// our actions begin with "move_to_", so let's check if it is a target action
	if( strpos( $doaction, 'move_to_' ) === 0 ) {
		$blog_id = str_replace( 'move_to_', '', $doaction ); // get blog ID from action name

		foreach ( $object_ids as $post_id ) {

			// get the original post object as an array
			$post = get_post( $post_id, ARRAY_A );
			// if you need to apply terms (more info below the code)
			$post_terms = wp_get_object_terms( $post_id, 'category', array( 'fields' => 'slugs' ) );
			// get all the post meta
			$data = get_post_custom( $post_id );
			// empty ID field, to tell WordPress to create a new post, not update an existing one
			$post[ 'ID' ] = '';

			switch_to_blog( $blog_id );
			
			// insert the post
			$inserted_post_id = wp_insert_post( $post ); // insert the post
			// update post terms
			wp_set_object_terms( $inserted_post_id, $post_terms, 'category', false );
			// add post meta
			foreach ( $data as $key => $values) {
				// if you do not want weird redirects
				if( '_wp_old_slug' === $key ) {
					continue;
				}
				foreach( $values as $value ) {
					add_post_meta( $inserted_post_id, $key, $value );
				}
			}

			restore_current_blog();

			// if you want just to copy pages, comment this line
			wp_delete_post( $post_id );

		}
		$redirect = add_query_arg( array(
			'misha_posts_moved' => count( $object_ids ),
			'misha_blogid' => $blog_id
		), $redirect );
	}
	return $redirect;
}

// show an appropriate notice 
add_action( 'admin_notices', 'rudr_bulk_multisite_notices' );
function rudr_bulk_multisite_notices() {

	if( ! empty( $_REQUEST[ 'misha_posts_moved' ] ) ) {

		// because I want to add blog names to notices
		$blog = get_blog_details( $_REQUEST[ 'misha_blogid' ] );

		// depending on ho much posts were changed, make the message different
		echo '<div class="updated notice is-dismissible"><p>';
		printf(
			_n( 
				'%d post has been moved to "%s".', 
				'%d posts have been moved to "%s".', 
				$_REQUEST[ 'misha_posts_moved' ]
			),
			$_REQUEST[ 'misha_posts_moved' ], 
			$blog->blogname 
		);
		echo '</p></div>';
	}
}
  • Working with bulk actions, you should also know, that for posts the filter will look like bulk_actions-edit-post, for custom post types bulk_actions-edit-{CPT name}. Or better read a tutorial about bulk actions on my blog.
  • You could also notice that we passed the maximum 50 sites to get in get_sites() function. The thing is that WordPress Multisite network supports unlimited amount of sites, so if you have 1000+ sites in your Network, you’d better think about another implementation of this step, I can give you two hints – maybe you do not need all the sites, in that case site_in parameter will help you, or if you need all of them, you could try to replace the default bulk action element with Select2 with AJAX search, read more about it here.
  • I used get_current_blog_id() as well because we don’t want to duplicate pages to the same website right? If you do, then another tutorial is for you.
  • Remove line 69, if you would like to duplicate posts, not to move them. By the way, if you set the second parameter to wp_delete_post( $post_id, true );, posts will be removed permanently, without moving to the trash.

And again, if this code seems difficult, please check my plugin instead.

Courtesy: Misha Rudrastyh

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment