WP_REST_Attachments_Controller::get_attachment_upload_subdirprotectedWP 7.1.0

Returns the uploads subdirectory an attachment is stored in.

Used to place a sideloaded file alongside the attachment it extends. The result is concatenated into a filesystem path by the caller, so it is returned only when the attachment resolves inside the uploads directory and the stored path is well formed.

Method of the class: WP_REST_Attachments_Controller{}

No Hooks.

Returns

string|null. Subdirectory beginning with a slash, an empty string when the attachment sits in the base directory, or null when the attachment is not inside the uploads directory.

Usage

// protected - for code of main (parent) or child class
$result = $this->get_attachment_upload_subdir( $attached_file ): ?string;
$attached_file(string) (required)
Absolute path to the attached file.

Changelog

Since 7.1.0 Introduced.

WP_REST_Attachments_Controller::get_attachment_upload_subdir() code WP 7.1

protected function get_attachment_upload_subdir( string $attached_file ): ?string {
	$uploads = wp_get_upload_dir();
	if ( empty( $uploads['basedir'] ) ) {
		return null;
	}

	$basedir  = untrailingslashit( wp_normalize_path( $uploads['basedir'] ) );
	$file_dir = wp_normalize_path( dirname( $attached_file ) );

	/*
	 * The attachment's directory must be the uploads base directory itself
	 * or a directory inside it. The trailing slash in the prefix comparison
	 * keeps a sibling directory that merely shares the prefix (for example
	 * 'uploads-elsewhere' next to 'uploads') from matching.
	 */
	if ( $file_dir !== $basedir && ! str_starts_with( $file_dir, trailingslashit( $basedir ) ) ) {
		return null;
	}

	$subdir = (string) substr( $file_dir, strlen( $basedir ) );

	// A prefix match alone does not rule out a path that climbs back out.
	if ( in_array( '..', explode( '/', $subdir ), true ) ) {
		return null;
	}

	return $subdir;
}