WP_Network::get_by_path()public staticWP 4.4.0

Retrieves the closest matching network for a domain and path.

This will not necessarily return an exact match for a domain and path. Instead, it breaks the domain and path into pieces that are then used to match the closest possibility from a query.

The intent of this method is to match a network during bootstrap for a requested site address.

Method of the class: WP_Network{}

Return

WP_Network|false. Network object if successful. False when no network is found.

Usage

$result = WP_Network::get_by_path( $domain, $path, $segments );
$domain(string)
Domain to check.
Default: ''
$path(string)
Path to check.
Default: ''
$segments(int|null)
Path segments to use.
Default: null, or the full path

Changelog

Since 4.4.0 Introduced.

WP_Network::get_by_path() code WP 6.5.2

public static function get_by_path( $domain = '', $path = '', $segments = null ) {
	$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-installation.
	 */
	$using_paths = true;
	if ( wp_using_ext_object_cache() ) {
		$using_paths = get_networks(
			array(
				'number'       => 1,
				'count'        => true,
				'path__not_in' => '/',
			)
		);
	}

	$paths = array();
	if ( $using_paths ) {
		$path_segments = array_filter( explode( '/', trim( $path, '/' ) ) );

		/**
		 * Filters 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[] = '/';
	}

	/**
	 * Determines 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|false|WP_Network $network  Network value to return by path. Default null
	 *                                        to continue retrieving the network.
	 * @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 string[]              $paths    Array of 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;
	}

	if ( ! $using_paths ) {
		$networks = get_networks(
			array(
				'number'     => 1,
				'orderby'    => array(
					'domain_length' => 'DESC',
				),
				'domain__in' => $domains,
			)
		);

		if ( ! empty( $networks ) ) {
			return array_shift( $networks );
		}

		return false;
	}

	$networks = get_networks(
		array(
			'orderby'    => array(
				'domain_length' => 'DESC',
				'path_length'   => 'DESC',
			),
			'domain__in' => $domains,
			'path__in'   => $paths,
		)
	);

	/*
	 * 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 $network;
	}

	return false;
}