Skip to content

Instantly share code, notes, and snippets.

@technosailor
Last active December 14, 2015 12:59
Show Gist options
  • Save technosailor/5090564 to your computer and use it in GitHub Desktop.
Save technosailor/5090564 to your computer and use it in GitHub Desktop.
Class to duplicate one Multisite blog to another
<?php
/*
Plugin Name: AB Duplicate Blog
Author: Aaron Brazell
Version: 1.0-beta
Description: Duplicate a WordPress Multisite blog into a new one, transferring options, taxonomies, etc
*/
class AB_Duplicate_Blog {
public $success;
public $categories;
public $new_blog_domain;
public $new_blog_id;
public $is_new;
public $transfer_page_titles;
public function __construct() {
global $current_user;
if( !is_multisite() && !is_super_admin( $current_user->ID ) )
return false;
$this->success = false;
$this->categories = apply_filters( 'ab_preload_cats', array( 'Issue', 'Alert', 'Report' ) );
$this->new_blog_domain = false;
$this->new_blog_id = false;
$this->is_new = false;
$this->transfer_page_titles = apply_filters( 'ab_transfer_page_titles', array( 'Current Issue', 'Alert', 'Reports', 'Master Archives', 'Renew Now', 'About' ) );
$this->hooks();
}
public function hooks() {
add_action( 'admin_menu', array( $this, 'menu_item' ) );
add_action( 'admin_init', array( $this, 'create_blog' ) );
add_action( 'admin_notices', array( $this, 'messages' ) );
}
public function menu_item() {
add_submenu_page( 'tools.php', __( 'Duplicate Blog', 'ab-duplicate-blog' ), __( 'Duplicate Blog', 'ab-duplicate-blog' ), 'administrator', 'duplicate-blog', array( $this, 'admin_html' ) );
}
public function messages()
{
if( !$this->success )
return false;
$text = ( $this->is_new ) ? 'New site created' : 'Existing site updated';
$message = sprintf( '<div class="update-nag">%1$s with ID %2$d. Go to the <a href="%3$s">Dashboard</a> to edit.', $text, $this->new_blog_id, esc_url( $this->new_blog_domain . '/wp-admin' ) );
echo $message;
}
public function create_blog()
{
if( !isset( $_POST['_ab_dupeblog_wpnonce'] ) )
return false;
if( !wp_verify_nonce( $_POST['_ab_dupeblog_wpnonce'], 'ab-duplicate-blog_duplicate-blog') )
return false;
global $current_user, $wpdb, $blog_id, $current_site;
$domain = ( is_subdomain_install() ) ? sanitize_title( $_POST['new-site-address'] ) . '.' . $current_site->domain : $current_site->domain;
$this->new_blog_domain = esc_url( $domain );
$path = ( is_subdomain_install() ) ? '/' : '/' . sanitize_title( $_POST['new-site-address'] );
$name = $_POST['new-site-name'];
// Get an object of Pages to transfer
$page_ids = array();
$page_not_ids = array();
foreach( $this->transfer_page_titles as $pt )
{
if( $pid = post_exists( $pt ) )
$page_ids[] = $pid;
else
$page_not_ids[] = $pt;
}
$pages = get_posts(
array( 'include' => $page_ids, 'post_type' => 'page' )
);
$post_meta = array();
foreach( $pages as $p )
{
$post_meta[$p->post_title] = get_post_custom( $p->ID );
}
// Get Admin User
$email = get_option( 'admin_email' );
$admin_user = get_user_by( 'email', $email );
if( !$admin_user )
$admin_user = get_user_by( 'login', 'admin' );
$admin_id = $admin_user->ID;
// Get other Users to transfer making sure we eliminate the admin user
$users = get_users(
array(
'include' => $_POST['new-site-users'],
)
);
$temp_users = array();
foreach( $users as $u )
{
if( $u->ID == $admin_id )
continue;
$temp_users[] = $u;
}
$users = (object) $temp_users;
// Get specific options
$active_plugins = get_option( 'active_plugins' );
$active_stylesheet = get_option( 'stylesheet' );
$active_template = get_option( 'template' );
$new_blog_id = domain_exists( $domain, $path, 1 );
// Check to see if the site already exists. If it does, then the insertion uses the existing blog
if( is_null( $new_blog_id ) )
{
$new_blog_id = create_empty_blog( $domain, $path, $name );
$this->is_new = true;
}
$this->new_blog_id = $new_blog_id;
// We've created an empty blog and have the ID of that site. Let's switch context and push what we need into it
switch_to_blog( $new_blog_id );
// Add Admin User
add_user_to_blog( $blog_id, $admin_user->ID, 'administrator' );
// Add additional users
foreach( $users as $u )
{
add_user_to_blog( $blog_id, $u->ID, $u->roles[0] );
}
// Add the categories
foreach( $this->categories as $c )
wp_create_category( $c );
// Delete Existing pages so we have a blank slate
$exposts = get_posts( array( 'post_per_page' => 999, 'post_type' => 'page' ) );
if( !empty( $exposts ) )
{
foreach( $exposts as $p )
{
wp_delete_post( $p->ID, true );
}
}
// Insert transferred pages
foreach( $pages as $p )
{
$p = (array) $p;
// The post doesn't exist so remove the ID so wp_insert_post() does an insert instead of update
if( !post_exists( $p->post_title ) )
unset( $p['ID'] );
$post_result = wp_insert_post( $p, true );
if( is_wp_error( $post_result ) )
{
echo $post_result->get_error_message();
exit;
}
// Add post meta
foreach( $post_meta[$p['post_title']] as $k => $v )
{
if( get_post_meta( $post_result, $k, true ) )
update_post_meta( $post_result, $k, $v[0] );
else
add_post_meta( $post_result, $k, $v[0] );
}
}
// Insert non-existing pages
foreach( $page_not_ids as $pid )
{
$args = array( 'post_type' => 'page', 'post_title' => $pid, 'post_status' => 'publish', 'post_author' => $current_user->ID );
wp_insert_post( $args );
}
// Update Active Plugins
update_option( 'active_plugins', $active_plugins );
// Update Theme
if( get_option( 'stylesheet' ) )
update_option( 'stylesheet', $active_stylesheet );
else
add_option( 'stylesheet', $active_stylesheet );
if( get_option( 'template' ) )
update_option( 'template', $active_template );
else
add_option( 'template', $active_template );
// Make sure the blog privacy is set to keep the new site a secret until launch
update_option( 'blog_public', false );
restore_current_blog();
$this->success = true;
}
public function admin_html() {
echo '<h2>' . __( 'Duplicate Blog', 'ab-duplicate-blog' ) . '</h2>';
$nonce = wp_create_nonce( 'ab-duplicate-blog_duplicate-blog' );
?>
<form action="" method="post">
<table id="af-duplicate-blog-table" class="widefat">
<thead>
<tr>
<th scope="col"><?php _e( 'Description', 'ab-duplicate-blog' ) ?></th>
<th scope="col"><?php _e( 'Transfer Options', 'ab-duplicate-blog' ) ?></th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">New Site Name *</th>
<td>
<input type="text" placeholder="Required" name="new-site-name" size="50" />
</td>
</tr>
<tr>
<th scope="row">New Site Address *</th>
<td>
<?php
$siteurl = str_replace( 'http://', '', get_bloginfo('siteurl') );
?>
<input type="text" placeholder="Enter just the subdomain. Exclude http:// and .<?php echo $siteurl ?>" name="new-site-address" size="50" />
</td>
</tr>
<th scope="row">Authors to Create</th>
<td>
<?php
global $blog_id;
$authors = get_users( array( 'blog_id' => $blog_id, 'who' => 'authors' ) );
foreach( $authors as $a )
{
if( array_key_exists( 'subscriber', $a->caps ) )
continue;
$fname = get_user_meta( $a->ID, 'first_name', true );
$lname = get_user_meta( $a->ID, 'last_name', true );
$name = ( $fname ) ? $fname . ' ' . $lname : $a->user_nicename;
?>
<span class="agora-checkbox-third">
<input type="checkbox" name="new-site-users[]" value="<?php echo $a->ID ?>" /> <?php echo esc_html( $name ) ?>
</span>
<?php
}
?>
</td>
</tr>
</tbody>
</table>
<?php do_action( 'ab_duplicate_blog_form' ) ?>
<input type="submit" name="ab-submit-duplicate-blog" class="primary-button button" value="Create Blog" />
<input type="hidden" name="_ab_dupeblog_wpnonce" value="<?php echo $nonce ?>" />
</form>
<?php
}
}
$ab_duplicate_blog = new AB_Duplicate_Blog;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment