diff --git a/src/js/_enqueues/lib/image-edit.js b/src/js/_enqueues/lib/image-edit.js
index 167ee0f17b..8f44e930be 100644
--- a/src/js/_enqueues/lib/image-edit.js
+++ b/src/js/_enqueues/lib/image-edit.js
@@ -358,10 +358,16 @@
* @param {number} postid The post ID.
*
* @return {string} The value from the imagedit-save-target input field when available,
- * or 'full' when not available.
+ * 'full' when not selected, or 'all' if it doesn't exist.
*/
- getTarget : function(postid) {
- return $('input[name="imgedit-target-' + postid + '"]:checked', '#imgedit-save-target-' + postid).val() || 'full';
+ getTarget : function( postid ) {
+ var element = $( '#imgedit-save-target-' + postid );
+
+ if ( element.length ) {
+ return element.find( 'input[name="imgedit-target-' + postid + '"]:checked' ).val() || 'full';
+ }
+
+ return 'all';
},
/**
diff --git a/src/wp-admin/includes/image-edit.php b/src/wp-admin/includes/image-edit.php
index 3ecb38ceb8..9af0f5b1e2 100644
--- a/src/wp-admin/includes/image-edit.php
+++ b/src/wp-admin/includes/image-edit.php
@@ -43,15 +43,16 @@ function wp_image_editor( $post_id, $msg = false ) {
$note = "
";
}
}
- $edit_custom_sizes = false;
+
/**
- * Filters whether custom sizes are available options for image editing.
+ * Shows the settings in the Image Editor that allow selecting to edit only the thumbnail of an image.
*
- * @since 6.0.0
+ * @since 6.3.0
*
- * @param bool|string[] $edit_custom_sizes True if custom sizes can be edited or array of custom size names.
+ * @param bool Whether to show the settings in the Image Editor. Default false.
*/
- $edit_custom_sizes = apply_filters( 'edit_custom_thumbnail_sizes', $edit_custom_sizes );
+ $edit_thumbnails_separately = (bool) apply_filters( 'image_edit_thumbnails_separately', false );
+
?>
@@ -918,6 +899,9 @@ function wp_save_image( $post_id ) {
$target = ! empty( $_REQUEST['target'] ) ? preg_replace( '/[^a-z0-9_-]+/i', '', $_REQUEST['target'] ) : '';
$scale = ! empty( $_REQUEST['do'] ) && 'scale' === $_REQUEST['do'];
+ /** This filter is documented in wp-admin/includes/image-edit.php */
+ $edit_thumbnails_separately = (bool) apply_filters( 'image_edit_thumbnails_separately', false );
+
if ( $scale ) {
$size = $img->get_size();
$sX = $size['width'];
@@ -977,7 +961,7 @@ function wp_save_image( $post_id ) {
if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE &&
isset( $backup_sizes['full-orig'] ) && $backup_sizes['full-orig']['file'] != $basename ) {
- if ( 'thumbnail' === $target ) {
+ if ( $edit_thumbnails_separately && 'thumbnail' === $target ) {
$new_path = "{$dirname}/{$filename}-temp.{$ext}";
} else {
$new_path = $path;
@@ -1027,29 +1011,21 @@ function wp_save_image( $post_id ) {
$meta['width'] = $size['width'];
$meta['height'] = $size['height'];
- if ( $success ) {
+ if ( $success && ( 'nothumb' === $target || 'all' === $target ) ) {
$sizes = get_intermediate_image_sizes();
- if ( 'nothumb' === $target || 'all' === $target ) {
- if ( 'nothumb' === $target ) {
- $sizes = array_diff( $sizes, array( 'thumbnail' ) );
- }
- } elseif ( 'thumbnail' !== $target ) {
- $sizes = array_diff( $sizes, array( $target ) );
+
+ if ( $edit_thumbnails_separately && 'nothumb' === $target ) {
+ $sizes = array_diff( $sizes, array( 'thumbnail' ) );
}
}
$return->fw = $meta['width'];
$return->fh = $meta['height'];
- } elseif ( 'thumbnail' === $target ) {
+ } elseif ( $edit_thumbnails_separately && 'thumbnail' === $target ) {
$sizes = array( 'thumbnail' );
$success = true;
$delete = true;
$nocrop = true;
- } else {
- $sizes = array( $target );
- $success = true;
- $delete = true;
- $nocrop = $_wp_additional_image_sizes[ $size ]['crop'];
}
/*
diff --git a/tests/phpunit/tests/ajax/wpAjaxImageEditor.php b/tests/phpunit/tests/ajax/wpAjaxImageEditor.php
index 5fd7fffa3d..a06afa1f5c 100644
--- a/tests/phpunit/tests/ajax/wpAjaxImageEditor.php
+++ b/tests/phpunit/tests/ajax/wpAjaxImageEditor.php
@@ -28,39 +28,6 @@ class Tests_Ajax_wpAjaxImageEditor extends WP_Ajax_UnitTestCase {
parent::tear_down();
}
- /**
- * @ticket 22985
- * @requires function imagejpeg
- *
- * @covers ::wp_insert_attachment
- * @covers ::wp_save_image
- */
- public function testCropImageThumbnail() {
- require_once ABSPATH . 'wp-admin/includes/image-edit.php';
-
- $filename = DIR_TESTDATA . '/images/canola.jpg';
- $contents = file_get_contents( $filename );
-
- $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
- $id = $this->_make_attachment( $upload );
-
- $_REQUEST['action'] = 'image-editor';
- $_REQUEST['context'] = 'edit-attachment';
- $_REQUEST['postid'] = $id;
- $_REQUEST['target'] = 'thumbnail';
- $_REQUEST['do'] = 'save';
- $_REQUEST['history'] = '[{"c":{"x":5,"y":8,"w":289,"h":322}}]';
-
- $media_meta = wp_get_attachment_metadata( $id );
- $this->assertArrayHasKey( 'sizes', $media_meta, 'attachment should have size data' );
- $this->assertArrayHasKey( 'medium', $media_meta['sizes'], 'attachment should have data for medium size' );
- $ret = wp_save_image( $id );
-
- $media_meta = wp_get_attachment_metadata( $id );
- $this->assertArrayHasKey( 'sizes', $media_meta, 'cropped attachment should have size data' );
- $this->assertArrayHasKey( 'medium', $media_meta['sizes'], 'cropped attachment should have data for medium size' );
- }
-
/**
* @ticket 26381
* @requires function imagejpeg
diff --git a/tests/phpunit/tests/image/functions.php b/tests/phpunit/tests/image/functions.php
index 82988c5f6b..356b2dceac 100644
--- a/tests/phpunit/tests/image/functions.php
+++ b/tests/phpunit/tests/image/functions.php
@@ -350,6 +350,91 @@ class Tests_Image_Functions extends WP_UnitTestCase {
$this->assertTrue( $ret, 'Image failed to save.' );
}
+ /**
+ * Tests that `wp_image_editor()` applies 'image_edit_thumbnails_separately' filters.
+ *
+ * @ticket 53161
+ *
+ * @covers ::wp_image_editor
+ */
+ public function test_wp_image_editor_should_apply_image_edit_thumbnails_separately_filters() {
+ require_once ABSPATH . 'wp-admin/includes/image-edit.php';
+
+ $filename = DIR_TESTDATA . '/images/canola.jpg';
+ $contents = file_get_contents( $filename );
+ $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
+ $id = $this->_make_attachment( $upload );
+
+ $filter = new MockAction();
+ add_filter( 'image_edit_thumbnails_separately', array( &$filter, 'filter' ) );
+
+ ob_start();
+ wp_image_editor( $id );
+ ob_end_clean();
+
+ $this->assertSame( 1, $filter->get_call_count() );
+ }
+
+ /**
+ * Tests that `wp_image_editor()` conditionally outputs markup for editing thumbnails separately
+ * based on the result of applying 'image_edit_thumbnails_separately' filters.
+ *
+ * @ticket 53161
+ *
+ * @covers ::wp_image_editor
+ *
+ * @dataProvider data_wp_image_editor_should_respect_image_edit_thumbnails_separately_filters
+ *
+ * @param string $callback The name of the callback for the 'image_edit_thumbnails_separately' hook.
+ * @param bool $expected Whether the markup should be output.
+ */
+ public function test_wp_image_editor_should_respect_image_edit_thumbnails_separately_filters( $callback, $expected ) {
+ require_once ABSPATH . 'wp-admin/includes/image-edit.php';
+
+ $filename = DIR_TESTDATA . '/images/canola.jpg';
+ $contents = file_get_contents( $filename );
+ $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
+ $id = $this->_make_attachment( $upload );
+
+ add_filter( 'image_edit_thumbnails_separately', $callback );
+
+ ob_start();
+ wp_image_editor( $id );
+ $actual = ob_get_clean();
+
+ if ( $expected ) {
+ $this->assertStringContainsString(
+ 'imgedit-applyto',
+ $actual,
+ 'The markup should have been output.'
+ );
+ } else {
+ $this->assertStringNotContainsString(
+ 'imgedit-applyto',
+ $actual,
+ 'The markup should not have been output.'
+ );
+ }
+ }
+
+ /**
+ * Data provider.
+ *
+ * @return array[]
+ */
+ public function data_wp_image_editor_should_respect_image_edit_thumbnails_separately_filters() {
+ return array(
+ 'true' => array(
+ 'callback' => '__return_true',
+ 'expected' => true,
+ ),
+ 'false' => array(
+ 'callback' => '__return_false',
+ 'expected' => false,
+ ),
+ );
+ }
+
/**
* Tests that a passed mime type overrides the extension in the filename when saving an image.
*