Loading inc/class-s3-uploads.php +45 −14 Original line number Diff line number Diff line Loading @@ -47,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_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' ); add_action( 'wp_handle_sideload_prefilter', array( $this, 'filter_sideload_move_temp_file_to_s3' ) ); Loading Loading @@ -216,4 +217,34 @@ class S3_Uploads { return $file; } /** * Filters wp_read_image_metadata. exif_read_data() doesn't work on * file streams so we need to make a temporary local copy to extract * exif data from. * * @param array $meta * @param string $file * @return array|bool */ public function wp_filter_read_image_metadata( $meta, $file ) { remove_filter( 'wp_read_image_metadata', array( $this, 'wp_filter_read_image_metadata' ), 10 ); $temp_file = $this->copy_image_from_s3( $file ); $meta = wp_read_image_metadata( $temp_file ); add_filter( 'wp_read_image_metadata', array( $this, 'wp_filter_read_image_metadata' ), 10, 2 ); unlink( $temp_file ); return $meta; } /** * Get a local copy of the file. * * @param string $file * @return string */ public function copy_image_from_s3( $file ) { $temp_filename = wp_tempnam( $file, 's3-uploads' ); copy( $file, $temp_filename ); return $temp_filename; } } tests/data/canola.jpgdeleted 100644 → 0 −198 KiB Loading image diff... tests/data/sunflower.jpg 0 → 100644 +58 KiB Loading image diff... tests/test-s3-uploads-image-editor-imagick.php +7 −7 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ class Test_S3_Uploads_Image_Editor_Imagick extends WP_UnitTestCase { public function setUp() { $this->image_path = dirname( __FILE__ ) . '/data/canola.jpg'; $this->image_path = dirname( __FILE__ ) . '/data/sunflower.jpg'; require_once ABSPATH . WPINC . '/class-wp-image-editor.php'; require_once ABSPATH . WPINC . '/class-wp-image-editor-imagick.php'; Loading @@ -26,13 +26,13 @@ class Test_S3_Uploads_Image_Editor_Imagick extends WP_UnitTestCase { public function test_save_image_with_inbuilt_fails() { $upload_dir = wp_upload_dir(); $path = $upload_dir['basedir'] . '/canola.jpg'; $path = $upload_dir['basedir'] . '/sunflower.jpg'; copy( $this->image_path, $path ); $image_editor = new WP_Image_Editor_Imagick( $path ); $image_editor->load(); $status = $image_editor->save( $upload_dir['basedir'] . '/canola-100x100.jpg' ); $status = $image_editor->save( $upload_dir['basedir'] . '/sunflower-100x100.jpg' ); $this->assertWPError( $status ); } Loading @@ -40,19 +40,19 @@ class Test_S3_Uploads_Image_Editor_Imagick extends WP_UnitTestCase { public function test_save_image() { $upload_dir = wp_upload_dir(); $path = $upload_dir['basedir'] . '/canola.jpg'; $path = $upload_dir['basedir'] . '/sunflower.jpg'; copy( $this->image_path, $path ); $image_editor = new S3_Uploads_Image_Editor_Imagick( $path ); $image_editor->load(); $image_editor->resize( 100, 100, true ); $status = $image_editor->save( $upload_dir['basedir'] . '/canola-100x100.jpg' ); $status = $image_editor->save( $upload_dir['basedir'] . '/sunflower-100x100.jpg' ); $this->assertNotInstanceOf( 'WP_Error', $status ); $this->assertEquals( $upload_dir['basedir'] . '/canola-100x100.jpg', $status['path'] ); $this->assertEquals( 'canola-100x100.jpg', $status['file'] ); $this->assertEquals( $upload_dir['basedir'] . '/sunflower-100x100.jpg', $status['path'] ); $this->assertEquals( 'sunflower-100x100.jpg', $status['file'] ); $this->assertEquals( 100, $status['width'] ); $this->assertEquals( 100, $status['height'] ); Loading tests/test-s3-uploads-stream-wrapper.php +22 −22 Original line number Diff line number Diff line Loading @@ -19,8 +19,8 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_copy_via_stream_wrapper() { $local_path = dirname( __FILE__ ) . '/data/canola.jpg'; $remote_path = 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg'; $local_path = dirname( __FILE__ ) . '/data/sunflower.jpg'; $remote_path = 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg'; $result = copy( $local_path, $remote_path ); $this->assertTrue( $result ); $this->assertEquals( file_get_contents( $local_path ), file_get_contents( $remote_path ) ); Loading @@ -28,18 +28,18 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_rename_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $result = rename( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola-test.jpg' ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $result = rename( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower-test.jpg' ); $this->assertTrue( $result ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola-test.jpg' ) ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower-test.jpg' ) ); } public function test_unlink_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $result = unlink( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $result = unlink( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $this->assertTrue( $result ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ) ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ) ); } public function test_copy_via_stream_wrapper_fails_on_invalid_permission() { Loading @@ -50,14 +50,14 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { $uploads->register_stream_wrapper(); $bucket_root = strtok( S3_UPLOADS_BUCKET, '/' ); $result = @copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . $bucket_root . '/canola.jpg' ); $result = @copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . $bucket_root . '/sunflower.jpg' ); $this->assertFalse( $result ); } public function test_rename_via_stream_wrapper_fails_on_invalid_permission() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); stream_wrapper_unregister( 's3' ); Loading @@ -65,7 +65,7 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { $uploads->register_stream_wrapper(); $bucket_root = strtok( S3_UPLOADS_BUCKET, '/' ); $result = @rename( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg', 's3://' . $bucket_root . '/canola.jpg' ); $result = @rename( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg', 's3://' . $bucket_root . '/sunflower.jpg' ); $this->assertFalse( $result ); } Loading @@ -87,23 +87,23 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { } public function get_file_exists_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ) ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola-missing.jpg' ) ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ) ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower-missing.jpg' ) ); } public function test_getimagesize_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $file = 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg'; copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $file = 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg'; $image = getimagesize( $file ); $this->assertEquals( array( 640, 480, 419, 2, 'width="640" height="480"', 'width="640" height="419"', 'bits' => 8, 'channels' => 3, 'mime' => 'image/jpeg', Loading @@ -112,8 +112,8 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_stream_wrapper_supports_seeking() { $file = 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg'; copy( dirname( __FILE__ ) . '/data/canola.jpg', $file ); $file = 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg'; copy( dirname( __FILE__ ) . '/data/sunflower.jpg', $file ); $f = fopen( $file, 'r' ); $result = fseek( $f, 0, SEEK_END ); Loading @@ -124,8 +124,8 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_wp_handle_upload() { $path = tempnam( sys_get_temp_dir(), 'canola' ) . '.jpg'; copy( dirname( __FILE__ ) . '/data/canola.jpg', $path ); $path = tempnam( sys_get_temp_dir(), 'sunflower' ) . '.jpg'; copy( dirname( __FILE__ ) . '/data/sunflower.jpg', $path ); $contents = file_get_contents( $path ); $file = array( 'error' => null, Loading Loading
inc/class-s3-uploads.php +45 −14 Original line number Diff line number Diff line Loading @@ -47,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_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' ); add_action( 'wp_handle_sideload_prefilter', array( $this, 'filter_sideload_move_temp_file_to_s3' ) ); Loading Loading @@ -216,4 +217,34 @@ class S3_Uploads { return $file; } /** * Filters wp_read_image_metadata. exif_read_data() doesn't work on * file streams so we need to make a temporary local copy to extract * exif data from. * * @param array $meta * @param string $file * @return array|bool */ public function wp_filter_read_image_metadata( $meta, $file ) { remove_filter( 'wp_read_image_metadata', array( $this, 'wp_filter_read_image_metadata' ), 10 ); $temp_file = $this->copy_image_from_s3( $file ); $meta = wp_read_image_metadata( $temp_file ); add_filter( 'wp_read_image_metadata', array( $this, 'wp_filter_read_image_metadata' ), 10, 2 ); unlink( $temp_file ); return $meta; } /** * Get a local copy of the file. * * @param string $file * @return string */ public function copy_image_from_s3( $file ) { $temp_filename = wp_tempnam( $file, 's3-uploads' ); copy( $file, $temp_filename ); return $temp_filename; } }
tests/test-s3-uploads-image-editor-imagick.php +7 −7 Original line number Diff line number Diff line Loading @@ -3,7 +3,7 @@ class Test_S3_Uploads_Image_Editor_Imagick extends WP_UnitTestCase { public function setUp() { $this->image_path = dirname( __FILE__ ) . '/data/canola.jpg'; $this->image_path = dirname( __FILE__ ) . '/data/sunflower.jpg'; require_once ABSPATH . WPINC . '/class-wp-image-editor.php'; require_once ABSPATH . WPINC . '/class-wp-image-editor-imagick.php'; Loading @@ -26,13 +26,13 @@ class Test_S3_Uploads_Image_Editor_Imagick extends WP_UnitTestCase { public function test_save_image_with_inbuilt_fails() { $upload_dir = wp_upload_dir(); $path = $upload_dir['basedir'] . '/canola.jpg'; $path = $upload_dir['basedir'] . '/sunflower.jpg'; copy( $this->image_path, $path ); $image_editor = new WP_Image_Editor_Imagick( $path ); $image_editor->load(); $status = $image_editor->save( $upload_dir['basedir'] . '/canola-100x100.jpg' ); $status = $image_editor->save( $upload_dir['basedir'] . '/sunflower-100x100.jpg' ); $this->assertWPError( $status ); } Loading @@ -40,19 +40,19 @@ class Test_S3_Uploads_Image_Editor_Imagick extends WP_UnitTestCase { public function test_save_image() { $upload_dir = wp_upload_dir(); $path = $upload_dir['basedir'] . '/canola.jpg'; $path = $upload_dir['basedir'] . '/sunflower.jpg'; copy( $this->image_path, $path ); $image_editor = new S3_Uploads_Image_Editor_Imagick( $path ); $image_editor->load(); $image_editor->resize( 100, 100, true ); $status = $image_editor->save( $upload_dir['basedir'] . '/canola-100x100.jpg' ); $status = $image_editor->save( $upload_dir['basedir'] . '/sunflower-100x100.jpg' ); $this->assertNotInstanceOf( 'WP_Error', $status ); $this->assertEquals( $upload_dir['basedir'] . '/canola-100x100.jpg', $status['path'] ); $this->assertEquals( 'canola-100x100.jpg', $status['file'] ); $this->assertEquals( $upload_dir['basedir'] . '/sunflower-100x100.jpg', $status['path'] ); $this->assertEquals( 'sunflower-100x100.jpg', $status['file'] ); $this->assertEquals( 100, $status['width'] ); $this->assertEquals( 100, $status['height'] ); Loading
tests/test-s3-uploads-stream-wrapper.php +22 −22 Original line number Diff line number Diff line Loading @@ -19,8 +19,8 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_copy_via_stream_wrapper() { $local_path = dirname( __FILE__ ) . '/data/canola.jpg'; $remote_path = 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg'; $local_path = dirname( __FILE__ ) . '/data/sunflower.jpg'; $remote_path = 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg'; $result = copy( $local_path, $remote_path ); $this->assertTrue( $result ); $this->assertEquals( file_get_contents( $local_path ), file_get_contents( $remote_path ) ); Loading @@ -28,18 +28,18 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_rename_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $result = rename( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola-test.jpg' ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $result = rename( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower-test.jpg' ); $this->assertTrue( $result ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola-test.jpg' ) ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower-test.jpg' ) ); } public function test_unlink_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $result = unlink( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $result = unlink( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $this->assertTrue( $result ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ) ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ) ); } public function test_copy_via_stream_wrapper_fails_on_invalid_permission() { Loading @@ -50,14 +50,14 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { $uploads->register_stream_wrapper(); $bucket_root = strtok( S3_UPLOADS_BUCKET, '/' ); $result = @copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . $bucket_root . '/canola.jpg' ); $result = @copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . $bucket_root . '/sunflower.jpg' ); $this->assertFalse( $result ); } public function test_rename_via_stream_wrapper_fails_on_invalid_permission() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); stream_wrapper_unregister( 's3' ); Loading @@ -65,7 +65,7 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { $uploads->register_stream_wrapper(); $bucket_root = strtok( S3_UPLOADS_BUCKET, '/' ); $result = @rename( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg', 's3://' . $bucket_root . '/canola.jpg' ); $result = @rename( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg', 's3://' . $bucket_root . '/sunflower.jpg' ); $this->assertFalse( $result ); } Loading @@ -87,23 +87,23 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { } public function get_file_exists_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ) ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/canola-missing.jpg' ) ); copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $this->assertTrue( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ) ); $this->assertFalse( file_exists( 's3://' . S3_UPLOADS_BUCKET . '/sunflower-missing.jpg' ) ); } public function test_getimagesize_via_stream_wrapper() { copy( dirname( __FILE__ ) . '/data/canola.jpg', 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg' ); $file = 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg'; copy( dirname( __FILE__ ) . '/data/sunflower.jpg', 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg' ); $file = 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg'; $image = getimagesize( $file ); $this->assertEquals( array( 640, 480, 419, 2, 'width="640" height="480"', 'width="640" height="419"', 'bits' => 8, 'channels' => 3, 'mime' => 'image/jpeg', Loading @@ -112,8 +112,8 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_stream_wrapper_supports_seeking() { $file = 's3://' . S3_UPLOADS_BUCKET . '/canola.jpg'; copy( dirname( __FILE__ ) . '/data/canola.jpg', $file ); $file = 's3://' . S3_UPLOADS_BUCKET . '/sunflower.jpg'; copy( dirname( __FILE__ ) . '/data/sunflower.jpg', $file ); $f = fopen( $file, 'r' ); $result = fseek( $f, 0, SEEK_END ); Loading @@ -124,8 +124,8 @@ class Test_S3_Uploads_Stream_Wrapper extends WP_UnitTestCase { public function test_wp_handle_upload() { $path = tempnam( sys_get_temp_dir(), 'canola' ) . '.jpg'; copy( dirname( __FILE__ ) . '/data/canola.jpg', $path ); $path = tempnam( sys_get_temp_dir(), 'sunflower' ) . '.jpg'; copy( dirname( __FILE__ ) . '/data/sunflower.jpg', $path ); $contents = file_get_contents( $path ); $file = array( 'error' => null, Loading