Commit 8c892d10 authored by Jeremy Felt's avatar Jeremy Felt
Browse files

Don't filter absolute paths when deleting an original file

The `wp_delete_file` filter  is used in two different ways. When
filtering the filename for the removal of thumbnails, extra image
sizes, and backup sizes, a relative path is expected in return. This
relative path is then used to rebuild the absolute path before
`unlink()` fires.

When filtering directly in `wp_delete_file()`, an absolute path is
expected at all times.

This fixes a case where original files would not be deleted from S3
when removed from the media library, but where all of the thumbnails
would be deleted.

See https://github.com/humanmade/S3-Uploads/issues/92
See https://core.trac.wordpress.org/ticket/39476
parent dbbd1c41
Loading
Loading
Loading
Loading
+18 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ class S3_Uploads {
	private        $secret;

	public $original_upload_dir;
	public $original_file;

	/**
	 *
@@ -46,6 +47,7 @@ class S3_Uploads {

		add_filter( 'upload_dir', array( $this, 'filter_upload_dir' ) );
		add_filter( 'wp_image_editors', array( $this, 'filter_editors' ), 9 );
		add_action( 'delete_attachment', array( $this, 'set_original_file' ) );
		add_filter( 'wp_delete_file', array( $this, 'wp_filter_delete_file' ) );
		add_filter( 'wp_read_image_metadata', array( $this, 'wp_filter_read_image_metadata' ), 10, 2 );
		remove_filter( 'admin_notices', 'wpthumb_errors' );
@@ -102,6 +104,17 @@ class S3_Uploads {
		return $dirs;
	}

	/**
	 * Capture the full path to the original file being deleted. This
	 * is used when determining whether an absolute or relative path
	 * should be used when deleting the file.
	 *
	 * @param $post_id
	 */
	public function set_original_file( $post_id ) {
		$this->original_file = get_attached_file( $post_id );
	}

	/**
	 * When WordPress removes files, it's expecting to do so on
	 * absolute file paths, as such it breaks when using uris for
@@ -115,6 +128,11 @@ class S3_Uploads {
	public function wp_filter_delete_file( $file_path ) {
		$dir = wp_upload_dir();

		// When `wp_delete_file()` is called directly, it expects an absolute path.
		if ( $file_path === $this->original_file ) {
			return $file_path;
		}

		return str_replace( trailingslashit( $dir['basedir'] ), '', $file_path );
	}