/**
 * Move a blog from one network to another
 *
 * @since 1.3
 *
 * @param integer $site_id ID of blog to move
 * @param integer $new_network_id ID of destination network
 */
function move_site($site_id, $new_network_id)
{
    global $wpdb;
    // Get the site
    $site = get_blog_details($site_id);
    // Bail if site does not exist
    if (empty($site)) {
        return new WP_Error('blog_not_exist', __('Site does not exist.', 'wp-multi-network'));
    }
    // Main sites cannot be moved, to prevent breakage
    if (is_main_site_for_network($site->blog_id)) {
        return true;
    }
    // Cast new network ID
    $new_network_id = (int) $new_network_id;
    // Return early if site does not need to be moved
    if ($new_network_id === (int) $site->site_id) {
        return true;
    }
    // Store the old network ID for using later
    $old_network_id = (int) $site->site_id;
    $old_network = wp_get_network($old_network_id);
    // No change
    if ($old_network_id === $new_network_id) {
        return new WP_Error('blog_not_moved', __('Site was not moved.', 'wp-multi-network'));
    }
    // New network is not zero
    if (0 !== $new_network_id) {
        $new_network = wp_get_network($new_network_id);
        if (empty($new_network)) {
            return new WP_Error('network_not_exist', __('Network does not exist.', 'wp-multi-network'));
        }
        // Tweak the domain and path if needed
        // If the site domain is the same as the network domain on a subdomain
        // install, don't prepend old "hostname"
        if (is_subdomain_install() && $site->domain !== $old_network->domain) {
            $ex_dom = substr($site->domain, 0, strpos($site->domain, '.') + 1);
            $domain = $ex_dom . $new_network->domain;
        } else {
            $domain = $new_network->domain;
        }
        $path = substr($site->path, strlen($old_network->path));
        // New network is zero (orphan)
    } else {
        // Mock a zero network object
        $new_network = new WP_Network((object) array('domain' => 'network.zero', 'path' => '/', 'id' => '0'));
        // Set domain & path to that of the current site
        $domain = $site->domain;
        $path = $site->path;
    }
    // Move the site is the blogs table
    $where = array('blog_id' => $site->blog_id);
    $update = array('site_id' => $new_network->id, 'domain' => $domain, 'path' => $path);
    $update_result = $wpdb->update($wpdb->blogs, $update, $where);
    // Bail if site could not be moved
    if (empty($update_result)) {
        return new WP_Error('blog_not_moved', __('Site could not be moved.', 'wp-multi-network'));
    }
    // Update old network count
    if (0 !== $old_network_id) {
        switch_to_network($old_network_id);
        wp_update_network_site_counts();
        restore_current_network();
    }
    // Update new network count
    if (0 !== $new_network_id) {
        switch_to_network($new_network_id);
        wp_update_network_site_counts();
        restore_current_network();
    }
    // Change relevant blog options
    $options_table = $wpdb->get_blog_prefix($site->blog_id) . 'options';
    $old_domain = $old_network->domain . $old_network->path;
    $new_domain = $new_network->domain . $new_network->path;
    // Update all site options
    foreach (network_options_list() as $option_name) {
        $sql = "SELECT * FROM {$options_table} WHERE option_name = %s";
        $prep = $wpdb->prepare($sql, $option_name);
        $option = $wpdb->get_row($prep);
        // No value, so skip it
        if (empty($option)) {
            continue;
        }
        $new_value = str_replace($old_domain, $new_domain, $option->option_value);
        update_blog_option($site->blog_id, $option_name, $new_value);
    }
    // Delete rewrite rules for site at old URL
    delete_blog_option($site_id, 'rewrite_rules');
    // Site moved
    do_action('move_site', $site_id, $old_network_id, $new_network_id);
}
/**
 * Metabox for assigning sites to a network
 *
 * @since 1.7.0
 *
 * @param WP_Network $network
 */
