Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid overwriting existing WebP files when creating WebP images #359

Merged
merged 5 commits into from Jun 16, 2022
Merged

Avoid overwriting existing WebP files when creating WebP images #359

merged 5 commits into from Jun 16, 2022

Conversation

mukeshpanchal27
Copy link
Member

@mukeshpanchal27 mukeshpanchal27 commented Jun 10, 2022

Summary

This PR skips the creation of duplicate WebP images if anyone uses an image file with the same name with an extension of jpg, jpe, or jpeg.

Please check more detail about the issue and the options for the solution here

As @felixarntz suggested we should go with 1st approach.

If you want to generate a WebP image for .png images then please add the below code snippet in your current themes functions.php

add_filter('webp_uploads_upload_image_mime_transforms', function () {

    return [
        'image/jpeg' =>  [ 'image/jpeg', 'image/webp' ],
        'image/png' =>  [ 'image/png', 'image/webp' ],
        'image/webp' =>  [ 'image/webp', 'image/jpeg' ],
    ];
});

Fixes #358

Images for testing

If you want to test the different images then please download the zip in which I added all image formats( jpg, jpe, jpeg and png ) - image.zip

Checklist

  • PR has either [Focus] or Infrastructure label.
  • PR has a [Type] label.
  • PR has a milestone or the no milestone label.

@mukeshpanchal27 mukeshpanchal27 added [Focus] Images Issues related to the Images focus area [Plugin] Modern Image Formats Issues for the Modern Image Formats plugin (formerly WebP Uploads) [Type] Bug An existing feature is broken labels Jun 10, 2022
@bethanylang bethanylang added this to the 1.2.0 milestone Jun 10, 2022
@bethanylang bethanylang added this to Backlog in [Focus] Images via automation Jun 10, 2022
@bethanylang bethanylang moved this from Backlog to Review in [Focus] Images Jun 10, 2022
@jjgrainger jjgrainger added the no milestone PRs that do not have a defined milestone for release label Jun 10, 2022
Copy link
Contributor

@jjgrainger jjgrainger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks goods

Copy link
Member

@mitogh mitogh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one question, besides that things look good on my end.

I would encourage to add a test case replicating the current issue BTW.


