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

Support retry mechanism for generating sub-sizes in additional MIME types on constrained environments. #188

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
123 changes: 89 additions & 34 deletions modules/images/webp-uploads/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
* @return array An array with the updated structure for the metadata before is stored in the database.
*/
function webp_uploads_create_sources_property( array $metadata, $attachment_id ) {
// Make sure we have some sizes to work with, otherwise avoid any work.
if ( empty( $metadata['sizes'] ) || ! is_array( $metadata['sizes'] ) ) {
return $metadata;
}
// This should take place only on the JPEG image.
$valid_mime_transforms = webp_uploads_get_supported_image_mime_transforms();

Expand All @@ -42,60 +46,64 @@ function webp_uploads_create_sources_property( array $metadata, $attachment_id )
return $metadata;
}

$dirname = pathinfo( $file, PATHINFO_DIRNAME );
$image_sizes = array();
if ( isset( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ) {
$image_sizes = $metadata['sizes'];
}

foreach ( wp_get_registered_image_subsizes() as $size_name => $properties ) {
// This image size does not exist on the defined sizes.
if ( ! isset( $image_sizes[ $size_name ] ) || ! is_array( $image_sizes[ $size_name ] ) ) {
$dirname = pathinfo( $file, PATHINFO_DIRNAME );
foreach ( $metadata['sizes'] as $size_name => $properties ) {
// This image size is not defined or not an array.
if ( ! is_array( $properties ) ) {
continue;
}

$current_size = $image_sizes[ $size_name ];
$sources = array();
if ( isset( $current_size['sources'] ) && is_array( $current_size['sources'] ) ) {
$sources = $current_size['sources'];
}

// Try to find the mime type of the image size.
$current_mime = '';
if ( isset( $current_size['mime-type'] ) ) {
$current_mime = $current_size['mime-type'];
} elseif ( isset( $current_size['file'] ) ) {
$current_mime = wp_check_filetype( $current_size['file'] )['type'];
if ( isset( $properties['mime-type'] ) ) {
$current_mime = $properties['mime-type'];
} elseif ( isset( $properties['file'] ) ) {
$current_mime = wp_check_filetype( $properties['file'] )['type'];
}

// The mime type can't be determined.
if ( empty( $current_mime ) ) {
continue;
}
mitogh marked this conversation as resolved.
Show resolved Hide resolved

$sources[ $current_mime ] = array(
'file' => isset( $current_size['file'] ) ? $current_size['file'] : '',
'filesize' => 0,
);
// Ensure a `sources` property exists on the existing size.
if ( empty( $properties['sources'] ) || ! is_array( $properties['sources'] ) ) {
$properties['sources'] = array();
}

// Set the filesize from the current mime image.
$file_location = path_join( $dirname, $sources[ $current_mime ]['file'] );
if ( file_exists( $file_location ) ) {
$sources[ $current_mime ]['filesize'] = filesize( $file_location );
if ( empty( $properties['sources'][ $current_mime ] ) ) {
$properties['sources'][ $current_mime ] = array(
'file' => isset( $properties['file'] ) ? $properties['file'] : '',
'filesize' => 0,
);
// Set the filesize from the current mime image.
$file_location = path_join( $dirname, $properties['file'] );
if ( file_exists( $file_location ) ) {
$properties['sources'][ $current_mime ]['filesize'] = filesize( $file_location );
}
$metadata['sizes'][ $size_name ] = $properties;
wp_update_attachment_metadata( $attachment_id, $metadata );
}

$formats = isset( $valid_mime_transforms[ $current_mime ] ) ? $valid_mime_transforms[ $current_mime ] : array();

foreach ( $formats as $mime ) {
if ( empty( $sources[ $mime ] ) ) {
$source = webp_uploads_generate_image_size( $attachment_id, $size_name, $mime );
if ( is_array( $source ) ) {
$sources[ $mime ] = $source;
}
// If this property exists no need to create the image again.
if ( ! empty( $properties['sources'][ $mime ] ) ) {
continue;
}

$source = webp_uploads_generate_image_size( $attachment_id, $size_name, $mime );
if ( is_wp_error( $source ) ) {
continue;
}

$properties['sources'][ $mime ] = $source;
$metadata['sizes'][ $size_name ] = $properties;
wp_update_attachment_metadata( $attachment_id, $metadata );
}

$current_size['sources'] = $sources;
$metadata['sizes'][ $size_name ] = $current_size;
mitogh marked this conversation as resolved.
Show resolved Hide resolved
$metadata['sizes'][ $size_name ] = $properties;
}

return $metadata;
Expand Down Expand Up @@ -285,3 +293,50 @@ function webp_uploads_remove_sources_files( $attachment_id ) {
}

add_action( 'delete_attachment', 'webp_uploads_remove_sources_files', 10, 1 );

/**
* Filter on `wp_get_missing_image_subsizes` acting as an action for the logic of the plugin
* to determine if additional mime types still need to be created.
*
* @since n.e.x.t
*
* @see wp_get_missing_image_subsizes()
*
* @param array $missing_sizes Associative array of arrays of image sub-sizes.
* @param array $image_meta The metadata from the image.
* @param int $attachment_id The ID of the attachment.
* @return array Associative array of arrays of image sub-sizes.
*/
function webp_uploads_wp_get_missing_image_subsizes( $missing_sizes, $image_meta, $attachment_id ) {
// Only setup the trace array if we no longer have more sizes.
if ( ! empty( $missing_sizes ) ) {
return $missing_sizes;
}

/**
* The usage of `debug_backtrace` in this particular case is mainly to ensure the call to
* `wp_get_missing_image_subsizes()` originated from `wp_update_image_subsizes()`, since only then the
* additional image sizes should be generated. `wp_get_missing_image_subsizes()` could also be called
* from other places in which case the custom logic should not trigger. In an ideal world an action
* would exist in `wp_update_image_subsizes` that runs any time, but the current
* `wp_generate_attachment_metadata` filter is skipped when all core sub-sizes have been generated.
* An eventual core implementation will not require this workaround. The limit of 10 is used to allow
* for some flexibility. While by default the function would be on index 5, other custom code may
* cause the index to be slightly higher.
*
* @see wp_update_image_subsizes()
* @see wp_get_missing_image_subsizes()
*/
$trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 10 );

foreach ( $trace as $element ) {
if ( isset( $element['function'] ) && 'wp_update_image_subsizes' === $element['function'] ) {
webp_uploads_create_sources_property( $image_meta, $attachment_id );
break;
}
}

return array();
}

add_filter( 'wp_get_missing_image_subsizes', 'webp_uploads_wp_get_missing_image_subsizes', 10, 3 );
mitogh marked this conversation as resolved.
Show resolved Hide resolved