function wpmn_edit_network_assign_sites_metabox($network = null)
{
    // To
    $to = get_sites(array('network_id' => $network->id));
    // From
    $from = get_sites(array('network__not_in' => array($network->id)));
    ?>

	<table class="assign-sites widefat">
		<thead>
			<tr>
				<th><?php 
    esc_html_e('Available Sites', 'wp-multi-network');
    ?>
</th>
				<th>&nbsp;</th>
				<th><?php 
    esc_html_e('Network Sites', 'wp-multi-network');
    ?>
</th>
			</tr>
		</thead>
		<tr>
			<td class="column-available">
				<p class="description"><?php 
    esc_html_e('Subsites in other networks & orphaned sites without networks.', 'wp-multi-network');
    ?>
</p>
				<select name="from[]" id="from" multiple>

					<?php 
    foreach ($from as $site) {
        ?>

						<?php 
        if ((int) $site->site_id !== (int) $network->id && !is_main_site_for_network($site->blog_id)) {
            ?>

							<option value="<?php 
            echo esc_attr($site->blog_id);
            ?>
">
								<?php 
            echo esc_html(sprintf('%1$s (%2$s%3$s)', $site->name, $site->domain, $site->path));
            ?>
							</option>

						<?php 
        }
        ?>

					<?php 
    }
    ?>

				</select>
			</td>
			<td class="column-actions">
				<input type="button" name="unassign" id="unassign" class="button" value="&larr;">
				<input type="button" name="assign" id="assign" class="button" value="&rarr;">
			</td>
			<td class="column-assigned">
				<p class="description"><?php 
    esc_html_e('Only subsites of this network can be reassigned.', 'wp-multi-network');
    ?>
</p>
				<select name="to[]" id="to" multiple>

					<?php 
    foreach ($to as $site) {
        ?>

						<?php 
        if ((int) $site->site_id === (int) $network->id) {
            ?>

							<option value="<?php 
            echo esc_attr($site->blog_id);
            ?>
" <?php 
            disabled(is_main_site_for_network($site->blog_id));
            ?>
>
								<?php 
            echo esc_html(sprintf('%1$s (%2$s%3$s)', $site->name, $site->domain, $site->path));
            ?>
							</option>

						<?php 
        }
        ?>

					<?php 
    }
    ?>

				</select>
			</td>
		</tr>
	</table>

<?php 
}
 /**
  * Handle the request to reassign sites
  *
  * @since 1.7.0
  *
  * @global object $wpdb
  */
 private function reassign_sites_handler()
 {
     global $wpdb;
     // Coming in
     $to = isset($_POST['to']) ? $_POST['to'] : array();
     // Orphaning out
     $from = isset($_POST['from']) ? $_POST['from'] : array();
     // Bail early if no movement
     if (empty($to) && empty($from)) {
         return;
     }
     // Cast the network ID
     $network_id = (int) $_GET['id'];
     // Query for sites
     $sql = "SELECT * FROM {$wpdb->blogs}";
     $prep = $wpdb->prepare($sql, (int) $_GET['id']);
     $sites = $wpdb->get_results($prep);
     // Loop through and move sites
     foreach ($sites as $site) {
         // Skip the main site of this network
         if (is_main_site_for_network($site->blog_id, $site->site_id)) {
             continue;
         }
         // Coming in
         if (in_array($site->blog_id, $to)) {
             move_site($site->blog_id, $network_id);
             // Orphaning out
         } elseif (in_array($site->blog_id, $from)) {
             move_site($site->blog_id, 0);
         }
     }
 }
/**
 * Metabox for assigning sites to a network
 *
 * @since 1.7.0
 *
 * @param  object $network
 * @global object $wpdb
 */
