diff --git a/src/wp-admin/includes/file.php b/src/wp-admin/includes/file.php index ddd2be849a..759b0974bb 100644 --- a/src/wp-admin/includes/file.php +++ b/src/wp-admin/includes/file.php @@ -2555,3 +2555,41 @@ function wp_opcache_invalidate( $filepath, $force = false ) { return false; } + +/** + * Wrapper for PHP filesize with filters and casting the result as an integer. + * + * @since 6.0.0 + * + * @link https://www.php.net/manual/en/function.filesize.php + * + * @param string $path Path to the file. + * @return int The size of the file in bytes, or 0 in the event of an error. + */ +function wp_filesize( $path ) { + /** + * Filters the result of wp_filesize before the PHP function is run. + * + * @since 6.0.0 + * + * @param null|int $size The unfiltered value. Returning an int from the callback bypasses the filesize call. + * @param string $path Path to the file. + */ + $size = apply_filters( 'pre_wp_filesize', null, $path ); + + if ( is_int( $size ) ) { + return $size; + } + + $size = (int) @filesize( $path ); + + /** + * Filters the size of the file. + * + * @since 6.0.0 + * + * @param int $size The result of PHP filesize on the file. + * @param string $path Path to the file. + */ + return (int) apply_filters( 'wp_filesize', $size, $path ); +} diff --git a/src/wp-admin/includes/image.php b/src/wp-admin/includes/image.php index 627fdfb4b5..2818b3dd5d 100644 --- a/src/wp-admin/includes/image.php +++ b/src/wp-admin/includes/image.php @@ -210,6 +210,9 @@ function _wp_image_meta_replace_original( $saved_data, $original_file, $image_me // Store the original image file name in image_meta. $image_meta['original_image'] = wp_basename( $original_file ); + // Add image file size. + $image_meta['filesize'] = wp_filesize( $new_file ); + return $image_meta; } @@ -235,10 +238,11 @@ function wp_create_image_subsizes( $file, $attachment_id ) { // Default image meta. $image_meta = array( - 'width' => $imagesize[0], - 'height' => $imagesize[1], - 'file' => _wp_relative_upload_path( $file ), - 'sizes' => array(), + 'width' => $imagesize[0], + 'height' => $imagesize[1], + 'file' => _wp_relative_upload_path( $file ), + 'filesize' => wp_filesize( $file ), + 'sizes' => array(), ); // Fetch additional metadata from EXIF/IPTC. @@ -629,6 +633,11 @@ function wp_generate_attachment_metadata( $attachment_id, $file ) { // Remove the blob of binary data from the array. unset( $metadata['image']['data'] ); + // Capture file size for cases where it has not been captured yet, such as PDFs. + if ( ! isset( $metadata['filesize'] ) && file_exists( $file ) ) { + $metadata['filesize'] = wp_filesize( $file ); + } + /** * Filters the generated attachment meta data. * diff --git a/src/wp-admin/includes/media.php b/src/wp-admin/includes/media.php index d9dcbd5d7d..093ee69360 100644 --- a/src/wp-admin/includes/media.php +++ b/src/wp-admin/includes/media.php @@ -3378,7 +3378,7 @@ function attachment_submitbox_metadata() { if ( isset( $meta['filesize'] ) ) { $file_size = $meta['filesize']; } elseif ( file_exists( $file ) ) { - $file_size = filesize( $file ); + $file_size = wp_filesize( $file ); } if ( ! empty( $file_size ) ) { diff --git a/src/wp-includes/class-wp-image-editor-gd.php b/src/wp-includes/class-wp-image-editor-gd.php index f32e2b4202..f745bcf9f8 100644 --- a/src/wp-includes/class-wp-image-editor-gd.php +++ b/src/wp-includes/class-wp-image-editor-gd.php @@ -497,6 +497,7 @@ class WP_Image_Editor_GD extends WP_Image_Editor { 'width' => $this->size['width'], 'height' => $this->size['height'], 'mime-type' => $mime_type, + 'filesize' => wp_filesize( $filename ), ); } diff --git a/src/wp-includes/class-wp-image-editor-imagick.php b/src/wp-includes/class-wp-image-editor-imagick.php index d898db553a..fea2e5e4ef 100644 --- a/src/wp-includes/class-wp-image-editor-imagick.php +++ b/src/wp-includes/class-wp-image-editor-imagick.php @@ -729,6 +729,7 @@ class WP_Image_Editor_Imagick extends WP_Image_Editor { 'width' => $this->size['width'], 'height' => $this->size['height'], 'mime-type' => $mime_type, + 'filesize' => wp_filesize( $filename ), ); } diff --git a/src/wp-includes/media.php b/src/wp-includes/media.php index 5ab3cd1913..b3204c2799 100644 --- a/src/wp-includes/media.php +++ b/src/wp-includes/media.php @@ -4046,7 +4046,7 @@ function wp_prepare_attachment_for_js( $attachment ) { if ( isset( $meta['filesize'] ) ) { $bytes = $meta['filesize']; } elseif ( file_exists( $attached_file ) ) { - $bytes = filesize( $attached_file ); + $bytes = wp_filesize( $attached_file ); } else { $bytes = ''; } diff --git a/src/wp-includes/post.php b/src/wp-includes/post.php index 10dddf859b..7cf8204e05 100644 --- a/src/wp-includes/post.php +++ b/src/wp-includes/post.php @@ -6538,6 +6538,7 @@ function wp_delete_attachment_files( $post_id, $meta, $backup_sizes, $file ) { * @type array $sizes Keys are size slugs, each value is an array containing * 'file', 'width', 'height', and 'mime-type'. * @type array $image_meta Image metadata. + * @type int $filesize File size of the attachment. * } */ function wp_get_attachment_metadata( $attachment_id = 0, $unfiltered = false ) { diff --git a/tests/phpunit/tests/file.php b/tests/phpunit/tests/file.php index 311ba30339..cf3ec2d356 100644 --- a/tests/phpunit/tests/file.php +++ b/tests/phpunit/tests/file.php @@ -262,4 +262,39 @@ class Tests_File extends WP_UnitTestCase { return $keys; } + + /** + * @ticket 49412 + * @covers ::wp_filesize + */ + function test_wp_filesize_with_nonexistent_file() { + $file = 'nonexistent/file.jpg'; + $this->assertEquals( 0, wp_filesize( $file ) ); + } + + /** + * @ticket 49412 + * @covers ::wp_filesize + */ + function test_wp_filesize() { + $file = DIR_TESTDATA . '/images/test-image-upside-down.jpg'; + + $this->assertEquals( filesize( $file ), wp_filesize( $file ) ); + + $filter = function() { + return 999; + }; + + add_filter( 'wp_filesize', $filter ); + + $this->assertEquals( 999, wp_filesize( $file ) ); + + $pre_filter = function() { + return 111; + }; + + add_filter( 'pre_wp_filesize', $pre_filter ); + + $this->assertEquals( 111, wp_filesize( $file ) ); + } } diff --git a/tests/phpunit/tests/image/editorGd.php b/tests/phpunit/tests/image/editorGd.php index 781ff96cb4..5d967bdcdb 100644 --- a/tests/phpunit/tests/image/editorGd.php +++ b/tests/phpunit/tests/image/editorGd.php @@ -100,6 +100,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 50, 'height' => 33, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-50x33.jpg' ), ), ); @@ -300,6 +301,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 10, 'height' => 7, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-10x7.jpg' ), ), // #1 @@ -308,6 +310,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 75, 'height' => 50, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-75x50.jpg' ), ), // #2 @@ -316,6 +319,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 30, 'height' => 20, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-30x20.jpg' ), ), // #3 @@ -324,6 +328,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 45, 'height' => 400, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-45x400.jpg' ), ), // #4 @@ -332,6 +337,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 50, 'height' => 33, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-50x33.jpg' ), ), // #5 @@ -340,6 +346,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 55, 'height' => 37, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-55x37.jpg' ), ), // #6 @@ -348,6 +355,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 83, 'height' => 55, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-83x55.jpg' ), ), // #7 @@ -356,6 +364,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 90, 'height' => 60, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-90x60.jpg' ), ), // #8 @@ -364,6 +373,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 105, 'height' => 70, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-105x70.jpg' ), ), // #9 @@ -372,6 +382,7 @@ class Tests_Image_Editor_GD extends WP_Image_UnitTestCase { 'width' => 200, 'height' => 133, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-200x133.jpg' ), ), ); diff --git a/tests/phpunit/tests/image/editorImagick.php b/tests/phpunit/tests/image/editorImagick.php index e82486d828..02e0590a2e 100644 --- a/tests/phpunit/tests/image/editorImagick.php +++ b/tests/phpunit/tests/image/editorImagick.php @@ -90,6 +90,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 50, 'height' => 33, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-50x33.jpg' ), ), ); @@ -289,6 +290,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 10, 'height' => 7, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-10x7.jpg' ), ), // #1 @@ -297,6 +299,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 75, 'height' => 50, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-75x50.jpg' ), ), // #2 @@ -305,6 +308,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 30, 'height' => 20, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-30x20.jpg' ), ), // #3 @@ -313,6 +317,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 45, 'height' => 400, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-45x400.jpg' ), ), // #4 @@ -321,6 +326,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 50, 'height' => 33, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-50x33.jpg' ), ), // #5 @@ -329,6 +335,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 55, 'height' => 37, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-55x37.jpg' ), ), // #6 @@ -337,6 +344,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 83, 'height' => 55, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-83x55.jpg' ), ), // #7 @@ -345,6 +353,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 90, 'height' => 60, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-90x60.jpg' ), ), // #8 @@ -353,6 +362,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 105, 'height' => 70, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-105x70.jpg' ), ), // #9 @@ -361,6 +371,7 @@ class Tests_Image_Editor_Imagick extends WP_Image_UnitTestCase { 'width' => 200, 'height' => 133, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( dirname( $file ) . '/waffles-200x133.jpg' ), ), ); diff --git a/tests/phpunit/tests/image/functions.php b/tests/phpunit/tests/image/functions.php index 8cd42a13b5..c02862b3e7 100644 --- a/tests/phpunit/tests/image/functions.php +++ b/tests/phpunit/tests/image/functions.php @@ -479,40 +479,47 @@ class Tests_Image_Functions extends WP_UnitTestCase { $this->assertNotEmpty( $attachment_id ); + $temp_dir = get_temp_dir(); + + $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); + $expected = array( - 'sizes' => array( + 'sizes' => array( 'full' => array( 'file' => 'wordpress-gsoc-flyer-pdf.jpg', 'width' => 1088, 'height' => 1408, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf.jpg' ), ), 'medium' => array( 'file' => 'wordpress-gsoc-flyer-pdf-232x300.jpg', 'width' => 232, 'height' => 300, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-232x300.jpg' ), ), 'large' => array( 'file' => 'wordpress-gsoc-flyer-pdf-791x1024.jpg', 'width' => 791, 'height' => 1024, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ), ), 'thumbnail' => array( 'file' => 'wordpress-gsoc-flyer-pdf-116x150.jpg', 'width' => 116, 'height' => 150, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ), ), ), + 'filesize' => wp_filesize( $test_file ), ); - $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); $this->assertSame( $expected, $metadata ); unlink( $test_file ); - $temp_dir = get_temp_dir(); foreach ( $metadata['sizes'] as $size ) { unlink( $temp_dir . $size['file'] ); } @@ -549,41 +556,49 @@ class Tests_Image_Functions extends WP_UnitTestCase { $this->assertNotEmpty( $attachment_id ); + $temp_dir = get_temp_dir(); + + $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); + $expected = array( - 'sizes' => array( + 'sizes' => array( 'full' => array( 'file' => 'wordpress-gsoc-flyer-pdf.jpg', 'width' => 1088, 'height' => 1408, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf.jpg' ), ), 'medium' => array( 'file' => 'wordpress-gsoc-flyer-pdf-300x300.jpg', 'width' => 300, 'height' => 300, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-300x300.jpg' ), ), 'large' => array( 'file' => 'wordpress-gsoc-flyer-pdf-791x1024.jpg', 'width' => 791, 'height' => 1024, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-791x1024.jpg' ), ), 'thumbnail' => array( 'file' => 'wordpress-gsoc-flyer-pdf-116x150.jpg', 'width' => 116, 'height' => 150, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-116x150.jpg' ), ), ), + 'filesize' => wp_filesize( $test_file ), ); - $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); $this->assertSame( $expected, $metadata ); unlink( $test_file ); foreach ( $metadata['sizes'] as $size ) { - unlink( get_temp_dir() . $size['file'] ); + unlink( $temp_dir . $size['file'] ); } } @@ -617,14 +632,21 @@ class Tests_Image_Functions extends WP_UnitTestCase { add_image_size( 'test-size', 100, 100 ); add_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10, 2 ); + $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); + + $temp_dir = get_temp_dir(); + $expected = array( 'file' => 'wordpress-gsoc-flyer-pdf-77x100.jpg', 'width' => 77, 'height' => 100, 'mime-type' => 'image/jpeg', + 'filesize' => wp_filesize( $temp_dir . 'wordpress-gsoc-flyer-pdf-77x100.jpg' ), ); - $metadata = wp_generate_attachment_metadata( $attachment_id, $test_file ); + // Different environments produce slightly different filesize results. + $this->assertSame( $metadata['sizes']['test-size'], $expected ); + $this->assertArrayHasKey( 'test-size', $metadata['sizes'], 'The `test-size` was not added to the metadata.' ); $this->assertSame( $expected, $metadata['sizes']['test-size'] ); @@ -632,7 +654,6 @@ class Tests_Image_Functions extends WP_UnitTestCase { remove_filter( 'fallback_intermediate_image_sizes', array( $this, 'filter_fallback_intermediate_image_sizes' ), 10 ); unlink( $test_file ); - $temp_dir = get_temp_dir(); foreach ( $metadata['sizes'] as $size ) { unlink( $temp_dir . $size['file'] ); }