Skip to content

Commit

Permalink
Closes 2554: Prevent having a webp bigger than the original (#751)
Browse files Browse the repository at this point in the history
  • Loading branch information
CrochetFeve0251 authored Nov 13, 2023
1 parent e5555a3 commit 93d6964
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 3 deletions.
1 change: 1 addition & 0 deletions classes/Optimization/Data/AbstractData.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ abstract class AbstractData implements DataInterface {
*/
protected $default_optimization_data = [
'status' => '',
'message' => '',
'level' => false,
'sizes' => [],
'stats' => [
Expand Down
4 changes: 4 additions & 0 deletions classes/Optimization/Data/CustomFolders.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 5 additions & 0 deletions classes/Optimization/Data/WP.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
4 changes: 4 additions & 0 deletions classes/Optimization/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
50 changes: 48 additions & 2 deletions classes/Optimization/Process/AbstractProcess.php
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
}
}
}
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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'];
}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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 );

Expand Down
7 changes: 7 additions & 0 deletions classes/Optimization/Process/ProcessInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*
Expand Down
4 changes: 4 additions & 0 deletions inc/classes/class-imagify-files-list-table.php
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,10 @@ public function column_optimization( $item ) {
<span class="data"><?php esc_html_e( 'WebP generated:', 'imagify' ); ?></span>
<strong class="data-value"><?php echo esc_html( $has_webp ); ?></strong>
</li>
<li class="imagify-data-item">
<span class="data"><?php esc_html_e( 'WebP generated:', 'imagify' ); ?></span>
<strong class="data-value"><?php echo esc_html( $has_webp ); ?></strong>
</li>
<?php
}
}
Expand Down
13 changes: 13 additions & 0 deletions inc/classes/class-imagify.php
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,19 @@ private function curl_http_call( $url, $args = [] ) {
return new WP_Error( 'curl', 'cURL isn\'t installed on the server.' );
}

/**
* Allows to mock Imagify calls to the API.
*
* @param stdClass|null $response Response from the call.
* @param string $url URL from the call.
* @param array $args Arguments from the call.
*/
$response = apply_filters( 'pre_imagify_request', null, $url, $args );

if ( $response ) {
return $response;
}

try {
$url = self::API_ENDPOINT . $url;
$ch = curl_init();
Expand Down
9 changes: 9 additions & 0 deletions inc/functions/admin-ui.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,18 @@ function get_imagify_attachment_optimization_text( $process ) {
}

$data = $process->get_data();
$optimized_data = $data->get_optimization_data();
$attachment_id = $media->get_id();
$optimization_level = imagify_get_optimization_level_label( $data->get_optimization_level() );

if ( ! $is_media_page ) {
$output .= $output_before . '<span class="data">' . __( 'New Filesize:', 'imagify' ) . '</span> <strong class="big">' . $data->get_optimized_size() . '</strong>' . $output_after;
}

if ( key_exists( 'message', $optimized_data ) && $optimized_data['message'] ) {
$output .= $output_before . '<span class="data">' . __( 'Convert:', 'imagify' ) . '</span> <strong class="big">' . $optimized_data['message'] . '</strong>' . $output_after;
}

$chart = '';

if ( ! $is_media_page ) {
Expand Down Expand Up @@ -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 . '<span class="data">' . __( 'WebP generated:', 'imagify' ) . '</span> <strong class="big">' . esc_html( $has_webp ) . '</strong>' . $output_after;

$total_optimized_thumbnails = $data->get_optimized_sizes_count();
Expand Down
3 changes: 2 additions & 1 deletion inc/functions/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) ) {
Expand Down Expand Up @@ -199,6 +199,7 @@ function imagify_translate_api_message( $message ) {
'</a>'
),
'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.
Expand Down

0 comments on commit 93d6964

Please sign in to comment.