function wpmn_edit_network_assign_sites_metabox($network = null)
{
    global $wpdb;
    // Get sites
    $sql = "SELECT * FROM {$wpdb->blogs}";
    $sites = $wpdb->get_results($sql);
    foreach ($sites as $key => $site) {
        $table_name = $wpdb->get_blog_prefix($site->blog_id) . "options";
        $sql = "SELECT * FROM {$table_name} WHERE option_name = %s";
        $prep = $wpdb->prepare($sql, 'blogname');
        $site_name = $wpdb->get_row($prep);
        $sites[$key]->name = stripslashes($site_name->option_value);
    }
    ?>

	<table class="assign-sites widefat">
		<thead>
			<tr>
				<th><?php 
    esc_html_e('Available Sites', 'wp-multi-network');
    ?>
</th>
				<th>&nbsp;</th>
				<th><?php 
    esc_html_e('Network Sites', 'wp-multi-network');
    ?>
</th>
			</tr>
		</thead>
		<tr>
			<td class="column-available">
				<p class="description"><?php 
    esc_html_e('Subsites of other networks, and orphaned sites with no networks.', 'wp-multi-network');
    ?>
</p>
				<select name="from[]" id="from" multiple>

					<?php 
    foreach ($sites as $site) {
        ?>

						<?php 
        if ($site->site_id !== $network->id && !is_main_site_for_network($site->blog_id)) {
            ?>

							<option value="<?php 
            echo esc_attr($site->blog_id);
            ?>
">
								<?php 
            echo esc_html(sprintf('%1$s (%2$s%3$s)', $site->name, $site->domain, $site->path));
            ?>
							</option>

						<?php 
        }
        ?>

					<?php 
    }
    ?>

				</select>
			</td>
			<td class="column-actions">
				<input type="button" name="unassign" id="unassign" class="button" value="&larr;">
				<input type="button" name="assign" id="assign" class="button" value="&rarr;">
			</td>
			<td class="column-assigned">
				<p class="description"><?php 
    esc_html_e('Only subsites of this network can be reassigned.', 'wp-multi-network');
    ?>
</p>
				<select name="to[]" id="to" multiple>

					<?php 
    foreach ($sites as $site) {
        ?>

						<?php 
        if ($site->site_id === $network->id) {
            ?>

							<option value="<?php 
            echo esc_attr($site->blog_id);
            ?>
" <?php 
            disabled(is_main_site_for_network($site->blog_id));
            ?>
>
								<?php 
            echo esc_html(sprintf('%1$s (%2$s%3$s)', $site->name, $site->domain, $site->path));
            ?>
							</option>

						<?php 
        }
        ?>

					<?php 
    }
    ?>

				</select>
			</td>
		</tr>
	</table>

<?php 
}
 /**
  * Handle the request to reassign sites
  *
  * @since 2.0.0
  */
 private function handle_reassign_sites()
 {
     // Coming in
     $to = isset($_POST['to']) ? array_map('absint', (array) $_POST['to']) : array();
     // Orphaning out
     $from = isset($_POST['from']) ? array_map('absint', (array) $_POST['from']) : array();
     // Bail early if no movement
     if (empty($to) && empty($from)) {
         return;
     }
     // Cast the network ID
     $network_id = (int) $_GET['id'];
     // Setup sites arrays
     $moving_to = $moving_from = array();
     // Query for sites in this network
     $sites_list = get_sites(array('network_id' => $network_id, 'fields' => 'ids'));
     // Moving out from current network
     foreach ($from as $site_id) {
         if (in_array($site_id, $sites_list, true)) {
             $moving_from[] = $site_id;
         }
     }
     // Moving into current network
     foreach ($to as $site_id) {
         if (!in_array($site_id, $sites_list, true)) {
             $moving_to[] = $site_id;
         }
     }
     // Merge into one array
     $moving = array_filter(array_merge($moving_to, $moving_from));
     // Loop through and move sites
     foreach ($moving as $site_id) {
         // Skip the main site of this network
         if (is_main_site_for_network($site_id)) {
             continue;
         }
         // Coming in
         if (in_array($site_id, $to) && !in_array($site_id, $sites_list, true)) {
             move_site($site_id, $network_id);
             // Orphaning out
         } elseif (in_array($site_id, $from, true)) {
             move_site($site_id, 0);
         }
     }
 }
 /**
  * Move a site to a new network
  *
  * @since 1.3
  *
  * @param  integer  $site_id         ID of site to move
  * @param  integer  $new_network_id  ID of destination network
  */
 function move_site($site_id = 0, $new_network_id = 0)
 {
     global $wpdb;
     // Get the site
     $site = get_blog_details($site_id);
     // Bail if site does not exist
     if (empty($site)) {
         return new WP_Error('blog_not_exist', __('Site does not exist.', 'wp-multi-network'));
     }
     // Main sites cannot be moved, to prevent breakage
     if (is_main_site_for_network($site->blog_id)) {
         return true;
     }
     // Cast new network ID
     $new_network_id = (int) $new_network_id;
     // Return early if site does not need to be moved
     if ($new_network_id === (int) $site->site_id) {
         return true;
     }
     // Move the site is the blogs table
     $where = array('blog_id' => $site->blog_id);
     $update = array('site_id' => $new_network_id);
     $result = $wpdb->update($wpdb->blogs, $update, $where);
     // Bail if site could not be moved
     if (empty($result)) {
         return new WP_Error('blog_not_moved', __('Site could not be moved.', 'wp-multi-network'));
     }
     // Update old network count
     if (0 !== $site->site_id) {
         switch_to_network($site->site_id);
         wp_update_network_site_counts();
         restore_current_network();
     }
     // Update new network count
     if (0 !== $new_network_id) {
         switch_to_network($new_network_id);
         wp_update_network_site_counts();
         restore_current_network();
     }
     // Refresh blog details
     refresh_blog_details($site_id);
     // Clean network caches
     clean_network_cache(array_filter(array($site->site_id, $new_network_id)));
     // Site moved
     do_action('move_site', $site_id, $site->site_id, $new_network_id);
     // Return the new network ID as confirmation
     return $new_network_id;
 }