| @@ -13,15 +13,16 @@ | ||
| 13 | 13 | Image, |
| 14 | 14 | Image_Backup, |
| 15 | 15 | Image_Conversion, |
| 16 | 16 | Image_DB_Update, |
| 17 | + Image_Dimensions, | |
| 17 | 18 | Image_Meta, |
| 18 | 19 | Image_Status, |
| 19 | - WP_Image_Meta}; | |
| 20 | + WP_Image_Meta | |
| 21 | +}; | |
| 20 | 22 | use ImageOptimization\Classes\Logger; |
| 21 | 23 | use ImageOptimization\Classes\Utils; |
| 22 | 24 | use ImageOptimization\Classes\Exceptions\Quota_Exceeded_Error; |
| 23 | -use ImageOptimization\Modules\Oauth\Components\Connect; | |
| 24 | 25 | use ImageOptimization\Modules\Optimization\Classes\{ |
| 25 | 26 | Exceptions\Image_File_Already_Exists_Error, |
| 26 | 27 | Exceptions\Image_Optimization_Error, |
| 27 | 28 | Exceptions\Bulk_Token_Expired_Error, |
| @@ -26,8 +27,9 @@ | ||
| 26 | 27 | Exceptions\Image_Optimization_Error, |
| 27 | 28 | Exceptions\Bulk_Token_Expired_Error, |
| 28 | 29 | Exceptions\Image_Already_Optimized_Error, |
| 29 | 30 | }; |
| 31 | +use ImageOptimization\Modules\Connect\Classes\Exceptions\Connection_Error; | |
| 30 | 32 | use ImageOptimization\Modules\Settings\Classes\Settings; |
| 31 | 33 | use Throwable; |
| 32 | 34 | |
| 33 | 35 | use ImageOptimization\Plugin; |
| @@ -42,9 +44,9 @@ | ||
| 42 | 44 | * |
| 43 | 45 | * This class is used by manual, bulk and on-upload optimization flows. |
| 44 | 46 | */ |
| 45 | 47 | class Optimize_Image { |
| 46 | - private const IMAGE_OPTIMIZE_ENDPOINT = 'image/optimize'; | |
| 48 | + public const IMAGE_OPTIMIZE_ENDPOINT = 'image/optimize'; | |
| 47 | 49 | |
| 48 | 50 | protected ?Image $image; |
| 49 | 51 | protected WP_Image_Meta $wp_meta; |
| 50 | 52 | protected string $initiator; |
| @@ -53,20 +55,18 @@ | ||
| 53 | 55 | private string $current_image_size; |
| 54 | 56 | private bool $keep_backups; |
| 55 | 57 | private array $current_size_duplicates; |
| 56 | 58 | protected Image_Conversion $image_conversion; |
| 59 | + private bool $is_reoptimize; | |
| 57 | 60 | |
| 58 | 61 | /** |
| 59 | - * @throws Quota_Exceeded_Error|Bulk_Token_Expired_Error|Image_File_Already_Exists_Error|Image_Optimization_Error | |
| 62 | + * @throws Quota_Exceeded_Error|Connection_Error|Bulk_Token_Expired_Error|Image_File_Already_Exists_Error|Image_Optimization_Error | |
| 60 | 63 | */ |
| 61 | 64 | public function optimize(): void { |
| 62 | 65 | $sizes_enabled = Settings::get( Settings::CUSTOM_SIZES_OPTION_NAME ); |
| 63 | 66 | $sizes_exist = $this->wp_meta->get_size_keys(); |
| 64 | 67 | |
| 65 | - Logger::log( | |
| 66 | - Logger::LEVEL_INFO, | |
| 67 | - "Start optimization of {$this->image->get_id()}" | |
| 68 | - ); | |
| 68 | + Logger::debug( "Start optimization of {$this->image->get_id()}" ); | |
| 69 | 69 | |
| 70 | 70 | foreach ( $sizes_exist as $size_exist ) { |
| 71 | 71 | // If some image sizes optimization is disabled in settings, we check if the current one is still enabled |
| 72 | 72 | if ( |
| @@ -84,24 +84,18 @@ | ||
| 84 | 84 | |
| 85 | 85 | $image_meta = new Image_Meta( $this->image->get_id() ); |
| 86 | 86 | |
| 87 | 87 | // If the current size was already optimized -- ignore it. |
| 88 | - if ( in_array( $size_exist, $image_meta->get_optimized_sizes(), true ) ) { | |
| 89 | - Logger::log( | |
| 90 | - Logger::LEVEL_INFO, | |
| 91 | - "Size `$size_exist` is already optimized" | |
| 92 | - ); | |
| 88 | + if ( ! $this->is_reoptimize && in_array( $size_exist, $image_meta->get_optimized_sizes(), true ) ) { | |
| 89 | + Logger::debug( "Size `$size_exist` is already optimized" ); | |
| 93 | 90 | |
| 94 | 91 | continue; |
| 95 | 92 | } |
| 96 | 93 | |
| 97 | 94 | if ( ! file_exists( $this->image->get_file_path( $size_exist ) ) ) { |
| 98 | - Logger::log( | |
| 99 | - Logger::LEVEL_ERROR, | |
| 100 | - "Can't access file for size `$size_exist`" | |
| 101 | - ); | |
| 95 | + Logger::debug( "Can't access file for size `$size_exist`" ); | |
| 102 | 96 | |
| 103 | - throw new Image_Optimization_Error( esc_html__( 'File is missing. Verify the upload', 'image-optimization' ) ); | |
| 97 | + continue; | |
| 104 | 98 | } |
| 105 | 99 | |
| 106 | 100 | $this->current_image_size = $size_exist; |
| 107 | 101 | $this->current_size_duplicates = $this->wp_meta->get_size_duplicates( $size_exist ); |
| @@ -119,12 +113,9 @@ | ||
| 119 | 113 | if ( ! $this->keep_backups ) { |
| 120 | 114 | Image_Backup::remove( $this->image->get_id() ); |
| 121 | 115 | } |
| 122 | 116 | |
| 123 | - Logger::log( | |
| 124 | - Logger::LEVEL_INFO, | |
| 125 | - "End optimization of {$this->image->get_id()}" | |
| 126 | - ); | |
| 117 | + Logger::debug( "End optimization of {$this->image->get_id()}" ); | |
| 127 | 118 | } |
| 128 | 119 | |
| 129 | 120 | private function optimize_current_size(): void { |
| 130 | 121 | try { |
| @@ -143,19 +134,19 @@ | ||
| 143 | 134 | |
| 144 | 135 | // This should only be updated after meta |
| 145 | 136 | $this->update_attachment_post(); |
| 146 | 137 | } catch ( Image_Already_Optimized_Error $iao ) { |
| 147 | - // If we can't optimize it further, just file update the meta | |
| 138 | + // If we can't optimize it further, just update the meta | |
| 148 | 139 | $original_size = $this->wp_meta->get_file_size( $this->current_image_size ) |
| 149 | 140 | ?? File_System::size( $this->image->get_file_path( $this->current_image_size ) ); |
| 150 | 141 | |
| 151 | - $this->update_attachment_meta( $original_size ); | |
| 152 | - $this->update_attachment_post(); | |
| 153 | - } catch ( Bulk_Token_Expired_Error | Quota_Exceeded_Error | Image_File_Already_Exists_Error $e ) { | |
| 142 | + $this->update_attachment_meta( $original_size, true ); | |
| 143 | + $this->update_attachment_post( true ); | |
| 144 | + } catch ( Bulk_Token_Expired_Error | Quota_Exceeded_Error | Connection_Error | Image_File_Already_Exists_Error $e ) { | |
| 154 | 145 | throw $e; |
| 155 | 146 | } catch ( Throwable $t ) { |
| 156 | 147 | // In case of anything else |
| 157 | - throw new Image_Optimization_Error( $t->getMessage() ); | |
| 148 | + throw new Image_Optimization_Error( esc_html( $t->getMessage() ) ); | |
| 158 | 149 | } |
| 159 | 150 | } |
| 160 | 151 | |
| 161 | 152 | private function send_file() { |
| @@ -201,12 +192,9 @@ | ||
| 201 | 192 | Plugin::instance()->modules_manager->get_modules( 'connect-manager' )->connect_instance->update_usage_data( $response->stats ); |
| 202 | 193 | } |
| 203 | 194 | |
| 204 | 195 | if ( ! isset( $response->imageKey ) || $image_key !== $response->imageKey ) { // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase |
| 205 | - Logger::log( | |
| 206 | - Logger::LEVEL_ERROR, | |
| 207 | - "Image key must be $image_key, instead got $response->imageKey" | |
| 208 | - ); | |
| 196 | + Logger::error( "Image key must be $image_key, instead got $response->imageKey" ); | |
| 209 | 197 | |
| 210 | 198 | throw new Image_Optimization_Error( esc_html__( 'Service response is incorrect', 'image-optimization' ) ); |
| 211 | 199 | } |
| 212 | 200 | |
| @@ -212,12 +200,9 @@ | ||
| 212 | 200 | |
| 213 | 201 | $received_file_hash = md5( base64_decode( $response->image, true ) ); |
| 214 | 202 | |
| 215 | 203 | if ( ! isset( $response->checksum ) || $received_file_hash !== $response->checksum ) { |
| 216 | - Logger::log( | |
| 217 | - Logger::LEVEL_ERROR, | |
| 218 | - "Image key must be $response->checksum, instead calculated $received_file_hash" | |
| 219 | - ); | |
| 204 | + Logger::error( "Image key must be $response->checksum, instead calculated $received_file_hash" ); | |
| 220 | 205 | |
| 221 | 206 | throw new Image_Optimization_Error( esc_html__( 'Service response is incorrect', 'image-optimization' ) ); |
| 222 | 207 | } |
| 223 | 208 | |
| @@ -279,12 +264,12 @@ | ||
| 279 | 264 | * Updates attachment records in the `wp_posts` table. |
| 280 | 265 | * |
| 281 | 266 | * @return void |
| 282 | 267 | */ |
| 283 | - private function update_attachment_post() { | |
| 268 | + private function update_attachment_post( ?bool $is_fully_optimized = false ) { | |
| 284 | 269 | $update_query = []; |
| 285 | 270 | |
| 286 | - if ( $this->image_conversion->is_enabled() ) { | |
| 271 | + if ( $this->image_conversion->is_enabled() && ! $is_fully_optimized ) { | |
| 287 | 272 | $attachment_object = $this->image->get_attachment_object(); |
| 288 | 273 | |
| 289 | 274 | $update_query['guid'] = File_Utils::replace_extension( |
| 290 | 275 | $attachment_object->guid, |
| @@ -303,16 +288,16 @@ | ||
| 303 | 288 | /** |
| 304 | 289 | * Updates attachment records in the `wp_postmeta` table. |
| 305 | 290 | * |
| 306 | 291 | * @param int $optimized_size |
| 292 | + * @param bool|null $is_fully_optimized | |
| 307 | 293 | * |
| 308 | 294 | * @return void |
| 309 | 295 | */ |
| 310 | - private function update_attachment_meta( int $optimized_size ) { | |
| 296 | + private function update_attachment_meta( int $optimized_size, ?bool $is_fully_optimized = false ) { | |
| 311 | 297 | $meta = new Image_Meta( $this->image->get_id() ); |
| 298 | + $dimensions = Image_Dimensions::get_by_path( $this->current_image_path ); | |
| 312 | 299 | |
| 313 | - list($width, $height) = getimagesize( $this->current_image_path ); | |
| 314 | - | |
| 315 | 300 | $sizes_to_update = [ $this->current_image_size, ...$this->current_size_duplicates ]; |
| 316 | 301 | |
| 317 | 302 | foreach ( $sizes_to_update as $size ) { |
| 318 | 303 | $meta |
| @@ -320,13 +305,13 @@ | ||
| 320 | 305 | ->add_optimized_size( $size ) |
| 321 | 306 | ->add_original_data( $size, $this->wp_meta->get_size_data( $size ) ); |
| 322 | 307 | |
| 323 | 308 | $this->wp_meta |
| 324 | - ->set_width( $size, $width ) | |
| 325 | - ->set_height( $size, $height ) | |
| 309 | + ->set_width( $size, $dimensions->width ) | |
| 310 | + ->set_height( $size, $dimensions->height ) | |
| 326 | 311 | ->set_file_size( $size, $optimized_size ); |
| 327 | 312 | |
| 328 | - if ( $this->image_conversion->is_enabled() ) { | |
| 313 | + if ( $this->image_conversion->is_enabled() && ! $is_fully_optimized ) { | |
| 329 | 314 | $this->wp_meta |
| 330 | 315 | ->set_file_path( $size, $this->current_image_path ) |
| 331 | 316 | ->set_mime_type( $size, $this->image_conversion->get_current_mime_type() ); |
| 332 | 317 | } |
| @@ -366,13 +351,14 @@ | ||
| 366 | 351 | |
| 367 | 352 | /** |
| 368 | 353 | * @throws Invalid_Image_Exception |
| 369 | 354 | */ |
| 370 | - public function __construct( int $image_id, string $initiator, ?string $bulk_token = null ) { | |
| 355 | + public function __construct( int $image_id, string $initiator, ?string $bulk_token = null, ?bool $is_reoptimize = false ) { | |
| 371 | 356 | $this->image = new Image( $image_id ); |
| 372 | 357 | $this->wp_meta = new WP_Image_Meta( $image_id, $this->image ); |
| 373 | 358 | $this->initiator = $initiator; |
| 374 | 359 | $this->bulk_token = $bulk_token; |
| 360 | + $this->is_reoptimize = $is_reoptimize; | |
| 375 | 361 | $this->image_conversion = new Image_Conversion(); |
| 376 | 362 | $this->keep_backups = Settings::get( Settings::BACKUP_ORIGINAL_IMAGES_OPTION_NAME ); |
| 377 | 363 | } |
| 378 | 364 | } |