update_attachment_to_webp( $attachment_id, $metadata ); } /** * Convert an attachment and all its sizes to WebP and update DB. * * @param int $attachment_id * @param array $metadata * @return array Updated metadata. */ public function update_attachment_to_webp( $attachment_id, $metadata = array() ) { $file = get_attached_file( $attachment_id ); if ( ! $file || ! file_exists( $file ) ) { update_post_meta( $attachment_id, '_AHSITW_converted', 'failed_missing' ); return $metadata; } if ( empty( $metadata ) ) { $metadata = wp_get_attachment_metadata( $attachment_id ); } $webp_file = $this->convert_image( $file ); if ( $webp_file ) { // Update the attachment path and MIME type in WordPress. update_attached_file( $attachment_id, $webp_file ); wp_update_post( array( 'ID' => $attachment_id, 'post_mime_type' => 'image/webp', ) ); $old_ext = pathinfo( $file, PATHINFO_EXTENSION ); if ( ! empty( $metadata['file'] ) ) { $metadata['file'] = str_replace( '.' . $old_ext, '.webp', $metadata['file'] ); } // Convert all sub-sizes. if ( ! empty( $metadata['sizes'] ) && is_array( $metadata['sizes'] ) ) { $base_dir = trailingslashit( dirname( $file ) ); foreach ( $metadata['sizes'] as $size => $size_data ) { if ( ! empty( $size_data['file'] ) ) { $size_file = $base_dir . $size_data['file']; $webp_size_file = $this->convert_image( $size_file ); if ( $webp_size_file ) { $metadata['sizes'][ $size ]['file'] = basename( $webp_size_file ); $metadata['sizes'][ $size ]['mime-type'] = 'image/webp'; } } } } // Finalize metadata update in DB. wp_update_attachment_metadata( $attachment_id, $metadata ); update_post_meta( $attachment_id, '_AHSITW_converted', current_time( 'mysql' ) ); return $metadata; } else { // Mark as failed to avoid infinite loop. update_post_meta( $attachment_id, '_AHSITW_converted', 'failed_process' ); } return false; } /** * Convert a single image file to WebP. * * @param string $file_path * @return string|bool Path to the WebP file on success, False on failure. */ public function convert_image( $file_path ) { if ( empty( $file_path ) || ! file_exists( $file_path ) ) { return false; } $ext = pathinfo( $file_path, PATHINFO_EXTENSION ); if ( 'webp' === strtolower( $ext ) ) { return $file_path; } $webp_path = preg_replace( '/\.(jpe?g|png)$/i', '.webp', $file_path ); if ( $webp_path === $file_path ) { $webp_path .= '.webp'; } $editor = wp_get_image_editor( $file_path ); if ( is_wp_error( $editor ) ) { return false; } $quality = absint( get_option( 'AHSITW_quality', 80 ) ); $editor->set_quality( ( $quality >= 1 && $quality <= 100 ) ? $quality : 80 ); $saved = $editor->save( $webp_path, 'image/webp' ); if ( is_wp_error( $saved ) ) { return false; } return $webp_path; } /** * Check if server supports WebP. * * @return bool */ public static function is_webp_supported() { return wp_image_editor_supports( array( 'mime_type' => 'image/webp' ) ); } }