// Skip creation of duplicate WebP image if a image file has the same name with an extension of jpe, jpg, or jpeg.
if ( file_exists( $destination ) ) {
continue;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to try to create a different destination name instead? Like appending a number or a UUID instead, in the same way, WordPress handles it when the file already exists?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mitogh Yes, this is the eventual plan, but for now adding this stop-gap to not overwrite/confuse images should be sufficient.

Let's work on a proper solution where both images can be kept in a separate PR.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mukeshpanchal27 This PR only fixes one half of the bug - for when the full size is generated, but not for when the other sizes are generated. See my comment below, I think this should rather be fixed at the root of the problem, in webp_uploads_generate_additional_image_source(). Otherwise, it's easy to miss certain situations, one of them already missing here.

Could you then also add a test for the new condition in webp_uploads_generate_additional_image_source(), to cover the new clause that an existing image file would cause a WP_Error?

Comment on lines 95 to 97
if ( file_exists( $destination ) ) {
continue;
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding this check here, I think a cleaner solution would be to handle it within the webp_uploads_generate_additional_image_source() function which is the function where the file is actually generated. That would fix the problem at its root and it would ensure you don't have to add a condition around it everywhere you call that function.

The current implementation here is actually missing the scenario when a new image size is generated where that function is also called - right now there would still be a chance for the image to be overwritten. By adding the condition to webp_uploads_generate_additional_image_source() and returning a WP_Error in that case, we only need to make that change there and it will work everywhere without any further changes.

@mukeshpanchal27
Copy link
Member Author

If we consider checking the file_exists in function webp_uploads_generate_additional_image_source() then we can check it after the editor generate_filename function because we will get all additional thumbnail size URLs after this code snippet.

if ( null === $destination_file_name ) {
	$extension             = explode( '|', $allowed_mimes[ $mime ] );
	$destination_file_name = $editor->generate_filename( null, null, $extension[0] );
}

As I troubleshoot the issue, we have two options here.

  1. We can check file_exists after the code snippet so we get full and other thumbnail images.

     if ( null === $destination_file_name ) {
     	$extension             = explode( '|', $allowed_mimes[ $mime ] );
     	$destination_file_name = $editor->generate_filename( null, null, $extension[0] );
     }
    
     if ( file_exists( $destination_file_name ) ) {
     	return new WP_Error( 'webp_image_file_exist', __( 'The webP image already exists.', 'performance-lab' ) );
     }
    

In this approach there may be some unnecessary checking happens for the duplicate image in function webp_uploads_generate_additional_image_source()

  1. We pass $destination_file_name in function webp_uploads_generate_image_size() for consistancy for thumbnail images so we can check file_exists at top in function webp_uploads_generate_additional_image_source()

     $filename    = pathinfo( $properties['file'], PATHINFO_FILENAME );
     $extension   = explode( '|', $allowed_mimes[ $targeted_mime ] );
     $destination = trailingslashit( $original_directory ) . "{$filename}.{$extension[0]}";
     $source = webp_uploads_generate_image_size( $attachment_id, $size_name, $mime, $destination );
    

If we consider this option then we don't need to call the generate_filename function to get the image name.

if ( null === $destination_file_name ) {
	$extension             = explode( '|', $allowed_mimes[ $mime ] );
	$destination_file_name = $editor->generate_filename( null, null, $extension[0] );
}

In this approach we have to update unit test, we use webp_uploads_generate_image_size() function in unit test.

If I miss anything then please let me know.

@felixarntz
Copy link
Member

@mukeshpanchal27 I think we should go with your approach 1, always run the file_exists check right after we have the $destination_file_name set for sure. That way we only need to have the check in one place.

In this approach there may be some unnecessary checking happens for the duplicate image in function webp_uploads_generate_additional_image_source()

Can you clarify what you mean? I think there would only be a single file_exists check in each different situation, only in webp_uploads_generate_additional_image_source().

Changes are reverted and working on other approach.
// Skip creation of duplicate WebP image if an image file already exists in the directory.
@mukeshpanchal27
Copy link
Member Author

Can you clarify what you mean?

For duplicate image, webp_uploads_generate_additional_image_source() function check this https://github.com/mukeshpanchal27/performance/blob/fix/358-skip-duplicate-webp-image/modules/images/webp-uploads/helper.php#L85-L143 code that may be not require for already exist images.

PR updated with approach 1 and requested the review.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mukeshpanchal27

For duplicate image, webp_uploads_generate_additional_image_source() function check this https://github.com/mukeshpanchal27/performance/blob/fix/358-skip-duplicate-webp-image/modules/images/webp-uploads/helper.php#L85-L143 code that may be not require for already exist images.

Right, I agree it's a bit wasteful that we have to run all that logic before the file_exists check, but unless $destination_file_name is already provided, some of that logic is critical to run before since it affects the file name (for example the resize() call).

I think the current implementation is good for now since it solves the problem. In WordPress core this will eventually be implemented differently anyway. I left one more tiny comment, but already approving this since it's good to go.

modules/images/webp-uploads/helper.php Outdated Show resolved Hide resolved
@felixarntz felixarntz merged commit e63deaa into WordPress:trunk Jun 16, 2022
[Focus] Images automation moved this from Review to Done Jun 16, 2022
@felixarntz felixarntz changed the title Skip creation of duplicate WebP images Avoid overwriting existing WebP files when creating WebP images Jun 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Focus] Images Issues related to the Images focus area no milestone PRs that do not have a defined milestone for release [Plugin] Modern Image Formats Issues for the Modern Image Formats plugin (formerly WebP Uploads) [Type] Bug An existing feature is broken
Projects
Development

Successfully merging this pull request may close these issues.

WebP file overwritten if filename has the same name with extension of jpeg and jpg
6 participants