From e0b98ce8483231e6e5946cd2a9b372922958a238 Mon Sep 17 00:00:00 2001 From: ArkaPrabhaChowdhury Date: Wed, 29 Jul 2026 14:15:50 +0530 Subject: [PATCH 1/2] Media: Support cropping remote images without URL fopen --- src/wp-admin/includes/image.php | 23 ++++++++++++++++++++++- tests/phpunit/tests/image/functions.php | 25 ++++++++++++++++++++----- 2 files changed, 42 insertions(+), 6 deletions(-) diff --git a/src/wp-admin/includes/image.php b/src/wp-admin/includes/image.php index 935c613d561e9..e518dfe39ebb2 100644 --- a/src/wp-admin/includes/image.php +++ b/src/wp-admin/includes/image.php @@ -24,7 +24,10 @@ */ function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $src_abs = false, $dst_file = false ) { $src_file = $src; - if ( is_numeric( $src ) ) { // Handle int as attachment ID. + $tmp_file = false; + + // Handle int as attachment ID. + if ( is_numeric( $src ) ) { $src_file = get_attached_file( $src ); if ( ! file_exists( $src_file ) ) { @@ -38,7 +41,25 @@ function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $s } } + if ( wp_http_validate_url( $src ) ) { + if ( ! function_exists( 'download_url' ) ) { + require_once ABSPATH . 'wp-admin/includes/file.php'; + } + + $tmp_file = download_url( $src ); + if ( is_wp_error( $tmp_file ) ) { + return $tmp_file; + } + + $src = $tmp_file; + } + $editor = wp_get_image_editor( $src ); + + if ( $tmp_file ) { + wp_delete_file( $tmp_file ); + } + if ( is_wp_error( $editor ) ) { return $editor; } diff --git a/tests/phpunit/tests/image/functions.php b/tests/phpunit/tests/image/functions.php index 94cc0111f0d4c..c006fd1eb3f94 100644 --- a/tests/phpunit/tests/image/functions.php +++ b/tests/phpunit/tests/image/functions.php @@ -636,13 +636,30 @@ public function test_wp_crop_image_with_file() { } /** + * @ticket 42064 + * * @covers ::wp_crop_image * @requires function imagejpeg - * @requires extension openssl */ public function test_wp_crop_image_with_url() { + $mock_image_download = static function ( $response, $args ) { + copy( DIR_TESTDATA . '/images/canola.jpg', $args['filename'] ); + + return array( + 'response' => array( + 'code' => 200, + 'message' => 'OK', + ), + 'headers' => array(), + 'cookies' => array(), + 'body' => '', + ); + }; + + add_filter( 'pre_http_request', $mock_image_download, 10, 2 ); + $file = wp_crop_image( - 'https://s.w.org/screenshots/3.9/dashboard.png', + 'https://example.org/canola.jpg', 0, 0, 100, @@ -653,9 +670,7 @@ public function test_wp_crop_image_with_url() { DIR_TESTDATA . '/images/' . __FUNCTION__ . '.png' ); - if ( is_wp_error( $file ) && $file->get_error_code() === 'invalid_image' ) { - $this->markTestSkipped( 'Tests_Image_Functions::test_wp_crop_image_url() cannot access remote image.' ); - } + remove_filter( 'pre_http_request', $mock_image_download, 10 ); $this->assertNotWPError( $file, 'Cropping the image resulted in a WP_Error.' ); $this->assertFileExists( $file, "The file $file does not exist." ); From 492f2d974e7f90031dc20175d26e1d68cd10978b Mon Sep 17 00:00:00 2001 From: ArkaPrabhaChowdhury Date: Wed, 29 Jul 2026 14:25:07 +0530 Subject: [PATCH 2/2] Tests: Harden remote image crop coverage --- src/wp-admin/includes/image.php | 4 +++ tests/phpunit/tests/image/functions.php | 41 +++++++++++++++---------- 2 files changed, 28 insertions(+), 17 deletions(-) diff --git a/src/wp-admin/includes/image.php b/src/wp-admin/includes/image.php index e518dfe39ebb2..b994d4cd13982 100644 --- a/src/wp-admin/includes/image.php +++ b/src/wp-admin/includes/image.php @@ -51,6 +51,10 @@ function wp_crop_image( $src, $src_x, $src_y, $src_w, $src_h, $dst_w, $dst_h, $s return $tmp_file; } + if ( wp_http_validate_url( $src_file ) ) { + $src_file = $tmp_file; + } + $src = $tmp_file; } diff --git a/tests/phpunit/tests/image/functions.php b/tests/phpunit/tests/image/functions.php index c006fd1eb3f94..b21ad700fa11b 100644 --- a/tests/phpunit/tests/image/functions.php +++ b/tests/phpunit/tests/image/functions.php @@ -642,8 +642,15 @@ public function test_wp_crop_image_with_file() { * @requires function imagejpeg */ public function test_wp_crop_image_with_url() { - $mock_image_download = static function ( $response, $args ) { - copy( DIR_TESTDATA . '/images/canola.jpg', $args['filename'] ); + $url = 'https://example.org/canola.jpg'; + $mock_image_download = static function ( $response, $args, $requested_url ) use ( $url ) { + if ( $url !== $requested_url ) { + return $response; + } + + if ( empty( $args['filename'] ) || ! copy( DIR_TESTDATA . '/images/canola.jpg', $args['filename'] ) ) { + return new WP_Error( 'copy_failed', 'Could not copy the image fixture.' ); + } return array( 'response' => array( @@ -656,21 +663,21 @@ public function test_wp_crop_image_with_url() { ); }; - add_filter( 'pre_http_request', $mock_image_download, 10, 2 ); - - $file = wp_crop_image( - 'https://example.org/canola.jpg', - 0, - 0, - 100, - 100, - 100, - 100, - false, - DIR_TESTDATA . '/images/' . __FUNCTION__ . '.png' - ); - - remove_filter( 'pre_http_request', $mock_image_download, 10 ); + add_filter( 'pre_http_request', $mock_image_download, 10, 3 ); + + try { + $file = wp_crop_image( + $url, + 0, + 0, + 100, + 100, + 100, + 100 + ); + } finally { + remove_filter( 'pre_http_request', $mock_image_download, 10 ); + } $this->assertNotWPError( $file, 'Cropping the image resulted in a WP_Error.' ); $this->assertFileExists( $file, "The file $file does not exist." );