Automattic\WooCommerce\Internal\Utilities

URL::get_parent_url()publicWC 1.0

Outputs the parent URL.

For example, if $this->get_url() returns "https://example.com/foo/bar/baz" then this method will return "https://example.com/foo/bar/".

When a grand-parent is needed, the optional $level parameter can be used. By default this is set to 1 (parent). 2 will yield the grand-parent, 3 will yield the great grand-parent, etc.

If a level is specified that exceeds the number of path segments, this method will return false.

Method of the class: URL{}

No Hooks.

Return

String|false.

Usage

$URL = new URL();
$URL->get_parent_url( $level );
$level(int)
Used to indicate the level of parent.
Default: 1

URL::get_parent_url() code WC 8.6.1

public function get_parent_url( int $level = 1 ) {
	if ( $level < 1 ) {
		$level = 1;
	}

	$parts_count               = count( $this->path_parts );
	$parent_path_parts_to_keep = $parts_count - $level;

	/*
	 * With the exception of file URLs, we do not allow obtaining (grand-)parent directories that require
	 * us to describe them using directory traversals. For example, given "http://hostname/foo/bar/baz.png" we do
	 * not permit determining anything more than 2 levels up (we cannot go beyond "http://hostname/").
	 */
	if ( 'file' !== $this->components['scheme'] && $parent_path_parts_to_keep < 0 ) {
		return false;
	}

	// In the specific case of an absolute filepath describing the root directory, there can be no parent.
	if ( 'file' === $this->components['scheme'] && $this->is_absolute && empty( $this->path_parts ) ) {
		return false;
	}

	// Handle cases where the path starts with one or more 'dot segments'. Since the path has already been
	// processed, we can be confident that any such segments are at the start of the path.
	if ( $parts_count > 0 && ( '.' === $this->path_parts[0] || '..' === $this->path_parts[0] ) ) {
		// Determine the index of the last dot segment (ex: given the path '/../../foo' it would be 1).
		$single_dots   = array_keys( $this->path_parts, '.', true );
		$double_dots   = array_keys( $this->path_parts, '..', true );
		$max_dot_index = max( array_merge( $single_dots, $double_dots ) );

		// Prepend the required number of traversals and discard unnessary trailing segments.
		$last_traversal = $max_dot_index + ( $this->is_non_root_directory ? 1 : 0 );
		$parent_path    = str_repeat( '../', $level ) . join( '/', array_slice( $this->path_parts, 0, $last_traversal ) );
	} elseif ( $parent_path_parts_to_keep < 0 ) {
		// For relative filepaths only, we use traversals to describe the requested parent.
		$parent_path = untrailingslashit( str_repeat( '../', $parent_path_parts_to_keep * -1 ) );
	} else {
		// Otherwise, in a very simple case, we just remove existing parts.
		$parent_path = implode( '/', array_slice( $this->path_parts, 0, $parent_path_parts_to_keep ) );
	}

	if ( $this->is_relative() && '' === $parent_path ) {
		$parent_path = '.';
	}

	// Append a trailing slash, since a parent is always a directory. The only exception is the current working directory.
	$parent_path .= '/';

	// For absolute paths, apply a leading slash (does not apply if we have a root path).
	if ( $this->is_absolute && 0 !== strpos( $parent_path, '/' ) ) {
		$parent_path = '/' . $parent_path;
	}

	// Form the parent URL (ditching the query and fragment, if set).
	$parent_url = $this->get_url(
		array(
			'path'     => $parent_path,
			'query'    => null,
			'fragment' => null,
		)
	);

	// We process the parent URL through a fresh instance of this class, for consistency.
	return ( new self( $parent_url ) )->get_url();
}