diff --git a/src/wp-includes/rest-api/class-wp-rest-server.php b/src/wp-includes/rest-api/class-wp-rest-server.php index af73b80103546..5b537fa996005 100644 --- a/src/wp-includes/rest-api/class-wp-rest-server.php +++ b/src/wp-includes/rest-api/class-wp-rest-server.php @@ -1378,6 +1378,20 @@ public function get_index( $request ) { /** This filter is documented in wp-admin/includes/image.php */ $available['image_size_threshold'] = (int) apply_filters( 'big_image_size_threshold', 2560, array( 0, 0 ), '', 0 ); + + /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ + $available['image_strip_meta'] = (bool) apply_filters( 'image_strip_meta', true ); + + /* + * On the server, this filter receives the decoded image's actual bit depth. + * The client path never decodes the image on the server, so the filter is + * applied with 16 (the maximum depth the client encoder can produce) as + * both the value and the current depth. The client caps its output bit + * depth at the filtered value, so a plugin lowering it (e.g. to 8) takes + * effect on client-generated images too. + */ + /** This filter is documented in wp-includes/class-wp-image-editor-imagick.php */ + $available['image_max_bit_depth'] = (int) apply_filters( 'image_max_bit_depth', 16, 16 ); } $response = new WP_REST_Response( $available ); diff --git a/tests/phpunit/tests/rest-api/rest-server.php b/tests/phpunit/tests/rest-api/rest-server.php index f61d2fc745d99..b8e8cc6f5adcb 100644 --- a/tests/phpunit/tests/rest-api/rest-server.php +++ b/tests/phpunit/tests/rest-api/rest-server.php @@ -1207,6 +1207,76 @@ public function test_get_index() { $this->assertArrayHasKey( 'site_icon_url', $data ); } + /** + * @ticket 64804 + * + * @covers WP_REST_Server::get_index + */ + public function test_get_index_should_include_media_processing_settings(): void { + $user_id = self::factory()->user->create( array( 'role' => 'administrator' ) ); + $this->assertIsInt( $user_id ); + wp_set_current_user( $user_id ); + add_filter( 'wp_client_side_media_processing_enabled', '__return_true' ); + + $server = new WP_REST_Server(); + $request = new WP_REST_Request( 'GET', '/' ); + $index = $server->dispatch( $request ); + $data = $index->get_data(); + $this->assertIsArray( $data ); + + $this->assertArrayHasKey( 'image_sizes', $data ); + $this->assertArrayHasKey( 'image_size_threshold', $data ); + $this->assertArrayHasKey( 'image_strip_meta', $data ); + $this->assertTrue( $data['image_strip_meta'] ); + $this->assertArrayHasKey( 'image_max_bit_depth', $data ); + $this->assertSame( 16, $data['image_max_bit_depth'] ); + } + + /** + * @ticket 64804 + * + * @covers WP_REST_Server::get_index + */ + public function test_get_index_should_not_include_media_processing_settings_without_caps(): void { + add_filter( 'wp_client_side_media_processing_enabled', '__return_true' ); + + $server = new WP_REST_Server(); + $request = new WP_REST_Request( 'GET', '/' ); + $index = $server->dispatch( $request ); + $data = $index->get_data(); + $this->assertIsArray( $data ); + + $this->assertArrayNotHasKey( 'image_sizes', $data ); + $this->assertArrayNotHasKey( 'image_size_threshold', $data ); + $this->assertArrayNotHasKey( 'image_strip_meta', $data ); + $this->assertArrayNotHasKey( 'image_max_bit_depth', $data ); + } + + /** + * @ticket 64804 + * + * @covers WP_REST_Server::get_index + */ + public function test_get_index_should_honor_media_processing_filters(): void { + $user_id = self::factory()->user->create( array( 'role' => 'administrator' ) ); + $this->assertIsInt( $user_id ); + wp_set_current_user( $user_id ); + add_filter( 'wp_client_side_media_processing_enabled', '__return_true' ); + add_filter( 'image_strip_meta', '__return_false' ); + add_filter( + 'image_max_bit_depth', + static fn ( int $max_depth ) => min( 8, $max_depth ) + ); + + $server = new WP_REST_Server(); + $request = new WP_REST_Request( 'GET', '/' ); + $index = $server->dispatch( $request ); + $data = $index->get_data(); + + $this->assertFalse( $data['image_strip_meta'] ); + $this->assertSame( 8, $data['image_max_bit_depth'] ); + } + /** * @ticket 57902 * diff --git a/tests/qunit/fixtures/wp-api-generated.js b/tests/qunit/fixtures/wp-api-generated.js index 14a26f8301e3b..2591b830a1d5e 100644 --- a/tests/qunit/fixtures/wp-api-generated.js +++ b/tests/qunit/fixtures/wp-api-generated.js @@ -12919,6 +12919,8 @@ mockedApiResponse.Schema = { } }, "image_size_threshold": 2560, + "image_strip_meta": true, + "image_max_bit_depth": 16, "site_logo": 0, "site_icon": 0, "site_icon_url": ""