Index: src/wp-includes/ms-blogs.php
===================================================================
--- src/wp-includes/ms-blogs.php	(revision 41242)
+++ src/wp-includes/ms-blogs.php	(working copy)
@@ -538,6 +538,112 @@
 }
 
 /**
+ * Retrieves a site by given site data.
+ *
+ * @since 4.8.0
+ *
+ * @param int|string|array $field Name of a single field or an array of multiple fields to query against.
+ *                                The supported fields are 'id', 'slug', 'domain', 'path' and 'network_id'.
+ * @param mixed            $value Optional. If $field is the name of a field, this parameter must be
+ *                                provided for that field's value to query for. Otherwise it can be omitted.
+ *                                Default null.
+ * @return WP_Site|null The site object or null if not found.
+ */
+function get_site_by( $field, $value = null ) {
+	// If only an ID is provided, take a shortcut.
+	if ( 'id' === $field ) {
+		return get_site( $value );
+	}
+
+	$args = $field;
+	if ( ! is_array( $args ) ) {
+		$args = array( $field => $value );
+	}
+
+	// If only an ID is provided, take a shortcut.
+	if ( isset( $args['id'] ) && count( $args ) === 1 ) {
+		return get_site( $args['id'] );
+	}
+
+	if ( isset( $args['id'] ) ) {
+		if ( ! empty( $args['site__in'] ) ) {
+			$args['site__in'][] = $args['id'];
+		} else {
+			$args['site__in'] = array( $args['id'] );
+		}
+
+		unset( $args['id'] );
+	}
+
+	if ( isset( $args['slug'] ) ) {
+		$network = isset( $args['network_id'] ) ? get_network( $args['network_id'] ) : get_network();
+
+		// Create domain and path from the slug.
+		if ( is_subdomain_install() ) {
+			$args['domain'] = trim( $args['slug'], '/' ) . '.' . preg_replace( '|^www\.|', '', $network->domain );
+			$args['path'] = $network->path;
+		} else {
+			$args['domain'] = $network->domain;
+			$args['path'] = $network->path . trim( $args['slug'], '/' ) . '/';
+		}
+
+		unset( $args['slug'] );
+	} elseif ( isset( $args['url'] ) ) {
+		$parts = wp_parse_url( $args['url'] );
+		if ( ! $parts ) {
+			return null;
+		}
+
+		// Create domain and path from the URL.
+		$args['domain'] = $parts['host'];
+		if ( ! empty( $parts['path'] ) ) {
+			$args['path'] = '/' . trim( $parts['path'], '/' ) . '/';
+		} else {
+			$args['path'] = '/';
+		}
+
+		unset( $args['url'] );
+	} elseif ( isset( $args['domain'] ) && ! isset( $args['path'] ) ) {
+
+		// Do not allow domain-only lookup if not a subdomain install.
+		if ( ! is_subdomain_install() && empty( $args['site__in'] ) ) {
+			return null;
+		}
+	} elseif ( isset( $args['path'] ) && ! isset( $args['domain'] ) ) {
+
+		// Do not allow path-only lookup if not a subdirectory install.
+		if ( is_subdomain_install() && empty( $args['site__in'] ) ) {
+			return null;
+		}
+	}
+
+	// If none of these critical arguments are provided, bail.
+	if ( ! isset( $args['site__in'] ) && ! isset( $args['domain'] ) && ! isset( $args['path'] ) ) {
+		return null;
+	}
+
+	// If the domain is prefixed with www., account for the unprefixed variant as well.
+	if ( isset( $args['domain'] ) && substr( $args['domain'], 0, 4 ) == 'www.' ) {
+		$nowww = substr( $args['domain'], 4 );
+
+		$args['domain__in'] = array( $nowww, $args['domain'] );
+		unset( $args['domain'] );
+	}
+
+	$args['number'] = 1;
+	$args['fields'] = '';
+	$args['count']  = false;
+
+	$sites = get_sites( $args );
+
+	if ( empty( $sites ) ) {
+		return null;
+	}
+
+	return array_shift( $sites );
+}
+
+/**
  * Adds any sites from the given ids to the cache that do not already exist in cache.
  *
  * @since 4.6.0
