Skip to content

Commit

Permalink
Merge pull request #301 from WordPress/feature/update-secondary-image…
Browse files Browse the repository at this point in the history
…-onedit-with-targets

Only update the specified target images when an image is edited.
  • Loading branch information
felixarntz authored May 12, 2022
2 parents af8ea49 + 3643b94 commit d39c6aa
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 27 deletions.
106 changes: 86 additions & 20 deletions modules/images/webp-uploads/image-edit.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,41 @@
*/
function webp_uploads_update_sources( $metadata, $valid_mime_transforms, $main_images, $subsized_images ) {
foreach ( $valid_mime_transforms as $targeted_mime ) {
// Make sure the path and file exists as those values are being accessed.
if ( ! isset( $main_images[ $targeted_mime ]['path'], $main_images[ $targeted_mime ]['file'] ) || ! file_exists( $main_images[ $targeted_mime ]['path'] ) ) {
continue;
// Make sure the path and file exists as those values are required.
$image_directory = null;
if ( isset( $main_images[ $targeted_mime ]['path'], $main_images[ $targeted_mime ]['file'] ) && file_exists( $main_images[ $targeted_mime ]['path'] ) ) {
// Add sources to original image metadata.
$metadata['sources'][ $targeted_mime ] = array(
'file' => $main_images[ $targeted_mime ]['file'],
'filesize' => filesize( $main_images[ $targeted_mime ]['path'] ),
);
$image_directory = pathinfo( $main_images[ $targeted_mime ]['path'], PATHINFO_DIRNAME );
}

$image_directory = pathinfo( $main_images[ $targeted_mime ]['path'], PATHINFO_DIRNAME );
/**
* If no original image was provided the image_directory can't be determined, in that scenario try to
* find it from the `file` property.
*
* @see get_attached_file()
*/
if (
null === $image_directory
&& isset( $metadata['file'] )
&& 0 !== strpos( $metadata['file'], '/' )
&& ':\\' !== substr( $metadata['file'], 1, 2 )
) {
$uploads = wp_get_upload_dir();
if ( false === $uploads['error'] && isset( $uploads['basedir'] ) ) {
$file = path_join( $uploads['basedir'], $metadata['file'] );
if ( file_exists( $file ) ) {
$image_directory = pathinfo( $file, PATHINFO_DIRNAME );
}
}
}

// Add sources to original image metadata.
$metadata['sources'][ $targeted_mime ] = array(
'file' => $main_images[ $targeted_mime ]['file'],
'filesize' => filesize( $main_images[ $targeted_mime ]['path'] ),
);
if ( null === $image_directory ) {
continue;
}

foreach ( $metadata['sizes'] as $size_name => $size_details ) {
if ( empty( $subsized_images[ $targeted_mime ][ $size_name ]['file'] ) ) {
Expand All @@ -39,7 +62,6 @@ function webp_uploads_update_sources( $metadata, $valid_mime_transforms, $main_i

// Add sources to resized image metadata.
$subsize_path = path_join( $image_directory, $subsized_images[ $targeted_mime ][ $size_name ]['file'] );

if ( ! file_exists( $subsize_path ) ) {
continue;
}
Expand Down Expand Up @@ -91,15 +113,21 @@ function ( $metadata, $post_meta_id ) use ( $post_id, $file_path, $mime_type, $e
return $metadata;
}
$callback_executed = true;

// No sizes to be created.
if ( empty( $metadata['sizes'] ) ) {
return $metadata;
}

$old_metadata = wp_get_attachment_metadata( $post_id );
$resize_sizes = array();
$target = isset( $_REQUEST['target'] ) ? $_REQUEST['target'] : 'all';

foreach ( $old_metadata['sizes'] as $size_name => $size_details ) {
// If the target is 'nothumb', skip generating the 'thumbnail' size.
if ( 'nothumb' === $target && 'thumbnail' === $size_name ) {
continue;
}

if ( isset( $metadata['sizes'][ $size_name ] ) && ! empty( $metadata['sizes'][ $size_name ] ) &&
$metadata['sizes'][ $size_name ]['file'] !== $old_metadata['sizes'][ $size_name ]['file'] ) {
$resize_sizes[ $size_name ] = $metadata['sizes'][ $size_name ];
Expand All @@ -111,8 +139,18 @@ function ( $metadata, $post_meta_id ) use ( $post_id, $file_path, $mime_type, $e
$filename = pathinfo( $file_path, PATHINFO_FILENAME );
$main_images = array();
$subsized_images = array();

foreach ( $mime_transforms as $targeted_mime ) {
if ( $targeted_mime === $mime_type ) {
// If the target is `thumbnail` make sure it is the only selected size.
if ( 'thumbnail' === $target ) {
if ( isset( $metadata['sizes']['thumbnail'] ) ) {
$subsized_images[ $targeted_mime ] = array( 'thumbnail' => $metadata['sizes']['thumbnail'] );
}
// When the targeted thumbnail is selected no additional size and subsize is set.
continue;
}

$main_images[ $targeted_mime ] = array(
'path' => $file_path,
'file' => pathinfo( $file_path, PATHINFO_BASENAME ),
Expand All @@ -129,16 +167,44 @@ function ( $metadata, $post_meta_id ) use ( $post_id, $file_path, $mime_type, $e
continue;
}

$extension = explode( '|', $allowed_mimes[ $targeted_mime ] );
$destination = trailingslashit( $original_directory ) . "{$filename}.{$extension[0]}";
$result = $editor->save( $destination, $targeted_mime );

if ( is_wp_error( $result ) ) {
continue;
$extension = explode( '|', $allowed_mimes[ $targeted_mime ] );
$extension = $extension[0];

// If the target is `thumbnail` make sure only that size is generated.
if ( 'thumbnail' === $target ) {
if ( ! isset( $subsized_images[ $mime_type ]['thumbnail']['file'] ) ) {
continue;
}
$thumbnail_file = $subsized_images[ $mime_type ]['thumbnail']['file'];
$image_path = path_join( $original_directory, $thumbnail_file );
$editor = wp_get_image_editor( $image_path, array( 'mime_type' => $targeted_mime ) );

if ( is_wp_error( $editor ) ) {
continue;
}

$current_extension = pathinfo( $thumbnail_file, PATHINFO_EXTENSION );
// Create a file with then new extension out of the targeted file.
$target_file_name = preg_replace( "/\.$current_extension$/", ".$extension", $thumbnail_file );
$target_file_location = path_join( $original_directory, $target_file_name );
$result = $editor->save( $target_file_location, $targeted_mime );

if ( is_wp_error( $result ) ) {
continue;
}

$subsized_images[ $targeted_mime ] = array( 'thumbnail' => $result );
} else {
$destination = trailingslashit( $original_directory ) . "{$filename}.{$extension}";
$result = $editor->save( $destination, $targeted_mime );

if ( is_wp_error( $result ) ) {
continue;
}

$main_images[ $targeted_mime ] = $result;
$subsized_images[ $targeted_mime ] = $editor->multi_resize( $resize_sizes );
}

$main_images[ $targeted_mime ] = $result;
$subsized_images[ $targeted_mime ] = $editor->multi_resize( $resize_sizes );
}

return webp_uploads_update_sources( $metadata, $mime_transforms, $main_images, $subsized_images );
Expand Down
79 changes: 72 additions & 7 deletions tests/modules/images/webp-uploads/image-edit-tests.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* Tests for webp-uploads module image-edit.php.
*
* @package performance-lab
* @group webp-uploads
* @group image-edit
*/

use PerformanceLab\Tests\TestCase\ImagesTestCase;
Expand Down Expand Up @@ -138,31 +138,38 @@ public function it_should_prevent_to_backup_the_full_size_image_if_only_the_thum
$attachment_id = $this->factory->attachment->create_upload_object( TESTS_PLUGIN_DIR . '/tests/testdata/modules/images/leafs.jpg' );
$metadata = wp_get_attachment_metadata( $attachment_id );
$this->assertArrayHasKey( 'sources', $metadata );

$editor = new WP_Image_Edit( $attachment_id );
$editor->flip_vertical()->only_thumbnail()->save();
$this->assertTrue( $editor->success() );

$backup_sources = get_post_meta( $attachment_id, '_wp_attachment_backup_sources', true );
$this->assertEmpty( $backup_sources );

$backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
$this->assertIsArray( $backup_sizes );
$this->assertCount( 1, $backup_sizes );
$this->assertArrayHasKey( 'thumbnail-orig', $backup_sizes );
$this->assertArrayHasKey( 'sources', $backup_sizes['thumbnail-orig'] );

$metadata = wp_get_attachment_metadata( $attachment_id );

$this->assertImageHasSource( $attachment_id, 'image/jpeg' );
$this->assertImageHasSource( $attachment_id, 'image/webp' );

$this->assertImageHasSizeSource( $attachment_id, 'thumbnail', 'image/jpeg' );
$this->assertImageHasSizeSource( $attachment_id, 'thumbnail', 'image/webp' );

$this->assertFileNameIsNotEdited( $metadata['sources']['image/jpeg']['file'] );
$this->assertFileNameIsNotEdited( $metadata['sources']['image/webp']['file'] );

foreach ( $metadata['sizes'] as $size_name => $properties ) {
$this->assertImageHasSizeSource( $attachment_id, $size_name, 'image/jpeg' );
$this->assertImageHasSizeSource( $attachment_id, $size_name, 'image/webp' );

if ( 'thumbnail' === $size_name ) {
$this->assertSame( $properties['file'], $properties['sources']['image/jpeg']['file'] );
$this->assertSame( str_replace( '.jpg', '.webp', $properties['file'] ), $properties['sources']['image/webp']['file'] );
$this->assertFileNameIsEdited( $properties['sources']['image/jpeg']['file'] );
$this->assertFileNameIsEdited( $properties['sources']['image/webp']['file'] );
} else {
$this->assertFileNameIsNotEdited( $properties['sources']['image/jpeg']['file'] );
$this->assertFileNameIsNotEdited( $properties['sources']['image/webp']['file'] );
}
}
}

Expand Down Expand Up @@ -191,6 +198,10 @@ public function it_should_backup_the_image_when_all_images_except_the_thumbnail_
$this->assertImageHasSource( $attachment_id, 'image/jpeg' );
$this->assertImageHasSource( $attachment_id, 'image/webp' );

foreach ( $updated_metadata['sources'] as $properties ) {
$this->assertFileNameIsEdited( $properties['file'] );
}

$backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true );
$this->assertIsArray( $backup_sizes );
$this->assertArrayNotHasKey( 'thumbnail-orig', $backup_sizes, 'The thumbnail-orig was stored in the back up' );
Expand All @@ -203,6 +214,60 @@ public function it_should_backup_the_image_when_all_images_except_the_thumbnail_
}
}

/**
* Use the attached image when updating subsequent images not the original version
*
* @test
*/
public function it_should_use_the_attached_image_when_updating_subsequent_images_not_the_original_version() {
// The leafs image is 1080 pixels wide with this filter we ensure a -scaled version is created for this test.
add_filter(
'big_image_size_threshold',
function () {
// Due to the largest image size is 1024 and the image is 1080x720, 1050 is a good spot to create a scaled size for all images sizes.
return 1050;
}
);

$attachment_id = $this->factory->attachment->create_upload_object(
TESTS_PLUGIN_DIR . '/tests/testdata/modules/images/leafs.jpg'
);

$this->assertNotSame( wp_get_original_image_path( $attachment_id ), get_attached_file( $attachment_id ) );

$editor = new WP_Image_Edit( $attachment_id );
$editor->flip_right()->all_except_thumbnail()->save();

$this->assertTrue( $editor->success() );

$metadata = wp_get_attachment_metadata( $attachment_id );

$this->assertArrayHasKey( 'original_image', $metadata );
$this->assertArrayHasKey( 'sources', $metadata );
$this->assertImageHasSource( $attachment_id, 'image/jpeg' );
$this->assertImageHasSource( $attachment_id, 'image/webp' );

foreach ( $metadata['sources'] as $properties ) {
$this->assertFileNameIsEdited( $properties['file'] );
$this->assertStringContainsString( '-scaled-', $properties['file'] );
}

$this->assertArrayHasKey( 'sizes', $metadata );
foreach ( $metadata['sizes'] as $size_name => $properties ) {
$this->assertImageHasSizeSource( $attachment_id, $size_name, 'image/jpeg' );
$this->assertImageHasSizeSource( $attachment_id, $size_name, 'image/webp' );
foreach ( $properties['sources'] as $mime_type => $values ) {
if ( 'thumbnail' === $size_name ) {
$this->assertFileNameIsNotEdited( $values['file'], "'{$size_name}' is not valid." );
$this->assertStringNotContainsString( '-scaled-', $values['file'] );
} else {
$this->assertFileNameIsEdited( $values['file'], "'{$size_name}' is not valid." );
$this->assertStringContainsString( '-scaled-', $values['file'] );
}
}
}
}

/**
* Update source attributes when webp is edited.
*
Expand Down

0 comments on commit d39c6aa

Please sign in to comment.