/** * Add a Network * * <domain> * : Domain for network * * <path> * : Path for network * * [--site_name=<site_name>] * : Name of new network * * [--clone_network=<clone_network>] * : ID of network to clone * * [--options_to_clone=<options_to_clone>] * : Options to clone to new network * */ public function create($args, $assoc_args) { list($domain, $path) = $args; $assoc_args = wp_parse_args($assoc_args, array('site_name' => false, 'clone_network' => false, 'options_to_clone' => false)); $clone_network = $assoc_args['clone_network']; $options_to_clone = false; if (!empty($clone_network) && !wp_get_network($clone_network)) { WP_CLI::error(sprintf(__("Clone network %s doesn't exist.", 'wp-multi-network'), $clone_network)); if (!empty($assoc_args['options_to_clone'])) { $options_to_clone = explode(",", $assoc_args['options_to_clone']); } } // Add the network $network_id = add_network(array('domain' => $domain, 'path' => $path, 'site_name' => $assoc_args['site_name'], 'user_id' => get_current_user_id(), 'clone_network' => $clone_network, 'options_to_clone' => $options_to_clone)); if (is_wp_error($network_id)) { WP_CLI::error($network_id); } WP_CLI::success(sprintf(__('Created network %d.', 'wp-multi-network'), $network_id)); }
function get_object_by_id($network_id) { return wp_get_network($network_id); }
/** * Get the main network * * Uses the same logic as {@see is_main_network}, but returns the network object * instead. * * @return stdClass|null */ function wp_get_main_network() { global $wpdb; if (!is_multisite()) { return null; } // Added in 4.3.0 if (function_exists('get_main_network_id')) { $primary_network_id = get_main_network_id(); // 4.2.0 } else { // Override if (defined('PRIMARY_NETWORK_ID')) { return wp_get_network((int) PRIMARY_NETWORK_ID); } // Check cache $primary_network_id = (int) wp_cache_get('primary_network_id', 'site-options'); if (!empty($primary_network_id)) { return wp_get_network($primary_network_id); } $primary_network_id = (int) $wpdb->get_var("SELECT id FROM {$wpdb->site} ORDER BY id LIMIT 1"); wp_cache_add('primary_network_id', $primary_network_id, 'site-options'); } return wp_get_network($primary_network_id); }
// Search the network path + one more path segment (on top of the network path). $current_blog = get_site_by_path($domain, $path, substr_count($current_site->path, '/')); } } else { // Find the site by the domain and at most the first path segment. $current_blog = get_site_by_path($domain, $path, 1); if ($current_blog) { $current_site = wp_get_network($current_blog->site_id ? $current_blog->site_id : 1); } else { // If you don't have a site with the same domain/path as a network, you're pretty screwed, but: $current_site = get_network_by_path($domain, $path, 1); } } // The network declared by the site trumps any constants. if ($current_blog && $current_blog->site_id != $current_site->id) { $current_site = wp_get_network($current_blog->site_id); } // No network has been found, bail. if (empty($current_site)) { ms_not_installed(); } // @todo Investigate when exactly this can occur. if (empty($current_blog) && defined('WP_INSTALLING')) { $current_blog = new stdClass(); $current_blog->blog_id = $blog_id = 1; } // No site has been found, bail. if (empty($current_blog)) { // We're going to redirect to the network URL, with some possible modifications. $scheme = is_ssl() ? 'https' : 'http'; $destination = "{$scheme}://{$current_site->domain}{$current_site->path}";
/** * Get the main network * * @param stdClass $network Network being used * @return stdClass Corrected network to use */ function get_main_network() { // Use wp_get_main_network if it exists; see the WP Multi Network plugin if (function_exists('wp_get_main_network')) { return wp_get_main_network(); } // No function, do it ourselves global $wpdb; if (defined('PRIMARY_NETWORK_ID')) { return wp_get_network((int) PRIMARY_NETWORK_ID); } $primary_network_id = (int) wp_cache_get('primary_network_id', 'site-options'); if ($primary_network_id) { return wp_get_network($primary_network_id); } $primary_network_id = (int) $wpdb->get_var("SELECT id FROM {$wpdb->site} ORDER BY id LIMIT 1"); wp_cache_add('primary_network_id', $primary_network_id, 'site-options'); return wp_get_network($primary_network_id); }
function go_to($url) { global $wpdb; global $current_site, $current_blog, $blog_id, $switched, $_wp_switched_stack, $public, $table_prefix, $current_user, $wp_roles; // note: the WP and WP_Query classes like to silently fetch parameters // from all over the place (globals, GET, etc), which makes it tricky // to run them more than once without very carefully clearing everything $_GET = $_POST = array(); foreach (array('query_string', 'id', 'postdata', 'authordata', 'day', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages', 'pagenow') as $v) { if (isset($GLOBALS[$v])) { unset($GLOBALS[$v]); } } $parts = parse_url($url); if (isset($parts['scheme'])) { // set the HTTP_HOST $GLOBALS['_SERVER']['HTTP_HOST'] = $parts['host']; $req = $parts['path']; if (isset($parts['query'])) { $req .= '?' . $parts['query']; // parse the url query vars into $_GET parse_str($parts['query'], $_GET); } } else { $req = $url; } if (!isset($parts['query'])) { $parts['query'] = ''; } // Scheme if (0 === strpos($req, '/wp-admin') && force_ssl_admin()) { $_SERVER['HTTPS'] = 'on'; } else { unset($_SERVER['HTTPS']); } // Set this for bp_core_set_uri_globals() $GLOBALS['_SERVER']['REQUEST_URI'] = $req; unset($_SERVER['PATH_INFO']); // setup $current_site and $current_blog globals for multisite based on // REQUEST_URI; mostly copied from /wp-includes/ms-settings.php if (is_multisite()) { $current_blog = $current_site = $blog_id = null; $domain = addslashes($_SERVER['HTTP_HOST']); if (false !== strpos($domain, ':')) { if (substr($domain, -3) == ':80') { $domain = substr($domain, 0, -3); $_SERVER['HTTP_HOST'] = substr($_SERVER['HTTP_HOST'], 0, -3); } elseif (substr($domain, -4) == ':443') { $domain = substr($domain, 0, -4); $_SERVER['HTTP_HOST'] = substr($_SERVER['HTTP_HOST'], 0, -4); } } $path = stripslashes($_SERVER['REQUEST_URI']); // Get a cleaned-up version of the wp_version string // (strip -src, -alpha, etc which may trip up version_compare()) $wp_version = (double) $GLOBALS['wp_version']; if (version_compare($wp_version, '4.4', '>=')) { if (!($current_site = wp_cache_get('current_network', 'site-options'))) { // Are there even two networks installed? $one_network = $wpdb->get_row("SELECT * FROM {$wpdb->site} LIMIT 2"); // [sic] if (1 === $wpdb->num_rows) { $current_site = new WP_Network($one_network); wp_cache_add('current_network', $current_site, 'site-options'); } elseif (0 === $wpdb->num_rows) { ms_not_installed($domain, $path); } } if (empty($current_site)) { $current_site = WP_Network::get_by_path($domain, $path, 1); } // The network declared by the site trumps any constants. if ($current_blog && $current_blog->site_id != $current_site->id) { $current_site = WP_Network::get_instance($current_blog->site_id); } if (empty($current_site)) { do_action('ms_network_not_found', $domain, $path); ms_not_installed($domain, $path); } elseif ($path === $current_site->path) { $current_blog = get_site_by_path($domain, $path); } else { // Search the network path + one more path segment (on top of the network path). $current_blog = get_site_by_path($domain, $path, substr_count($current_site->path, '/')); } // Figure out the current network's main site. if (empty($current_site->blog_id)) { if ($current_blog->domain === $current_site->domain && $current_blog->path === $current_site->path) { $current_site->blog_id = $current_blog->blog_id; } elseif (!($current_site->blog_id = wp_cache_get('network:' . $current_site->id . ':main_site', 'site-options'))) { $current_site->blog_id = $wpdb->get_var($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $current_site->domain, $current_site->path)); wp_cache_add('network:' . $current_site->id . ':main_site', $current_site->blog_id, 'site-options'); } } $blog_id = $current_blog->blog_id; $public = $current_blog->public; if (empty($current_blog->site_id)) { // This dates to [MU134] and shouldn't be relevant anymore, // but it could be possible for arguments passed to insert_blog() etc. $current_blog->site_id = 1; } $site_id = $current_blog->site_id; wp_load_core_site_options($site_id); } elseif (version_compare($wp_version, '3.9', '>=')) { if (is_admin()) { $path = preg_replace('#(.*)/wp-admin/.*#', '$1/', $path); } list($path) = explode('?', $path); // Are there even two networks installed? $one_network = $wpdb->get_row("SELECT * FROM {$wpdb->site} LIMIT 2"); // [sic] if (1 === $wpdb->num_rows) { $current_site = wp_get_network($one_network); } elseif (0 === $wpdb->num_rows) { ms_not_installed(); } if (empty($current_site)) { $current_site = get_network_by_path($domain, $path, 1); } if (empty($current_site)) { ms_not_installed(); } elseif ($path === $current_site->path) { $current_blog = get_site_by_path($domain, $path); } else { // Search the network path + one more path segment (on top of the network path). $current_blog = get_site_by_path($domain, $path, substr_count($current_site->path, '/')); } // The network declared by the site trumps any constants. if ($current_blog && $current_blog->site_id != $current_site->id) { $current_site = wp_get_network($current_blog->site_id); } // If we don't have a network by now, we have a problem. if (empty($current_site)) { ms_not_installed(); } // @todo What if the domain of the network doesn't match the current site? $current_site->cookie_domain = $current_site->domain; if ('www.' === substr($current_site->cookie_domain, 0, 4)) { $current_site->cookie_domain = substr($current_site->cookie_domain, 4); } // Figure out the current network's main site. if (!isset($current_site->blog_id)) { if ($current_blog && $current_blog->domain === $current_site->domain && $current_blog->path === $current_site->path) { $current_site->blog_id = $current_blog->blog_id; } else { // @todo we should be able to cache the blog ID of a network's main site easily. $current_site->blog_id = $wpdb->get_var($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $current_site->domain, $current_site->path)); } } $blog_id = $current_blog->blog_id; $public = $current_blog->public; if (empty($current_blog->site_id)) { // This dates to [MU134] and shouldn't be relevant anymore, // but it could be possible for arguments passed to insert_blog() etc. $current_blog->site_id = 1; } $site_id = $current_blog->site_id; wp_load_core_site_options($site_id); // Pre WP 3.9 } else { $domain = rtrim($domain, '.'); $cookie_domain = $domain; if (substr($cookie_domain, 0, 4) == 'www.') { $cookie_domain = substr($cookie_domain, 4); } $path = preg_replace('|([a-z0-9-]+.php.*)|', '', $GLOBALS['_SERVER']['REQUEST_URI']); $path = str_replace('/wp-admin/', '/', $path); $path = preg_replace('|(/[a-z0-9-]+?/).*|', '$1', $path); $GLOBALS['current_site'] = wpmu_current_site(); if (!isset($GLOBALS['current_site']->blog_id) && !empty($GLOBALS['current_site'])) { $GLOBALS['current_site']->blog_id = $wpdb->get_var($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $GLOBALS['current_site']->domain, $GLOBALS['current_site']->path)); } $blogname = htmlspecialchars(substr($GLOBALS['_SERVER']['REQUEST_URI'], strlen($path))); if (false !== strpos($blogname, '/')) { $blogname = substr($blogname, 0, strpos($blogname, '/')); } if (false !== strpos($blogname, '?')) { $blogname = substr($blogname, 0, strpos($blogname, '?')); } $reserved_blognames = array('page', 'comments', 'blog', 'wp-admin', 'wp-includes', 'wp-content', 'files', 'feed'); if ($blogname != '' && !in_array($blogname, $reserved_blognames) && !is_file($blogname)) { $path .= $blogname . '/'; } $GLOBALS['current_blog'] = get_blog_details(array('domain' => $domain, 'path' => $path), false); unset($reserved_blognames); if ($GLOBALS['current_site'] && !$GLOBALS['current_blog']) { $GLOBALS['current_blog'] = get_blog_details(array('domain' => $GLOBALS['current_site']->domain, 'path' => $GLOBALS['current_site']->path), false); } $GLOBALS['blog_id'] = $GLOBALS['current_blog']->blog_id; } // Emulate a switch_to_blog() $table_prefix = $wpdb->get_blog_prefix($current_blog->blog_id); $wpdb->set_blog_id($current_blog->blog_id, $current_blog->site_id); $_wp_switched_stack = array(); $switched = false; if (!isset($current_site->site_name)) { $current_site->site_name = get_site_option('site_name'); if (!$current_site->site_name) { $current_site->site_name = ucfirst($current_site->domain); } } } $this->flush_cache(); unset($GLOBALS['wp_query'], $GLOBALS['wp_the_query']); $GLOBALS['wp_the_query'] = new WP_Query(); $GLOBALS['wp_query'] = $GLOBALS['wp_the_query']; $GLOBALS['wp'] = new WP(); // clean out globals to stop them polluting wp and wp_query foreach ($GLOBALS['wp']->public_query_vars as $v) { unset($GLOBALS[$v]); } foreach ($GLOBALS['wp']->private_query_vars as $v) { unset($GLOBALS[$v]); } $GLOBALS['wp']->main($parts['query']); $wp_roles->reinit(); $current_user = wp_get_current_user(); $current_user->for_blog($blog_id); // For BuddyPress, James. $this->clean_up_global_scope(); $GLOBALS['bp']->loggedin_user = NULL; $GLOBALS['bp']->pages = bp_core_get_directory_pages(); do_action('bp_init'); }
/** * Get main site for a network * * @param int $network_id Network ID, null for current network * @return int Main site ("blog" in old terminology) ID */ function get_main_site($network_id = null) { global $wpdb; if (empty($network_id)) { $network = $GLOBALS['current_site']; } else { $network = wp_get_network($network_id); } if (!($primary_id = wp_cache_get('network:' . $network->id . ':main_site', 'site-options'))) { $primary_id = $wpdb->get_var($wpdb->prepare("SELECT blog_id FROM {$wpdb->blogs} WHERE domain = %s AND path = %s", $network->domain, $network->path)); wp_cache_add('network:' . $network->id . ':main_site', $primary_id, 'site-options'); } return (int) $primary_id; }
/** * Retrieve a network object by its domain and path. * * @since 3.9.0 * * @global wpdb $wpdb * * @param string $domain Domain to check. * @param string $path Path to check. * @param int|null $segments Path segments to use. Defaults to null, or the full path. * @return object|false Network object if successful. False when no network is found. */ function get_network_by_path($domain, $path, $segments = null) { global $wpdb; $domains = array($domain); $pieces = explode('.', $domain); /* * It's possible one domain to search is 'com', but it might as well * be 'localhost' or some other locally mapped domain. */ while (array_shift($pieces)) { if ($pieces) { $domains[] = implode('.', $pieces); } } /* * If we've gotten to this function during normal execution, there is * more than one network installed. At this point, who knows how many * we have. Attempt to optimize for the situation where networks are * only domains, thus meaning paths never need to be considered. * * This is a very basic optimization; anything further could have drawbacks * depending on the setup, so this is best done per-install. */ $using_paths = true; if (wp_using_ext_object_cache()) { $using_paths = wp_cache_get('networks_have_paths', 'site-options'); if (false === $using_paths) { $using_paths = (bool) $wpdb->get_var("SELECT id FROM {$wpdb->site} WHERE path <> '/' LIMIT 1"); wp_cache_add('networks_have_paths', (int) $using_paths, 'site-options'); } } $paths = array(); if ($using_paths) { $path_segments = array_filter(explode('/', trim($path, "/"))); /** * Filter the number of path segments to consider when searching for a site. * * @since 3.9.0 * * @param int|null $segments The number of path segments to consider. WordPress by default looks at * one path segment. The function default of null only makes sense when you * know the requested path should match a network. * @param string $domain The requested domain. * @param string $path The requested path, in full. */ $segments = apply_filters('network_by_path_segments_count', $segments, $domain, $path); if (null !== $segments && count($path_segments) > $segments) { $path_segments = array_slice($path_segments, 0, $segments); } while (count($path_segments)) { $paths[] = '/' . implode('/', $path_segments) . '/'; array_pop($path_segments); } $paths[] = '/'; } /** * Determine a network by its domain and path. * * This allows one to short-circuit the default logic, perhaps by * replacing it with a routine that is more optimal for your setup. * * Return null to avoid the short-circuit. Return false if no network * can be found at the requested domain and path. Otherwise, return * an object from wp_get_network(). * * @since 3.9.0 * * @param null|bool|object $network Network value to return by path. * @param string $domain The requested domain. * @param string $path The requested path, in full. * @param int|null $segments The suggested number of paths to consult. * Default null, meaning the entire path was to be consulted. * @param array $paths The paths to search for, based on $path and $segments. */ $pre = apply_filters('pre_get_network_by_path', null, $domain, $path, $segments, $paths); if (null !== $pre) { return $pre; } // @todo Consider additional optimization routes, perhaps as an opt-in for plugins. // We already have paths covered. What about how far domains should be drilled down (including www)? $search_domains = "'" . implode("', '", $wpdb->_escape($domains)) . "'"; if (!$using_paths) { $network = $wpdb->get_row("SELECT id, domain, path FROM {$wpdb->site}\n\t\t\tWHERE domain IN ({$search_domains}) ORDER BY CHAR_LENGTH(domain) DESC LIMIT 1"); if ($network) { return wp_get_network($network); } return false; } else { $search_paths = "'" . implode("', '", $wpdb->_escape($paths)) . "'"; $networks = $wpdb->get_results("SELECT id, domain, path FROM {$wpdb->site}\n\t\t\tWHERE domain IN ({$search_domains}) AND path IN ({$search_paths})\n\t\t\tORDER BY CHAR_LENGTH(domain) DESC, CHAR_LENGTH(path) DESC"); } /* * Domains are sorted by length of domain, then by length of path. * The domain must match for the path to be considered. Otherwise, * a network with the path of / will suffice. */ $found = false; foreach ($networks as $network) { if ($network->domain === $domain || "www.{$network->domain}" === $domain) { if (in_array($network->path, $paths, true)) { $found = true; break; } } if ($network->path === '/') { $found = true; break; } } if ($found) { return wp_get_network($network); } return false; }
/** * Get the main network * * Uses the same logic as {@see is_main_network}, but returns the network object * instead. * * @return stdClass|null */ function wp_get_main_network() { // Bail if not multisite if (!is_multisite()) { return null; } // Return main network ID return wp_get_network(get_main_network_id()); }
/** * Handle the request to update a network * * @since 1.7.0 */ private function update_network_handler() { // Cast $network_id = (int) $_POST['network_id']; // Bail if invalid network if (!wp_get_network($network_id)) { wp_die(esc_html__('Invalid network id.', 'wp-multi-network')); } // Title $network_title = isset($_POST['title']) ? $_POST['title'] : ''; // Domain $network_domain = isset($_POST['domain']) ? $_POST['domain'] : ''; // Path $network_path = isset($_POST['path']) ? $_POST['path'] : ''; // Bail if missing fields if (empty($network_title) || empty($network_domain) || empty($network_path)) { $this->handler_redirect(array('page' => 'networks', 'id' => $network_id, 'action' => 'edit_network', 'network_updated' => '0')); } // Update domain & path update_network($network_id, $_POST['domain'], $_POST['path']); // Update network title switch_to_network($network_id); update_site_option('site_name', $_POST['title']); restore_current_network(); // Handle redirect $this->handler_redirect(array('id' => $network_id, 'action' => 'edit_network', 'network_updated' => '1')); }
/** * Returns generated network by id. * * @since 1.0.0 * * @access public * @param int $network_id The network id. * @return object|boolean The generated nework on success, otherwise FALSE. */ public function getObjectById($network_id) { return wp_get_network($network_id); }
/** * Get network object * * @return stdClass|boolean {@see get_blog_details} */ public function get_network() { return wp_get_network($this->network); }
/** * Retrieves the additional domains for a network. * * The additional domains are the domains for all sites in the network except for the * main site. If the $global flag is set, it will get the domains for the sites in all * networks. * * @since 1.0.0 * @access public * @static * * @param int $network_id The network ID to get the addon domains for. * @param bool $global Whether the site domains for all networks should be retrieved. * @return array The site domains. */ public static function get_network_addon_domains($network_id = null, $global = false) { if (version_compare(get_bloginfo('version'), '4.6', '<')) { if (!$network_id) { $network = get_current_site(); } else { $network = wp_get_network($network_id); } } else { $network = get_network($network_id); } if (!$global) { $network_id = $network->id; } else { $network_id = false; } $addon_domains = array(); $sites = array(); if (version_compare(get_bloginfo('version'), '4.6', '<')) { $sites = wp_get_sites(array('network_id' => $network_id)); } else { $args = array('domain__not_in' => array($network->domain)); if ($network_id) { $args['network_id'] = $network_id; } $sites = get_sites($args); } foreach ($sites as $site) { if (is_array($site)) { $site = (object) $site; } if ($site->domain === $network->domain || in_array($site->domain, $addon_domains, true)) { continue; } $addon_domains[] = $site->domain; } return $addon_domains; }
/** * @subcommand set-domain * @synopsis <domain> */ public function set_domain($args, $assoc_args) { global $wpdb; $sites = wp_get_sites(); list($domain) = $args; $network = wp_get_network($wpdb->siteid); if (empty($network)) { return; } $old_domain = $network->domain; if ($old_domain == $domain) { return; } $wpdb->update($wpdb->site, array('domain' => $domain), array('id' => $wpdb->siteid)); update_site_option('siteurl', "http://{$domain}/"); update_site_option('site_name', "{$domain} Sites"); update_site_option('admin_email', "wordpress@{$domain}"); foreach (wp_get_sites() as $site) { $blog_id = $site['blog_id']; switch_to_blog($blog_id); $blog_domain = str_replace($old_domain, $domain, $site['domain']); $blog_data = array('domain' => $blog_domain, 'siteurl' => 'http://' . $blog_domain, 'path' => '/'); $blog_address = esc_url_raw($blog_data['siteurl']); if (get_option('siteurl') != $blog_address) { update_option('siteurl', $blog_address); } if (get_option('home') != $blog_address) { update_option('home', $blog_address); } update_blog_details($blog_id, $blog_data); restore_current_blog(); WP_CLI::line("{$blog_data['domain']} -> {$blog_domain}"); } if (file_exists(__DIR__ . '/hosts')) { $hosts = file_get_contents(__DIR__ . '/hosts'); $hosts = preg_replace('/\\s' . preg_quote($old_domain) . '\\s/', " {$domain} ", $hosts); $hosts = preg_replace('/\\.' . preg_quote($old_domain) . '\\s/', ".{$domain} ", $hosts); file_put_contents(__DIR__ . '/hosts', $hosts); } if (file_exists(__DIR__ . '/server_hosts')) { $hosts = file_get_contents(__DIR__ . '/server_hosts'); $hosts = preg_replace('/\\s' . preg_quote($old_domain) . '\\s/', " {$domain} ", $hosts); $hosts = preg_replace('/\\.' . preg_quote($old_domain) . '\\s/', ".{$domain} ", $hosts); file_put_contents(__DIR__ . '/server_hosts', $hosts); } if (file_exists('/etc/hosts')) { $hosts = file_get_contents('/etc/hosts'); $hosts = preg_replace('/\\s' . preg_quote($old_domain) . '\\s/', " {$domain} ", $hosts); $hosts = preg_replace('/\\.' . preg_quote($old_domain) . '\\s/', ".{$domain} ", $hosts); file_put_contents('/etc/hosts', $hosts); } WP_CLI::success("{$old_domain} -> {$domain}"); }