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
Allow developers to tweak which image formats to generate on upload #227
Conversation
…webp_uploads_upload_image_mime_transforms.
…rly if only the original mime type is needed.
…e correct mime type for new uploads.
Co-authored-by: Crisoforo Gaspar Hernández <hello@crisoforo.com>
…to return an empty array if a wrong value is returned from the filter.
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.
@eugene-manuilov Mostly looks good, I left a few comments for things that can be improved. One of them is crucial, we still need to run through the overall webp_uploads_create_sources_property()
function as before.
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.
@eugene-manuilov Awesome!
Overall this looks great, I will give this a test specifically to verify that the filter works to set output to a single mime type (eg transform jpeg->webp) and also test with and without WebP support. Can we add some additional tests that validates new functionality as well? |
@adamsilverstein @felixarntz @mitogh I have found and fixed a few issues while working on phpunit tests. Could you, please, take another look at the implementation? Also I have refactored a bit our phpunit tests for the webp-uploads module to make it easier to check sources. Let me know what you think. |
@@ -276,7 +278,15 @@ function webp_uploads_get_upload_image_mime_transforms() { | |||
return $default_transforms; | |||
} | |||
|
|||
return array_filter( $transforms, 'is_array' ); | |||
// Ensure that all mime types have correct transforms. If a mime type has invalid transforms array, |
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
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.
Minor comments, great work on refactoring the tests :)
$this->assertStringEndsNotWith( '.jpeg', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ); | ||
$this->assertStringEndsWith( '.webp', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ); | ||
$this->assertImageHasSizeSource( 'image/jpeg', 'thumbnail', $attachment_id ); | ||
$this->assertImageHasSizeSource( 'image/webp', 'thumbnail', $attachment_id ); |
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 think the abstraction works great to ensure the presence of the key this 2 assertions would ensure that the correct file extensions are used and can be used after assertImageHasSizeSource
as at that point if the previous assertions pass it can safely be used at this stage.
$this->assertImageHasSizeSource( 'image/webp', 'thumbnail', $attachment_id ); | |
$this->assertImageHasSizeSource( 'image/webp', 'thumbnail', $attachment_id ); | |
$this->assertStringEndsNotWith( '.jpeg', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ); | |
$this->assertStringEndsWith( '.webp', $metadata['sizes']['thumbnail']['sources']['image/webp']['file'] ); |
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 have added extensions check to image source constraints.
* @param int $attachment_id The attachment ID. | ||
* @param string $message An optional message to show on failure. | ||
*/ | ||
public static function assertImageHasSource( $mime_type, $attachment_id, $message = '' ) { |
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 would update the parameters as the mime type depends on the $attachment_id
it makes more sense to set first the attachment_id
public static function assertImageHasSource( $mime_type, $attachment_id, $message = '' ) { | |
public static function assertImageHasSource( $attachment_id, $expected_mime_type, $message = '' ) { |
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.
The current order is used to mimic how the ArrayHasKey
constraint work. The first param/params are needly and then goes the target that we want to check.
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.
Right, however by using this abstraction the second argument is no longer an array and if you are unfamiliar with the abstraction itself is difficult to know which is the base of the abstraction like if I want to use the assertion I would expect the first parameter to be the attachment ID similarly as how WP functions work due the expected_mime_type and additional parameters are based out of the attachment ID.
The logic comes from importance order:
- Attachment ID -> This is required and would always be present
- Size -> This is also present as is a WP API the only difference is the size name in some cases might not be defined
- Mime Type -> This is a newly introduced value so it might not be present in most cases.
Based on that order it makes more sense to pass the parameters in that order instead of the other way around.
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 don't have a strong opinion on either, but slightly leaning towards @mitogh's point here, since that order is what's more common in WordPress image functions.
The argument around assertArrayHasKey
makes sense, but here we're passing the attachment ID, and the assertion is not looking for the size "in" the attachment ID. It's looking for it in the metadata array. If the assertion was assertMetadataHasSource
, I think the assertArrayHasKey
comparison would make more sense, but because we're passing an attachment ID here, IMO sticking to the order WordPress developers are used to makes more sense.
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.
Ok, sounds good. Updated.
* @param int $attachment_id The attachment ID. | ||
* @param string $message An optional message to show on failure. | ||
*/ | ||
public static function assertImageNotHasSource( $mime_type, $attachment_id, $message = '' ) { |
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.
Same as above.
public static function assertImageNotHasSource( $mime_type, $attachment_id, $message = '' ) { | |
public static function assertImageNotHasSource( $attachment_id, $expected_mime_type, $message = '' ) { |
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.
Same reason. Just mimic how other constraints in phpunit work.
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.
See my reply above, slightly leaning towards @mitogh's point. But I think either way has its benefits here, I don't have a strong opinion.
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.
Ok, updated.
* @param int $attachment_id The attachment ID. | ||
* @param string $message An optional message to show on failure. | ||
*/ | ||
public static function assertImageHasSizeSource( $mime_type, $size, $attachment_id, $message = '' ) { |
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.
public static function assertImageHasSizeSource( $mime_type, $size, $attachment_id, $message = '' ) { | |
public static function assertImageHasSizeSource( $attachment_id, $size, $expected_mime_type, $message = '' ) { |
Since you are already using types would be great to specify the types as well for the parameters.
public static function assertImageHasSizeSource( $mime_type, $size, $attachment_id, $message = '' ) { | |
public static function assertImageHasSizeSource( int $attachment_id, string $size, string $expected_mime_type, string $message = '' ) { |
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 have added return types to custom constraints because it was required by php to make sure that the signature is compatible with the parent class. I am not sure about adding these types for params. Seems less important to me, but if we agree to add it, I'll update.
* @param int $attachment_id The attachment ID. | ||
* @param string $message An optional message to show on failure. | ||
*/ | ||
public static function assertImageNotHasSizeSource( $mime_type, $size, $attachment_id, $message = '' ) { |
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.
Similar to the above.
public static function assertImageNotHasSizeSource( $mime_type, $size, $attachment_id, $message = '' ) { | |
public static function assertImageNotHasSizeSource( $attachment_id, $size, $expected_mime_type, $message = '' ) { |
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.
Updated.
Co-authored-by: Crisoforo Gaspar Hernández <hello@crisoforo.com>
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.
@eugene-manuilov Great work refactoring the tests with the extra assertions! I have some minor comments, but nothing blocking.
* @param int $attachment_id The attachment ID. | ||
* @param string $message An optional message to show on failure. | ||
*/ | ||
public static function assertImageHasSource( $mime_type, $attachment_id, $message = '' ) { |
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 don't have a strong opinion on either, but slightly leaning towards @mitogh's point here, since that order is what's more common in WordPress image functions.
The argument around assertArrayHasKey
makes sense, but here we're passing the attachment ID, and the assertion is not looking for the size "in" the attachment ID. It's looking for it in the metadata array. If the assertion was assertMetadataHasSource
, I think the assertArrayHasKey
comparison would make more sense, but because we're passing an attachment ID here, IMO sticking to the order WordPress developers are used to makes more sense.
* @param int $attachment_id The attachment ID. | ||
* @param string $message An optional message to show on failure. | ||
*/ | ||
public static function assertImageNotHasSource( $mime_type, $attachment_id, $message = '' ) { |
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.
See my reply above, slightly leaning towards @mitogh's point. But I think either way has its benefits here, I don't have a strong opinion.
"autoload-dev": { | ||
"psr-4": { | ||
"PerformanceLab\\Tests\\": "tests/utils" | ||
} | ||
} |
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.
Not sure Composer usage like this would play well together with WordPress core, but since it's only tests IMO it should be okay at least in terms of this plugin. The classes would need to be renamed for core anyway.
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.
Do you mean I need to rename util classes to follow class-...
pattern? If so, can we make an exception for phpunit classes only?
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.
WordPress core still doesn't use any autoloading, there's always some sort of "includes" file that require_once
s all files. Obviously not great, but that's how I would do it, for maximum "compatibility" with the core paradigms.
However, since this is purely about PHPUnit classes and we're in this plugin, I'm not opposed to this (obviously better) approach :)
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.
Awesome! Thanks 😄
I did some testing to verify that the filter mapping works as expected, using the filter to test the following scenarios when uploading both jpegs and webp images:
In code: add_filter( 'webp_uploads_upload_image_mime_transforms', function() {
$test = 'only-webp'; // Try each
switch ( $test ) {
case 'only-webp':
return [
'image/jpeg' => [ 'image/webp' ],
'image/webp' => [ 'image/webp' ],
];
case 'only-jpg':
return [
'image/jpeg' => [ 'image/jpeg' ],
'image/webp' => [ 'image/jpeg' ],
];
case 'both':
return [
'image/jpeg' => [ 'image/jpeg', 'image/webp' ],
'image/webp' => [ 'image/webp', 'image/jpeg' ],
];
case 'reverse':
return [
'image/jpeg' => [ 'image/webp', 'image/jpeg' ],
'image/webp' => [ 'image/jpeg', 'image/webp' ],
];
case 'empty':
default:
return [];
}
}); I reviewed the files generated as well as the meta data. Comments below: ✅ only-webp: worked as expected, only webp images generated for either webp or jpeg uploads |
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 noticed some issues in testing that might be worth fixing, please review comment
Hm... it works correctly on my end. When I upload a webp image, all subsizes have been created in the jpeg format. The original image is still in webp though. Is it what you mean, @adamsilverstein? |
@adamsilverstein see #187 (comment):
Basically, what it says is that we need to select the alternate mime type for the "primary" image only if the original mime type is not included into the transformation list which is not the case in your situation. Does it make sense to you or I miss something? |
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.
Few minor comments, other than that great job 👍
Summary
Fixes #187
Relevant technical choices
Checklist
[Focus]
orInfrastructure
label.[Type]
label.no milestone
label.