From 93d69647d0bdb11d47aa0fb3cca226f3c524d67f Mon Sep 17 00:00:00 2001 From: Cyrille C <18537428+CrochetFeve0251@users.noreply.github.com> Date: Mon, 13 Nov 2023 14:50:11 +0100 Subject: [PATCH] Closes 2554: Prevent having a webp bigger than the original (#751) --- classes/Optimization/Data/AbstractData.php | 1 + classes/Optimization/Data/CustomFolders.php | 4 ++ classes/Optimization/Data/WP.php | 5 ++ classes/Optimization/File.php | 4 ++ .../Optimization/Process/AbstractProcess.php | 50 ++++++++++++++++++- .../Optimization/Process/ProcessInterface.php | 7 +++ .../class-imagify-files-list-table.php | 4 ++ inc/classes/class-imagify.php | 13 +++++ inc/functions/admin-ui.php | 9 ++++ inc/functions/api.php | 3 +- 10 files changed, 97 insertions(+), 3 deletions(-) diff --git a/classes/Optimization/Data/AbstractData.php b/classes/Optimization/Data/AbstractData.php index c538c3dfd..3c30b4424 100644 --- a/classes/Optimization/Data/AbstractData.php +++ b/classes/Optimization/Data/AbstractData.php @@ -25,6 +25,7 @@ abstract class AbstractData implements DataInterface { */ protected $default_optimization_data = [ 'status' => '', + 'message' => '', 'level' => false, 'sizes' => [], 'stats' => [ diff --git a/classes/Optimization/Data/CustomFolders.php b/classes/Optimization/Data/CustomFolders.php index f274b65ca..dc2cb5780 100644 --- a/classes/Optimization/Data/CustomFolders.php +++ b/classes/Optimization/Data/CustomFolders.php @@ -159,6 +159,10 @@ public function update_size_optimization_data( $size, array $data ) { $old_data['hash'] = md5_file( $file_path ); } + if ( key_exists( 'message', $data ) ) { + $old_data['message'] = $data['message']; + } + if ( ! $data['success'] ) { /** * Error. diff --git a/classes/Optimization/Data/WP.php b/classes/Optimization/Data/WP.php index 220d48916..90db43fd7 100644 --- a/classes/Optimization/Data/WP.php +++ b/classes/Optimization/Data/WP.php @@ -93,8 +93,13 @@ public function update_size_optimization_data( $size, array $data ) { 'original_size' => 0, 'optimized_size' => 0, 'percent' => 0, + 'message' => '', ], $old_data['stats'] ); + if ( key_exists( 'message', $data ) ) { + $old_data['message'] = $data['message']; + } + if ( ! $data['success'] ) { /** * Error. diff --git a/classes/Optimization/File.php b/classes/Optimization/File.php index 170e965f5..57820f168 100644 --- a/classes/Optimization/File.php +++ b/classes/Optimization/File.php @@ -530,6 +530,10 @@ public function optimize( $args = [] ) { return new \WP_Error( 'temp_file_not_found', $temp_file->get_error_message() ); } + if ( property_exists( $response, 'message' ) ) { + $args['convert'] = ''; + } + if ( 'webp' === $args['convert'] ) { $destination_path = $this->get_path_to_webp(); $this->path = $destination_path; diff --git a/classes/Optimization/Process/AbstractProcess.php b/classes/Optimization/Process/AbstractProcess.php index bdd536668..bec0948df 100644 --- a/classes/Optimization/Process/AbstractProcess.php +++ b/classes/Optimization/Process/AbstractProcess.php @@ -656,6 +656,14 @@ public function optimize_size( $size, $optimization_level = null ) { 'non_webp_file_path' => $sizes[ $thumb_size ]['path'], // Don't use $path nor $file->get_path(), it may return the path to a temporary file. 'optimization_level' => $optimization_level, ] ); + + if ( property_exists( $response, 'message' ) ) { + $path_is_temp = false; + if ( $path !== $sizes[ $thumb_size ]['path'] ) { + $this->filesystem->delete( $path ); + } + $path = $sizes[ $thumb_size ]['path']; + } } } } @@ -731,7 +739,7 @@ protected function compare_webp_file_size( $args ) { } // Optimization succeeded. - if ( $args['is_webp'] ) { + if ( ! property_exists( $args['response'], 'message' ) && $args['is_webp'] ) { /** * We just created a WebP version: * Check if it is lighter than the (maybe optimized) non-WebP file. @@ -776,7 +784,7 @@ protected function compare_webp_file_size( $args ) { $webp_size = $args['non_webp_thumb_size'] . static::WEBP_SUFFIX; $webp_file_size = $this->get_data()->get_size_data( $webp_size, 'optimized_size' ); - if ( ! $webp_file_size || $webp_file_size < $args['response']->new_size ) { + if ( property_exists( $args['response'], 'message' ) || ! $webp_file_size || $webp_file_size < $args['response']->new_size ) { // The WebP file is lighter than this one. return $args['response']; } @@ -1531,6 +1539,38 @@ public function has_webp() { return is_string( $data ) && strpos( $data, $needle ); } + /** + * Tell if the media has all WebP versions. + * + * @return bool + */ + public function is_full_webp() { + if ( ! $this->is_valid() ) { + return false; + } + + if ( ! $this->get_media()->is_image() ) { + return false; + } + + $data = $this->get_data()->get_optimization_data(); + + $sizes = $data['sizes']; + + if ( empty( $sizes ) ) { + return false; + } + + $keys = array_keys( $sizes ); + $non_webp_keys = array_values(array_filter($keys, function ( $key ) { + return strpos( $key, static::WEBP_SUFFIX ) === false; + })); + + return array_reduce($non_webp_keys, function ( $is_fully, $key ) use ( $sizes ) { + return key_exists( $key . self::WEBP_SUFFIX, $sizes ) && $is_fully; + }, true); + } + /** * Tell if a WebP version can be created for the given file. * Make sure the file is an image before using this method. @@ -1757,6 +1797,9 @@ public function update_size_optimization_data( $response, $size, $level ) { // Size data. $data['success'] = true; + if ( property_exists( $response, 'message' ) ) { + $data['message'] = imagify_translate_api_message( $response->message ); + } $data['original_size'] = $response->original_size; $data['optimized_size'] = $response->new_size; } @@ -1785,6 +1828,9 @@ public function update_size_optimization_data( $response, $size, $level ) { */ $data = (array) apply_filters( "imagify{$_unauthorized}_file_optimization_data", $data, $response, $size, $level, $this->get_data() ); + if ( property_exists( $response, 'message' ) ) { + $size = str_replace( '@imagify-webp', '', $size ); + } // Store. $this->get_data()->update_size_optimization_data( $size, $data ); diff --git a/classes/Optimization/Process/ProcessInterface.php b/classes/Optimization/Process/ProcessInterface.php index 09baade25..fa525647f 100644 --- a/classes/Optimization/Process/ProcessInterface.php +++ b/classes/Optimization/Process/ProcessInterface.php @@ -274,6 +274,13 @@ public function delete_webp_files( $keep_full = false ); */ public function is_size_webp( $size_name ); + /** + * Tell if the media has all WebP versions. + * + * @return bool + */ + public function is_full_webp(); + /** * Tell if the media has WebP versions. * diff --git a/inc/classes/class-imagify-files-list-table.php b/inc/classes/class-imagify-files-list-table.php index 0ca273f18..0be0e0f4b 100755 --- a/inc/classes/class-imagify-files-list-table.php +++ b/inc/classes/class-imagify-files-list-table.php @@ -612,6 +612,10 @@ public function column_optimization( $item ) { +
  • + + +
  • get_data(); + $optimized_data = $data->get_optimization_data(); $attachment_id = $media->get_id(); $optimization_level = imagify_get_optimization_level_label( $data->get_optimization_level() ); @@ -49,6 +50,10 @@ function get_imagify_attachment_optimization_text( $process ) { $output .= $output_before . '' . __( 'New Filesize:', 'imagify' ) . ' ' . $data->get_optimized_size() . '' . $output_after; } + if ( key_exists( 'message', $optimized_data ) && $optimized_data['message'] ) { + $output .= $output_before . '' . __( 'Convert:', 'imagify' ) . ' ' . $optimized_data['message'] . '' . $output_after; + } + $chart = ''; if ( ! $is_media_page ) { @@ -90,6 +95,10 @@ function get_imagify_attachment_optimization_text( $process ) { if ( $media->is_image() ) { $has_webp = $process->has_webp() ? __( 'Yes', 'imagify' ) : __( 'No', 'imagify' ); + + if ( $process->has_webp() ) { + $has_webp = $process->is_full_webp() ? __( 'Yes', 'imagify' ) : __( 'Partially', 'imagify' ); + } $output .= $output_before . '' . __( 'WebP generated:', 'imagify' ) . ' ' . esc_html( $has_webp ) . '' . $output_after; $total_optimized_thumbnails = $data->get_optimized_sizes_count(); diff --git a/inc/functions/api.php b/inc/functions/api.php index c6f32307b..e53831340 100755 --- a/inc/functions/api.php +++ b/inc/functions/api.php @@ -164,7 +164,7 @@ function get_imagify_max_image_size() { */ function imagify_translate_api_message( $message ) { if ( ! $message ) { - return imagify_translate_api_message( 'Unknown error occurred' ); + $message = 'Unknown error occurred'; } if ( is_wp_error( $message ) ) { @@ -199,6 +199,7 @@ function imagify_translate_api_message( $message ) { '' ), 'Your image is too big to be uploaded on our server' => __( 'Your file is too big to be uploaded on our server.', 'imagify' ), + 'Webp is less performant than original' => __( 'WebP file is larger than the original image', 'imagify' ), 'Our server returned an invalid response' => __( 'Our server returned an invalid response.', 'imagify' ), 'cURL isn\'t installed on the server' => __( 'cURL is not available on the server.', 'imagify' ), // API messages.