diff --git a/wp-includes/class-wp-network.php b/wp-includes/class-wp-network.php index 979e08341c..5b49b0dd29 100644 --- a/wp-includes/class-wp-network.php +++ b/wp-includes/class-wp-network.php @@ -151,4 +151,158 @@ class WP_Network { $this->cookie_domain = substr( $this->cookie_domain, 4 ); } } + + /** + * Retrieve a network by its domain and path. + * + * @since 4.4.0 + * @access public + * @static + * + * @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 WP_Network|bool Network object if successful. False when no network is found. + */ + public static function get_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 ( ! empty( $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 = $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 ( true === $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 ( false === $using_paths ) { + $network = $wpdb->get_row( " + SELECT * FROM {$wpdb->site} + WHERE domain IN ({$search_domains}) + ORDER BY CHAR_LENGTH(domain) + DESC LIMIT 1 + " ); + + if ( ! empty( $network ) && ! is_wp_error( $network ) ) { + return new WP_Network( $network ); + } + + return false; + + } else { + $search_paths = "'" . implode( "', '", $wpdb->_escape( $paths ) ) . "'"; + $networks = $wpdb->get_results( " + SELECT * FROM {$wpdb->site} + WHERE domain IN ({$search_domains}) + AND path IN ({$search_paths}) + ORDER 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 ( true === $found ) { + return new WP_Network( $network ); + } + + return false; + } } diff --git a/wp-includes/ms-load.php b/wp-includes/ms-load.php index 9690e1f94c..451e0dcc6d 100644 --- a/wp-includes/ms-load.php +++ b/wp-includes/ms-load.php @@ -113,145 +113,15 @@ function ms_site_check() { * Retrieve a network object by its domain and path. * * @since 3.9.0 - * - * @global wpdb $wpdb + * @since 4.4.0 Converted to a wrapper for WP_Network::get_by_path() * * @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. + * @return WP_Network|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 - WHERE 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 - WHERE domain IN ($search_domains) AND path IN ($search_paths) - ORDER 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; + return WP_Network::get_by_path( $domain, $path, $segments ); } /** diff --git a/wp-includes/ms-settings.php b/wp-includes/ms-settings.php index a231473fb5..00da6da92f 100644 --- a/wp-includes/ms-settings.php +++ b/wp-includes/ms-settings.php @@ -87,7 +87,7 @@ if ( !isset( $current_site ) || !isset( $current_blog ) ) { } } if ( empty( $current_site ) ) { - $current_site = get_network_by_path( $domain, $path, 1 ); + $current_site = WP_Network::get_by_path( $domain, $path, 1 ); } if ( empty( $current_site ) ) { @@ -118,7 +118,7 @@ if ( !isset( $current_site ) || !isset( $current_blog ) ) { $current_site = WP_Network::get_instance( $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 ); + $current_site = WP_Network::get_by_path( $domain, $path, 1 ); } } diff --git a/wp-includes/version.php b/wp-includes/version.php index d2f837c176..f188597f8b 100644 --- a/wp-includes/version.php +++ b/wp-includes/version.php @@ -4,7 +4,7 @@ * * @global string $wp_version */ -$wp_version = '4.4-alpha-34098'; +$wp_version = '4.4-alpha-34099'; /** * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.