-
Notifications
You must be signed in to change notification settings - Fork 138
Store the backup JPEG images in _wp_attachment_backup_sizes
#154
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
Store the backup JPEG images in _wp_attachment_backup_sizes
#154
Conversation
The property is added to every single image size available, each value inside the properties array is a reference to a different image mime type. If the image size was created as a JPEG version a WebP version would be created, if a WebP version exists a JPEG version would be created instead based on the details from ticket #142 This mechanism would allow extending the sources properties for more additional mime types. The value for each mime type is an associative array with `file` as the only property for now. And the plan is to include more meaningful properties such as `filesize` to a different mime type.
Make sure file follows the standard from `phpcs`
Prevent to use numeric indexes for each image size, instead use the correct image name.
In this case the `_wp_attached_file` needs to be used in order to gain any update to the image, instead of using the original image for any subsize.
Create an store the backup images for all the subsizes and supported image sizes.
Make sure the file is formatted properly.
| } | ||
|
|
||
| // TODO: Store the file size of the created image. | ||
| // $image['filesize'] = filesize( $image['path'] ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm in favor of storing this for all sizes, this is useful for performance analysis and potentially other things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great. for now would keep the TODO, and we can came back to this once we start working on:
modules/images/webp-uploads/load.php
Outdated
| $backup_sizes = get_post_meta( $attachment_id, '_wp_attachment_backup_sizes', true ); | ||
| $backup_sizes = is_array( $backup_sizes ) ? $backup_sizes : array(); | ||
|
|
||
| foreach ( webp_uploads_get_image_sizes() as $size => $properties ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of trying to recreate sizes, can we just copy the meta 'sizes'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can certainly do that but aside from that, we need to know if the newly created image should be cropped or not and that's the main reason why we need this function.
I think something we can do at the top of the foreach loop to make sure this $size exists in the original metadata before creating a targeted image instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, this is already the case on this line 😃
| if ( empty( $metadata['sizes'][ $size ] ) || ! is_array( $metadata['sizes'][ $size ] ) ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I noticed in testing when I uploading a very large image, I got a jpeg created with a -scaled suffix, then all of the generated .webp sub size files also included the -scaled suffix:
In addition, I noticed there was no full sized .webp created (that is {filename}-scaled.webp) - we need that full sized file for the image markup (only applies when you upload images larger than big_image_size_threshold)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for testing and for the feedback. Some follow-up comments.
One thing I noticed in testing when I uploading a very large image, I got a jpeg created with a -scaled suffix, then all of the generated .webp sub size files also included the -scaled suffix.
Great point mostly because this is created out of the scaled version. But let me fix this one :)
In addition, I noticed there was no full sized .webp created (that is {filename}-scaled.webp) - we need that full sized file for the image markup (only applies when you upload images larger than big_image_size_threshold)
Actually, this follows the same logic applied here #122 and #143 this behavior would go against this solved issue, as this scaled version is the full size image. Based on the issue scaled and full size always remains in the original image format. (not converted)
Let me know if you think we should change it instead.
Co-authored-by: Adam Silverstein <[email protected]>
Update the logic for hwo the additional mime types were created in order to allow image edits to take effect, when an image is cropped, flipped or rotated, those transformations are reflected into the additional mime types.
This would allow to quickly locate `webp` or a defined extension images and split between `-orig` images suffix as well.
Prevent namespace collisions when using the function from within the plugin.
The callback was passed as a parameter, no change is placed on the callback so we can safely return it.
This was due in some cases when restoring an image and editing it again, the image would result in not executing correctly due the meta was the same as before and the update callback was not executed, instead we are moving this work into an ajax callback.
modules/images/webp-uploads/load.php
Outdated
| } | ||
|
|
||
| // All subsizes are created out of the `file` property and not the original image. | ||
| $file = get_attached_file( $attachment_id, true ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you use get_attached_file here instead of the original image, is this to use the -scaled image?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct any edits to an image are performed to the scaled version (if present) by WordPress so any subsize should be based out of the modified image and not the original image instead.
The original image is only used to create the scaled version if not required it would be used as the attached file instead.
| // The file already exists as part of the backup sizes in the same key. | ||
| if ( array_key_exists( $key, $backup_sizes ) ) { | ||
| // This case would remove the file if is an edited version. | ||
| if ( defined( 'IMAGE_EDIT_OVERWRITE' ) && IMAGE_EDIT_OVERWRITE ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice!
| unset( $backup_sizes[ $key ] ); | ||
| } | ||
|
|
||
| // Editor needs to be recreated every time as there is not flush() or clear() function that can be used after we created an image. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you try$editor->__destruct (or even just $editor = null which should trigger __destruct)? For both Imagick and GD this should clear the image.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, let me try that thanks for the suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually calling __destruct seems like the same as creating a new variable altogether as essentially this is called by the engine itself so, for now, will keep it like that.
One thing that I've noted out of the class WP_Image_Editor is the fact that has a property get_size but not a set_size which would be the one we can use here to reset the size to the appropriate dimensions. Any thoughts on that one ?
| * @since 1.0.0 | ||
| */ | ||
|
|
||
| add_filter( 'wp_generate_attachment_metadata', 'webp_uploads_create_images_with_additional_mime_types', 10, 3 ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generating the additional mime types immediately might fail because it will double execution time, right? I can test this locally, but I think this might break uploads for some users.
Can we instead add an immediately one-time executing cron callback (wp_schedule_single_event)? that way the images will get generated on the next callback as part of a separate request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree I'm going to explore this as part of enchantment on top of this PR as you describe has become quite large at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I just updated this PR to handle this case.
| ); | ||
|
|
||
| /** | ||
| * An array representing all the valid mime types where multiple images would be created if |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should make sure that by returning only webp in the array only webp images are generated - that is, the uploads would work the way they do now in the plugin.
Although we decided this shouldn't be the default approach, it may turn out to be the best approach for most users, and over time it may become our choice for default. Code wise, we should be able to keep the existing plugin approach, but only use it in the case when a single mime type is specified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great point.
Let me think about how I can go about this use case when only a single mime type is present either JPEG or WebP so I can update this PR accordingly. Another use case we need to consider is the fact that due this is filterable it can be empty as well. Under that scenario we can either:
- Generate all subsizes with the same mime-type as the original image regardless if this filter is empty
- Not generate any subsize to follow what was specified on the filter.
It feels like the last point would be the way to go for consistency but let me know your thoughts on that one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed this one and added a TODO to handle this last point.
|
@mitogh this looks good so far, I left some small comments and questions. This PR has grown quite large because in addition to handling image generation you are supporting image edit and restore. I realize these are related because of the data storage, but still wonder if we could break them out so we can focus solely on the image generation and meta data storage. Once we land that, we can tackle the edit/restore bits in a separate PR. |
THe hash extraction ahs been moved into a custom function to avoid confusion and bring clarity when used.
Remove the suffix: - scaled - rotated - imagifyresized From the file names if present.
The result of the condition is always a boolean, so this section can be simplified with a single line instead.
Additional images would be created during a cron execution, removing any workload from the initial request. Tests where fixed and some new ones where introduced.
|
@mitogh @adamsilverstein I think the approach in #147 makes more sense than this one. Regarding backward-compatibility, I don't think the approach here justifies going with it given the unexpected data storage, specifically for the following reasons:
|
|
Closing this one in favor of: Details #147 (comment) |

Summary
Creates the JPEG version of the WebP images and store the references into
_wp_attachment_backup_sizessimilar to image transformations in order to take advantage of benefits from WP Core like files removed automatically by WordPress and uploaded into CDNsFixes:
Relevant technical choices
The changes introduced in this PR replicate the same behavior from WordPress core to store edited versions of additional mime types and the additional mime types themselves in the meta
_wp_attachment_backup_sizes.Checklist
[Focus]orInfrastructurelabel.[Type]label.no milestonelabel.