/** * Update the value of a network option that was already added. * * @since 4.4.0 * * @see update_option() * * @global wpdb $wpdb * * @param int $network_id ID of the network. Can be null to default to the current network ID. * @param string $option Name of option. Expected to not be SQL-escaped. * @param mixed $value Option value. Expected to not be SQL-escaped. * @return bool False if value was not updated and true if value was updated. */ function update_network_option($network_id, $option, $value) { global $wpdb; if ($network_id && !is_numeric($network_id)) { return false; } $network_id = (int) $network_id; // Fallback to the current network if a network ID is not specified. if (!$network_id) { $network_id = get_current_network_id(); } wp_protect_special_option($option); $old_value = get_network_option($network_id, $option, false); /** * Filters a specific network option before its value is updated. * * The dynamic portion of the hook name, `$option`, refers to the option name. * * @since 2.9.0 As 'pre_update_site_option_' . $key * @since 3.0.0 * @since 4.4.0 The `$option` parameter was added. * @since 4.7.0 The `$network_id` parameter was added. * * @param mixed $value New value of the network option. * @param mixed $old_value Old value of the network option. * @param string $option Option name. * @param int $network_id ID of the network. */ $value = apply_filters("pre_update_site_option_{$option}", $value, $old_value, $option, $network_id); if ($value === $old_value) { return false; } if (false === $old_value) { return add_network_option($network_id, $option, $value); } $notoptions_key = "{$network_id}:notoptions"; $notoptions = wp_cache_get($notoptions_key, 'site-options'); if (is_array($notoptions) && isset($notoptions[$option])) { unset($notoptions[$option]); wp_cache_set($notoptions_key, $notoptions, 'site-options'); } if (!is_multisite()) { $result = update_option($option, $value, 'no'); } else { $value = sanitize_option($option, $value); $serialized_value = maybe_serialize($value); $result = $wpdb->update($wpdb->sitemeta, array('meta_value' => $serialized_value), array('site_id' => $network_id, 'meta_key' => $option)); if ($result) { $cache_key = "{$network_id}:{$option}"; wp_cache_set($cache_key, $value, 'site-options'); } } if ($result) { /** * Fires after the value of a specific network option has been successfully updated. * * The dynamic portion of the hook name, `$option`, refers to the option name. * * @since 2.9.0 As "update_site_option_{$key}" * @since 3.0.0 * @since 4.7.0 The `$network_id` parameter was added. * * @param string $option Name of the network option. * @param mixed $value Current value of the network option. * @param mixed $old_value Old value of the network option. * @param int $network_id ID of the network. */ do_action("update_site_option_{$option}", $option, $value, $old_value, $network_id); /** * Fires after the value of a network option has been successfully updated. * * @since 3.0.0 * @since 4.7.0 The `$network_id` parameter was added. * * @param string $option Name of the network option. * @param mixed $value Current value of the network option. * @param mixed $old_value Old value of the network option. * @param int $network_id ID of the network. */ do_action('update_site_option', $option, $value, $old_value, $network_id); return true; } return false; }
/** * Determine whether a network is the main network of the Multisite install. * * @since 3.7.0 * * @param int $network_id Optional. Network ID to test. Defaults to current network. * @return bool True if $network_id is the main network, or if not running Multisite. */ function is_main_network($network_id = null) { if (!is_multisite()) { return true; } if (null === $network_id) { $network_id = get_current_network_id(); } $network_id = (int) $network_id; return $network_id === get_main_network_id(); }
wp_die(__('Sorry, you are not allowed to access this page.'), 403); } echo '<div class="wrap">'; echo '<h1>' . __('Upgrade Network') . '</h1>'; $action = isset($_GET['action']) ? $_GET['action'] : 'show'; switch ($action) { case "upgrade": $n = isset($_GET['n']) ? intval($_GET['n']) : 0; if ($n < 5) { /** * @global string $wp_db_version */ global $wp_db_version; update_site_option('wpmu_upgrade_site', $wp_db_version); } $site_ids = get_sites(array('spam' => '0', 'deleted' => '0', 'archived' => '0', 'network_id' => get_current_network_id(), 'number' => 5, 'offset' => $n, 'fields' => 'ids', 'order' => 'DESC', 'orderby' => 'id')); if (empty($site_ids)) { echo '<p>' . __('All done!') . '</p>'; break; } echo "<ul>"; foreach ((array) $site_ids as $site_id) { switch_to_blog($site_id); $siteurl = site_url(); $upgrade_url = admin_url('upgrade.php?step=upgrade_db'); restore_current_blog(); echo "<li>{$siteurl}</li>"; $response = wp_remote_get($upgrade_url, array('timeout' => 120, 'httpversion' => '1.1', 'sslverify' => false)); if (is_wp_error($response)) { wp_die(sprintf(__('Warning! Problem updating %1$s. Your server may not be able to connect to sites running on it. Error message: %2$s'), $siteurl, '<em>' . $response->get_error_message() . '</em>')); }
/** * Prepares the list of sites for display. * * @since 3.1.0 * @since 4.6.0 Converted to use get_sites() * * @global string $s * @global string $mode * @global wpdb $wpdb */ public function prepare_items() { global $s, $mode, $wpdb; if (!empty($_REQUEST['mode'])) { $mode = $_REQUEST['mode'] === 'excerpt' ? 'excerpt' : 'list'; set_user_setting('sites_list_mode', $mode); } else { $mode = get_user_setting('sites_list_mode', 'list'); } $per_page = $this->get_items_per_page('sites_network_per_page'); $pagenum = $this->get_pagenum(); $s = isset($_REQUEST['s']) ? wp_unslash(trim($_REQUEST['s'])) : ''; $wild = ''; if (false !== strpos($s, '*')) { $wild = '*'; $s = trim($s, '*'); } /* * If the network is large and a search is not being performed, show only * the latest sites with no paging in order to avoid expensive count queries. */ if (!$s && wp_is_large_network()) { if (!isset($_REQUEST['orderby'])) { $_GET['orderby'] = $_REQUEST['orderby'] = ''; } if (!isset($_REQUEST['order'])) { $_GET['order'] = $_REQUEST['order'] = 'DESC'; } } $args = array('number' => intval($per_page), 'offset' => intval(($pagenum - 1) * $per_page), 'network_id' => get_current_network_id()); if (empty($s)) { // Nothing to do. } elseif (preg_match('/^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$/', $s) || preg_match('/^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.?$/', $s) || preg_match('/^[0-9]{1,3}\\.[0-9]{1,3}\\.?$/', $s) || preg_match('/^[0-9]{1,3}\\.$/', $s)) { // IPv4 address $sql = $wpdb->prepare("SELECT blog_id FROM {$wpdb->registration_log} WHERE {$wpdb->registration_log}.IP LIKE %s", $wpdb->esc_like($s) . (!empty($wild) ? '%' : '')); $reg_blog_ids = $wpdb->get_col($sql); if ($reg_blog_ids) { $args['site__in'] = $reg_blog_ids; } } elseif (is_numeric($s) && empty($wild)) { $args['ID'] = $s; } else { $args['search'] = $s; if (!is_subdomain_install()) { $args['search_columns'] = array('path'); } } $order_by = isset($_REQUEST['orderby']) ? $_REQUEST['orderby'] : ''; if ('registered' === $order_by) { // registered is a valid field name. } elseif ('lastupdated' === $order_by) { $order_by = 'last_updated'; } elseif ('blogname' === $order_by) { if (is_subdomain_install()) { $order_by = 'domain'; } else { $order_by = 'path'; } } elseif ('blog_id' === $order_by) { $order_by = 'id'; } elseif (!$order_by) { $order_by = false; } $args['orderby'] = $order_by; if ($order_by) { $args['order'] = isset($_REQUEST['order']) && 'DESC' === strtoupper($_REQUEST['order']) ? "DESC" : "ASC"; } if (wp_is_large_network()) { $args['no_found_rows'] = true; } else { $args['no_found_rows'] = false; } /** * Filters the arguments for the site query in the sites list table. * * @since 4.6.0 * * @param array $args An array of get_sites() arguments. */ $args = apply_filters('ms_sites_list_table_query_args', $args); $_sites = get_sites($args); if (is_array($_sites)) { update_site_cache($_sites); $this->items = array_slice($_sites, 0, $per_page); } $total_sites = get_sites(array_merge($args, array('count' => true, 'offset' => 0, 'number' => 0))); $this->set_pagination_args(array('total_items' => $total_sites, 'per_page' => $per_page)); }
// Looks like an importer is installed, but not active. $plugins = get_plugins('/' . $plugin_slug); if (!empty($plugins)) { $keys = array_keys($plugins); $plugin_file = $plugin_slug . '/' . $keys[0]; $url = wp_nonce_url(add_query_arg(array('action' => 'activate', 'plugin' => $plugin_file, 'from' => 'import'), admin_url('plugins.php')), 'activate-plugin_' . $plugin_file); $action = sprintf('<a href="%s" aria-label="%s">%s</a>', esc_url($url), esc_attr(sprintf(__('Run %s'), $data[0])), __('Run Importer')); $is_plugin_installed = true; } } if (empty($action)) { if (is_main_site()) { $url = wp_nonce_url(add_query_arg(array('action' => 'install-plugin', 'plugin' => $plugin_slug, 'from' => 'import'), self_admin_url('update.php')), 'install-plugin_' . $plugin_slug); $action = sprintf('<a href="%1$s" class="install-now" data-slug="%2$s" data-name="%3$s" aria-label="%4$s">%5$s</a>', esc_url($url), esc_attr($plugin_slug), esc_attr($data[0]), esc_attr(sprintf(__('Install %s'), $data[0])), __('Install Now')); } else { $action = sprintf(__('This importer is not installed. Please install importers from <a href="%s">the main site</a>.'), get_admin_url(get_current_network_id(), 'import.php')); } } } else { $url = add_query_arg(array('import' => $importer_id), self_admin_url('admin.php')); $action = sprintf('<a href="%1$s" aria-label="%2$s">%3$s</a>', esc_url($url), esc_attr(sprintf(__('Run %s'), $data[0])), __('Run Importer')); $is_plugin_installed = true; } if (!$is_plugin_installed && is_main_site()) { $url = add_query_arg(array('tab' => 'plugin-information', 'plugin' => $plugin_slug, 'from' => 'import', 'TB_iframe' => 'true', 'width' => 600, 'height' => 550), network_admin_url('plugin-install.php')); $action .= sprintf(' | <a href="%1$s" class="thickbox open-plugin-details-modal" aria-label="%2$s">%3$s</a>', esc_url($url), esc_attr(sprintf(__('More information about %s'), $data[0])), __('Details')); } echo "\n\t\t\t<tr class='importer-item'>\n\t\t\t\t<td class='import-system'>\n\t\t\t\t\t<span class='importer-title'>{$data[0]}</span>\n\t\t\t\t\t<span class='importer-action'>{$action}</span>\n\t\t\t\t</td>\n\t\t\t\t<td class='desc'>\n\t\t\t\t\t<span class='importer-desc'>{$data[1]}</span>\n\t\t\t\t</td>\n\t\t\t</tr>"; } ?> </table>
$password = wp_generate_password(12, false); $user_id = wpmu_create_user($domain, $password, $email); if (false === $user_id) { wp_die(__('There was an error creating the user.')); } /** * Fires after a new user has been created via the network site-new.php page. * * @since 4.4.0 * * @param int $user_id ID of the newly created user. */ do_action('network_site_new_created_user', $user_id); } $wpdb->hide_errors(); $id = wpmu_create_blog($newdomain, $path, $title, $user_id, $meta, get_current_network_id()); $wpdb->show_errors(); if (!is_wp_error($id)) { if (!is_super_admin($user_id) && !get_user_option('primary_blog', $user_id)) { update_user_option($user_id, 'primary_blog', $id, true); } wp_mail(get_site_option('admin_email'), sprintf(__('[%s] New Site Created'), get_network()->site_name), sprintf(__('New site created by %1$s Address: %2$s Name: %3$s'), $current_user->user_login, get_site_url($id), wp_unslash($title)), sprintf('From: "%1$s" <%2$s>', _x('Site Admin', 'email "From" field'), get_site_option('admin_email'))); wpmu_welcome_notification($id, $user_id, $password, $title, array('public' => 1)); wp_redirect(add_query_arg(array('update' => 'added', 'id' => $id), 'site-new.php')); exit; } else { wp_die($id->get_error_message()); }
/** * Returns an array of site IDs. * * The function `wp_get_sites()` has been deprecated in WordPress 4.6 in favor of the new `get_sites()`. * * @since 2.0.2 * @param boolean $all_networks Whether to return not only sites in the current network, but from all networks. * @return array Array of site IDs. */ private static function _get_site_ids($all_networks = false) { if (!function_exists('get_sites') || !function_exists('get_current_network_id')) { $args = array(); if ($all_networks) { $args['network_id'] = 0; } $sites = wp_get_sites($args); return wp_list_pluck($sites, 'blog_id'); } $args = array('fields' => 'ids'); if (!$all_networks) { $args['network_id'] = get_current_network_id(); } return get_sites($args); }
/** * Can the current user delete this network? * * @since 2.0.0 * * @param WP_Network $network * * @return boolean */ private function can_delete($network) { // Bail if main network if (is_main_network($network->id)) { return false; } // Can't delete current network if (get_current_network_id() === $network->id) { return false; } // Bail if user cannot delete network if (!current_user_can('delete_network', $network->id)) { return false; } // Assume true (if you're already on this screen) return true; }
/** * Retrieve the blogs of the user. * * @since 2.6.0 * * @param array $args { * Method arguments. Note: arguments must be ordered as documented. * * @type string $username Username. * @type string $password Password. * } * @return array|IXR_Error Array contains: * - 'isAdmin' * - 'isPrimary' - whether the blog is the user's primary blog * - 'url' * - 'blogid' * - 'blogName' * - 'xmlrpc' - url of xmlrpc endpoint */ public function wp_getUsersBlogs($args) { if (!$this->minimum_args($args, 2)) { return $this->error; } // If this isn't on WPMU then just use blogger_getUsersBlogs if (!is_multisite()) { array_unshift($args, 1); return $this->blogger_getUsersBlogs($args); } $this->escape($args); $username = $args[0]; $password = $args[1]; if (!($user = $this->login($username, $password))) { return $this->error; } /** * Fires after the XML-RPC user has been authenticated but before the rest of * the method logic begins. * * All built-in XML-RPC methods use the action xmlrpc_call, with a parameter * equal to the method's name, e.g., wp.getUsersBlogs, wp.newPost, etc. * * @since 2.5.0 * * @param string $name The method name. */ do_action('xmlrpc_call', 'wp.getUsersBlogs'); $blogs = (array) get_blogs_of_user($user->ID); $struct = array(); $primary_blog_id = 0; $active_blog = get_active_blog_for_user($user->ID); if ($active_blog) { $primary_blog_id = (int) $active_blog->blog_id; } foreach ($blogs as $blog) { // Don't include blogs that aren't hosted at this site. if ($blog->site_id != get_current_network_id()) { continue; } $blog_id = $blog->userblog_id; switch_to_blog($blog_id); $is_admin = current_user_can('manage_options'); $is_primary = (int) $blog_id === $primary_blog_id; $struct[] = array('isAdmin' => $is_admin, 'isPrimary' => $is_primary, 'url' => home_url('/'), 'blogid' => (string) $blog_id, 'blogName' => get_option('blogname'), 'xmlrpc' => site_url('xmlrpc.php', 'rpc')); restore_current_blog(); } return $struct; }
/** * Notify user of signup success. * * This is the notification function used when site registration * is enabled. * * Filter {@see 'wpmu_signup_blog_notification'} to bypass this function or * replace it with your own notification behavior. * * Filter {@see 'wpmu_signup_blog_notification_email'} and * {@see 'wpmu_signup_blog_notification_subject'} to change the content * and subject line of the email sent to newly registered users. * * @since MU * * @param string $domain The new blog domain. * @param string $path The new blog path. * @param string $title The site title. * @param string $user_login The user's login name. * @param string $user_email The user's email address. * @param string $key The activation key created in wpmu_signup_blog() * @param array $meta By default, contains the requested privacy setting and lang_id. * @return bool */ function wpmu_signup_blog_notification($domain, $path, $title, $user_login, $user_email, $key, $meta = array()) { /** * Filters whether to bypass the new site email notification. * * @since MU * * @param string|bool $domain Site domain. * @param string $path Site path. * @param string $title Site title. * @param string $user_login User login name. * @param string $user_email User email address. * @param string $key Activation key created in wpmu_signup_blog(). * @param array $meta By default, contains the requested privacy setting and lang_id. */ if (!apply_filters('wpmu_signup_blog_notification', $domain, $path, $title, $user_login, $user_email, $key, $meta)) { return false; } // Send email with activation link. if (!is_subdomain_install() || get_current_network_id() != 1) { $activate_url = network_site_url("wp-activate.php?key={$key}"); } else { $activate_url = "http://{$domain}{$path}wp-activate.php?key={$key}"; } // @todo use *_url() API $activate_url = esc_url($activate_url); $admin_email = get_site_option('admin_email'); if ($admin_email == '') { $admin_email = 'support@' . $_SERVER['SERVER_NAME']; } $from_name = get_site_option('site_name') == '' ? 'WordPress' : esc_html(get_site_option('site_name')); $message_headers = "From: \"{$from_name}\" <{$admin_email}>\n" . "Content-Type: text/plain; charset=\"" . get_option('blog_charset') . "\"\n"; $user = get_user_by('login', $user_login); $switched_locale = switch_to_locale(get_user_locale($user)); $message = sprintf(apply_filters('wpmu_signup_blog_notification_email', __("To activate your blog, please click the following link:\n\n%s\n\nAfter you activate, you will receive *another email* with your login.\n\nAfter you activate, you can visit your site here:\n\n%s"), $domain, $path, $title, $user_login, $user_email, $key, $meta), $activate_url, esc_url("http://{$domain}{$path}"), $key); // TODO: Don't hard code activation link. $subject = sprintf(apply_filters('wpmu_signup_blog_notification_subject', _x('[%1$s] Activate %2$s', 'New site notification email subject'), $domain, $path, $title, $user_login, $user_email, $key, $meta), $from_name, esc_url('http://' . $domain . $path)); wp_mail($user_email, wp_specialchars_decode($subject), $message, $message_headers); if ($switched_locale) { restore_previous_locale(); } return true; }
/** * Adjusts the user count option to only include users in the network. * * This is a hacky way to fix `wp_update_network_user_counts()` which does not count users in the current network, * but instead counts all users in the entire setup which is incorrect. * * @since 1.0.0 * @access private * * @param int $user_count The original number of users. * @return int The modified number of users. */ function _ga_fix_network_user_counts($user_count) { global $wpdb; if (!is_multinetwork()) { return $user_count; } //TODO: When the time is right, this function should use the network_id argument that WP Network Roles introduces. $site_ids = get_sites(array('fields' => 'ids', 'network_id' => get_current_network_id())); $args = array('number' => 20, 'meta_query' => array('relation' => 'OR')); foreach ($site_ids as $site_id) { $args['meta_query'][] = array('key' => $wpdb->get_blog_prefix($site_id) . 'capabilities', 'compare' => 'EXISTS'); } $user_query = new WP_User_Query($args); return $user_query->total_users; }
/** * Retrieves the IDs of all sites in the current network. * * If the $global flag is set, it will get the IDs for all sites in all networks. * * @since 1.0.0 * @access public * @static * * @param boolean $global Whether the site IDs for all networks should be retrieved. * @return array The site IDs. */ public static function get_network_site_ids($global = false) { $ids = array(); if (version_compare(get_bloginfo('version'), '4.6', '<')) { $args = array(); if ($global) { $args['network_id'] = 0; } foreach (wp_get_sites($args) as $site) { $ids[] = $site['blog_id']; } } else { $args = array('fields' => 'ids'); if (!$global) { $args['network_id'] = get_current_network_id(); } $ids = get_sites($args); } return $ids; }
/** * Adjusts the query arguments for the Network Users list table to only show users in the network. * * It is usually undesirable to have a network administrator see all users regardless of whether * they're part of his/her network or not. This function ensures that only the global admin exposes * all users. * * @since 1.0.0 * @access private * * @param array $args Original query arguments. * @return array Modified query arguments. */ function _ga_adjust_users_list_table_query_args($args) { global $wpdb; if (!is_multinetwork() || !is_network_admin()) { return $args; } //TODO: When the time is right, this function should use the network_id argument that WP Network Roles introduces. $site_ids = get_sites(array('fields' => 'ids', 'network_id' => get_current_network_id())); // That's a large meta query, but it's all we can do here at this point. $site_queries = array(); foreach ($site_ids as $site_id) { $site_queries[] = array('key' => $wpdb->get_blog_prefix($site_id) . 'capabilities', 'compare' => 'EXISTS'); } $site_queries['relation'] = 'OR'; if (empty($args['meta_query'])) { $args['meta_query'] = $site_queries; } else { $args['meta_query'] = array('relation' => 'AND', array($args['meta_query'], $site_queries)); } return $args; }