summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--src/wp-admin/includes/media.php19
-rw-r--r--src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php30
-rw-r--r--tests/phpunit/tests/rest-api/rest-attachments-controller.php62
3 files changed, 104 insertions, 7 deletions
diff --git a/src/wp-admin/includes/media.php b/src/wp-admin/includes/media.php
index 73a2585f84..5c0b5d0b38 100644
--- a/src/wp-admin/includes/media.php
+++ b/src/wp-admin/includes/media.php
@@ -2194,14 +2194,19 @@ function media_upload_form( $errors = null ) {
$plupload_init['multi_selection'] = false;
}
- // Check if WebP images can be edited.
- if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
- $plupload_init['webp_upload_error'] = true;
- }
+ /** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php */
+ $prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, null );
+
+ if ( $prevent_unsupported_uploads ) {
+ // Check if WebP images can be edited.
+ if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ) ) {
+ $plupload_init['webp_upload_error'] = true;
+ }
- // Check if AVIF images can be edited.
- if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
- $plupload_init['avif_upload_error'] = true;
+ // Check if AVIF images can be edited.
+ if ( ! wp_image_editor_supports( array( 'mime_type' => 'image/avif' ) ) ) {
+ $plupload_init['avif_upload_error'] = true;
+ }
}
/**
diff --git a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
index 0c98a729e4..4c49a1f335 100644
--- a/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
+++ b/src/wp-includes/rest-api/endpoints/class-wp-rest-attachments-controller.php
@@ -134,6 +134,36 @@ class WP_REST_Attachments_Controller extends WP_REST_Posts_Controller {
array( 'status' => rest_authorization_required_code() )
);
}
+ $files = $request->get_file_params();
+
+ /**
+ * Filter whether the server should prevent uploads for image types it doesn't support. Default true.
+ *
+ * Developers can use this filter to enable uploads of certain image types. By default image types that are not
+ * supported by the server are prevented from being uploaded.
+ *
+ * @since 6.8.0
+ *
+ * @param bool $check_mime Whether to prevent uploads of unsupported image types.
+ * @param string|null $mime_type The mime type of the file being uploaded (if available).
+ */
+ $prevent_unsupported_uploads = apply_filters( 'wp_prevent_unsupported_mime_type_uploads', true, isset( $files['file']['type'] ) ? $files['file']['type'] : null );
+
+ // If the upload is an image, check if the server can handle the mime type.
+ if (
+ $prevent_unsupported_uploads &&
+ isset( $files['file']['type'] ) &&
+ str_starts_with( $files['file']['type'], 'image/' )
+ ) {
+ // Check if the image editor supports the type.
+ if ( ! wp_image_editor_supports( array( 'mime_type' => $files['file']['type'] ) ) ) {
+ return new WP_Error(
+ 'rest_upload_image_type_not_supported',
+ __( 'The web server cannot generate responsive image sizes for this image. Convert it to JPEG or PNG before uploading.' ),
+ array( 'status' => 400 )
+ );
+ }
+ }
return true;
}
diff --git a/tests/phpunit/tests/rest-api/rest-attachments-controller.php b/tests/phpunit/tests/rest-api/rest-attachments-controller.php
index 5794bf944d..1fdaaa26e1 100644
--- a/tests/phpunit/tests/rest-api/rest-attachments-controller.php
+++ b/tests/phpunit/tests/rest-api/rest-attachments-controller.php
@@ -28,6 +28,11 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
private static $test_file2;
/**
+ * @var string The path to the AVIF test image.
+ */
+ private static $test_avif_file;
+
+ /**
* @var array The recorded posts query clauses.
*/
protected $posts_clauses;
@@ -72,6 +77,9 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
if ( file_exists( self::$test_file2 ) ) {
unlink( self::$test_file2 );
}
+ if ( file_exists( self::$test_avif_file ) ) {
+ unlink( self::$test_avif_file );
+ }
self::delete_user( self::$editor_id );
self::delete_user( self::$author_id );
@@ -101,6 +109,12 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
copy( $orig_file2, self::$test_file2 );
}
+ $orig_avif_file = DIR_TESTDATA . '/images/avif-lossy.avif';
+ self::$test_avif_file = get_temp_dir() . 'avif-lossy.avif';
+ if ( ! file_exists( self::$test_avif_file ) ) {
+ copy( $orig_avif_file, self::$test_avif_file );
+ }
+
add_filter( 'rest_pre_dispatch', array( $this, 'wpSetUpBeforeRequest' ), 10, 3 );
add_filter( 'posts_clauses', array( $this, 'save_posts_clauses' ), 10, 2 );
}
@@ -2541,4 +2555,52 @@ class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Control
}
);
}
+
+ /**
+ * Test that uploading unsupported image types throws a `rest_upload_image_type_not_supported` error.
+ *
+ * @ticket 61167
+ */
+ public function test_upload_unsupported_image_type() {
+
+ // Only run this test when the editor doesn't support AVIF.
+ if ( wp_image_editor_supports( array( 'AVIF' ) ) ) {
+ $this->markTestSkipped( 'The image editor suppports AVIF.' );
+ }
+
+ $request = new WP_REST_Request( 'POST', '/wp/v2/media' );
+
+ wp_set_current_user( self::$author_id );
+ $request->set_header( 'Content-Type', 'image/avif' );
+ $request->set_header( 'Content-Disposition', 'attachment; filename=avif-lossy.avif' );
+ $request->set_body( file_get_contents( self::$test_avif_file ) );
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertErrorResponse( 'rest_upload_image_type_not_supported', $response, 400 );
+ }
+
+ /**
+ * Test that the `wp_prevent_unsupported_image_uploads` filter enables uploading of unsupported image types.
+ *
+ * @ticket 61167
+ */
+ public function test_upload_unsupported_image_type_with_filter() {
+
+ // Only run this test when the editor doesn't support AVIF.
+ if ( wp_image_editor_supports( array( 'AVIF' ) ) ) {
+ $this->markTestSkipped( 'The image editor suppports AVIF.' );
+ }
+
+ add_filter( 'wp_prevent_unsupported_image_uploads', '__return_false' );
+
+ $request = new WP_REST_Request( 'POST', '/wp/v2/media' );
+
+ wp_set_current_user( self::$author_id );
+ $request->set_header( 'Content-Type', 'image/avif' );
+ $request->set_header( 'Content-Disposition', 'attachment; filename=avif-lossy.avif' );
+ $request->set_body( file_get_contents( self::$test_avif_file ) );
+ $response = rest_get_server()->dispatch( $request );
+
+ $this->assertSame( 201, $response->get_status() );
+ }
}