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 ); + ?>
@@ -272,7 +273,7 @@ function wp_image_editor( $post_id, $msg = false ) {
@@ -307,32 +308,12 @@ function wp_image_editor( $post_id, $msg = false ) { - + - $size ) { - if ( array_key_exists( $size, $meta['sizes'] ) ) { - if ( 'thumbnail' === $size ) { - continue; - } - ?> - - - - -
@@ -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. *