Files
User A0264400 a766acdc90 first commit
2026-04-01 23:20:16 +03:00

838 lines
26 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Класс для работы со статистическими данными по оптимизации изображений
*
* @version 1.0
*/
class WRIO_Image_Statistic {
/**
* The single instance of the class.
*
* @since 1.3.0
* @access protected
* @var static
*/
protected static $_instance;
/**
* The statistic data.
*
* @var array{
* original: int,
* optimized: int,
* converted: int,
* optimized_percent: int|float,
* percent_line: float,
* webp_percent_line: float,
* unoptimized: int,
* unconverted: int,
* optimized_size: int|string,
* webp_optimized_size: int|string,
* avif_optimized_size: int|string,
* original_size: int|string,
* save_size_percent: float,
* error: int,
* webp_error: int,
* avif_converted: int,
* avif_unconverted: int,
* avif_percent_line: float,
* avif_error: int,
* quota_limit?: int|string
* }
* @see WRIO_Image_Statistic::load()
*/
protected $statistic;
/**
* Constructor.
*
* @return void
*
* @throws Exception
*/
public function __construct() {
$this->statistic = $this->load();
}
/**
* The main instance.
*
* @return static Returns the instance of the class.
* @since 1.3.0
*/
public static function get_instance() {
if ( ! isset( static::$_instance ) ) {
static::$_instance = new static();
}
return static::$_instance;
}
/**
* Read file size reliably within the current request.
* PHP caches stat() results; we clear cache for this path.
*
* @param mixed $file_path The file path.
*
* @return int
*/
protected function get_file_size( $file_path ) {
return wrio_get_file_size( $file_path );
}
/**
* Get the statistic data.
*
* @return array{
* original: int|string,
* optimized: int|string,
* converted: int,
* optimized_percent: float,
* percent_line: float,
* webp_percent_line: float,
* unoptimized: int,
* unconverted: int,
* optimized_size: int|string,
* webp_optimized_size: int|string,
* original_size: int|string,
* save_size_percent: float,
* error: int,
* webp_error: int,
* quota_limit?: int|string
* }
*/
public function get() {
return $this->statistic;
}
/**
* Добавляет новые данные к текущей статистике
* К текущим числам добавляются новые
*
* @param string $field Поле, к которому добавляем значение
* @param int $value добавляемое значение
*/
public function addToField( $field, $value ) {
if ( isset( $this->statistic[ $field ] ) ) {
$this->statistic[ $field ] = $this->statistic[ $field ] + $value;
}
}
/**
* Вычитает данные из текущей статистики
* Из текущего числа вычитается
*
* @param string $field Поле, из которого вычитается значение
* @param int $value вычитаемое значение
*/
public function deductFromField( $field, $value ) {
$value = (int) $value;
if ( isset( $this->statistic[ $field ] ) ) {
$this->statistic[ $field ] = $this->statistic[ $field ] - $value;
if ( $this->statistic[ $field ] < 0 ) {
$this->statistic[ $field ] = 0;
}
}
}
/**
* Сохранение статистики
*/
public function save() {
WRIO_Plugin::app()->updateOption( 'original_size', $this->statistic['original_size'] );
WRIO_Plugin::app()->updateOption( 'optimized_size', $this->statistic['optimized_size'] );
WRIO_Plugin::app()->updateOption( 'webp_optimized_size', $this->statistic['webp_optimized_size'] );
WRIO_Plugin::app()->updateOption( 'avif_optimized_size', $this->statistic['avif_optimized_size'] );
}
/**
* Loading statistics and calculating some parameters.
*
* @return array{
* original: int|string,
* optimized: int|string,
* converted: int,
* optimized_percent: float,
* percent_line: float,
* webp_percent_line: float,
* unoptimized: int,
* unconverted: int,
* optimized_size: int|string,
* webp_optimized_size: int|string,
* original_size: int|string,
* save_size_percent: float,
* error: int,
* webp_error: int,
* avif_converted: int,
* avif_unconverted: int,
* avif_percent_line: float,
* avif_error: int,
* quota_limit?: int|string
* }
*/
public function load() {
$original_size = WRIO_Plugin::app()->getOption( 'original_size', 0 );
$optimized_size = WRIO_Plugin::app()->getOption( 'optimized_size', 0 );
$webp_optimized_size = WRIO_Plugin::app()->getOption( 'webp_optimized_size', 0 );
$avif_optimized_size = WRIO_Plugin::app()->getOption( 'avif_optimized_size', 0 );
$image_query = WRIO_Image_Query::get_instance();
$total_images = $image_query->count_total_attachments( false ); // false = don't exclude WPML dupes for total display
$optimized_count = $image_query->count_optimized();
$error_count = $image_query->count_error(); // Count images with ANY error (attachment, webp, or avif)
$webp_optimized_count = RIO_Process_Queue::count_by_type_status( 'webp', 'success' );
$webp_error_count = (int) RIO_Process_Queue::count_by_type_status( 'webp', 'error' );
$avif_optimized_count = RIO_Process_Queue::count_by_type_status( 'avif', 'success' );
$avif_error_count = (int) RIO_Process_Queue::count_by_type_status( 'avif', 'error' );
if ( ! $total_images ) {
$total_images = 0;
}
if ( ! $error_count ) {
$error_count = 0;
}
if ( ! $optimized_count ) {
$optimized_count = 0;
}
// Unoptimized = total - optimized - errors (ensures mutual exclusivity)
$unoptimized_count = max( 0, $total_images - $optimized_count - $error_count );
// WebP stats
$unconverted_count = static::get_unconverted_count( 'webp' );
if ( $unconverted_count < 0 ) {
$unconverted_count = 0;
}
$converted_count = static::get_converted_count( 'webp' );
if ( $converted_count < 0 ) {
$converted_count = 0;
}
$total_count = $converted_count + $unconverted_count;
$webp_percent_diff_line = 0;
if ( $total_count ) {
$webp_percent_diff_line = round( $converted_count / $total_count * 100, 1 );
}
// AVIF stats
$avif_unconverted_count = static::get_unconverted_count( 'avif' );
if ( $avif_unconverted_count < 0 ) {
$avif_unconverted_count = 0;
}
$avif_converted_count = static::get_converted_count( 'avif' );
if ( $avif_converted_count < 0 ) {
$avif_converted_count = 0;
}
$avif_total_count = $avif_converted_count + $avif_unconverted_count;
$avif_percent_diff_line = 0;
if ( $avif_total_count ) {
$avif_percent_diff_line = round( $avif_converted_count / $avif_total_count * 100, 1 );
}
$percent_diff = 0;
$percent_diff_line = 100;
if ( $optimized_size && $original_size ) {
$percent_diff = round( ( $original_size - $optimized_size ) * 100 / $original_size, 1 );
$percent_diff_line = round( $optimized_size * 100 / $original_size, 0 );
}
$optimized_images_percent = 0;
if ( $total_images > 0 ) {
$optimized_images_percent = floor( $optimized_count * 100 / $total_images );
}
$processor = WIO_OptimizationTools::getImageProcessor();
$data = [
'original' => $total_images,
'optimized' => $optimized_count,
'converted' => $converted_count,
'optimized_percent' => $optimized_images_percent,
'percent_line' => $percent_diff_line,
'webp_percent_line' => $webp_percent_diff_line,
'unoptimized' => $unoptimized_count,
'unconverted' => $unconverted_count,
'optimized_size' => $optimized_size,
'webp_optimized_size' => $webp_optimized_size,
'original_size' => $original_size,
'save_size_percent' => $percent_diff,
'error' => $error_count,
'webp_error' => $webp_error_count,
// AVIF stats
'avif_converted' => $avif_converted_count,
'avif_unconverted' => $avif_unconverted_count,
'avif_percent_line' => $avif_percent_diff_line,
'avif_error' => $avif_error_count,
'avif_optimized_size' => $avif_optimized_size,
];
if ( $processor->has_quota_limit() ) {
$data['quota_limit'] = $processor->get_quota_limit();
}
return $data;
}
/**
* Count of non-optimized images
* Учитывает базовую оптимизацию и конвертацию форматов (WebP/AVIF)
* Accounts for basic optimization and format conversion (WebP/AVIF)
*
* An image is "unoptimized" if it's missing ANY required conversion:
* - Basic optimization (attachment) is always required
* - WebP conversion is required if WebP is enabled
* - AVIF conversion is required if AVIF is enabled
*
* @return int
* @since 1.3.6
*/
public static function get_unoptimized_count() {
return WRIO_Image_Query::get_instance()->count_unoptimized();
}
/**
* Count of non-converted images
*
* @param string $format Target format: 'webp' or 'avif'. Default 'webp'.
*
* @return int
*
* @since 1.5.3
*/
public static function get_unconverted_count( $format = 'webp' ) {
global $wpdb;
$db_table = RIO_Process_Queue::table_name();
$allowed_formats_sql = wrio_get_allowed_formats( true );
// Validate format
if ( ! in_array( $format, [ 'webp', 'avif' ], true ) ) {
$format = 'webp';
}
$sql = $wpdb->prepare(
"SELECT DISTINCT count(posts.ID)
FROM {$wpdb->posts} AS posts
WHERE posts.post_type = 'attachment'
AND posts.post_status = 'inherit'
AND posts.post_mime_type IN ( {$allowed_formats_sql} )
AND posts.ID NOT IN(SELECT object_id FROM {$db_table} AS rio WHERE rio.item_type = %s GROUP BY object_id)",
$format
);
$total_images = $wpdb->get_var( $sql );
return (int) $total_images;
}
/**
* non-converted images
*
* @param string $format Target format: 'webp' or 'avif'. Default 'webp'.
*
* @return array
*
* @since 1.5.3
*/
public static function get_unconverted_images( $format = 'webp' ) {
global $wpdb;
$db_table = RIO_Process_Queue::table_name();
$allowed_formats_sql = wrio_get_allowed_formats( true );
// Validate format
if ( ! in_array( $format, [ 'webp', 'avif' ], true ) ) {
$format = 'webp';
}
$sql = $wpdb->prepare(
"SELECT DISTINCT posts.ID
FROM {$wpdb->posts} AS posts
WHERE posts.post_type = 'attachment'
AND posts.post_status = 'inherit'
AND posts.post_mime_type IN ( {$allowed_formats_sql} )
AND posts.ID NOT IN(SELECT object_id FROM {$db_table} AS rio WHERE rio.item_type = %s GROUP BY object_id)",
$format
);
$images = $wpdb->get_col( $sql );
return is_array( $images ) ? $images : [];
}
/**
* Count of converted images
*
* @return int
*
* @since 1.5.3
*/
public static function get_converted_count( $format = 'webp' ) {
global $wpdb;
$db_table = RIO_Process_Queue::table_name();
$allowed_formats_sql = wrio_get_allowed_formats( true );
// Validate format
if ( ! in_array( $format, [ 'webp', 'avif' ], true ) ) {
$format = 'webp';
}
$sql = $wpdb->prepare(
"SELECT DISTINCT count(posts.ID)
FROM {$wpdb->posts} AS posts
WHERE posts.post_type = 'attachment'
AND posts.post_status = 'inherit'
AND posts.post_mime_type IN ( {$allowed_formats_sql} )
AND posts.ID IN(SELECT object_id FROM {$db_table} AS rio WHERE rio.item_type = %s GROUP BY object_id)",
$format
);
$total_images = $wpdb->get_var( $sql );
return (int) $total_images;
}
/**
* Возвращает результат последних оптимизаций изображений
*
* @param int $limit By default - 100. If limit=0, then no limit
*
* @return array {
* Параметры
* @type string $id id
* @type string $file_name Имя файла
* @type string $url URL
* @type string $thumbnail_url URL превьюшки
* @type string $optimized_size Размер после оптимизации
* @type string $thumbnails_count Сколько превьюшек оптимизировано
* @type string $total_saving Процент оптимизации главного файла и превьюшек
* }
*/
public function get_last_optimized_images( $limit = 100 ) {
global $wpdb;
$db_table = RIO_Process_Queue::table_name();
$limit = max( 0, (int) $limit );
$sql = $wpdb->prepare(
"SELECT object_id FROM {$db_table}
WHERE result_status IN (%s, %s)
ORDER BY id DESC
LIMIT %d;",
RIO_Process_Queue::STATUS_SUCCESS,
RIO_Process_Queue::STATUS_ERROR,
$limit
);
$optimized_images_logs = $wpdb->get_results( $sql, ARRAY_A );
$optimized_attachment_ids = [];
foreach ( $optimized_images_logs as $log ) {
$optimized_attachment_ids[] = $log['object_id'];
}
$optimized_attachment_ids = array_unique( $optimized_attachment_ids );
$optimized_attachment = [];
foreach ( $optimized_attachment_ids as $attachment_id ) {
$log_data = $this->get_last_optimized_image( $attachment_id );
if ( ! empty( $log_data ) ) {
$optimized_attachment[] = $log_data[0];
}
}
return $optimized_attachment;
}
/**
* Get the last optimized image record for a specific attachment.
* Uses the same data source as get_last_optimized_images() for consistency.
*
* @param int $attachment_id Attachment ID.
*
* @return array<int, array<string, mixed>>
* @since 1.3.9
*/
public function get_last_optimized_image( $attachment_id ) {
$info = WRIO_Media_Library::get_instance()->calculateMediaLibraryParams( $attachment_id );
$best_optimized_size = ! empty( $info['optimized_size'] ) ? $info['optimized_size'] : 0;
if ( ! empty( $info['webp_size'] ) ) {
$best_optimized_size = min( $best_optimized_size, $info['webp_size'] );
}
if ( ! empty( $info['avif_size'] ) ) {
$best_optimized_size = min( $best_optimized_size, $info['avif_size'] );
}
$original_size = ! empty( $info['original_size'] ) ? $info['original_size'] : 0;
$best_optimized_size = min( $best_optimized_size, $original_size );
$log = [
'id' => $attachment_id,
'file_name' => $info['original_name'],
'url' => $info['edit_url'],
'thumbnail_url' => $info['original_url'],
'original_size' => size_format( $original_size, 2 ),
'optimized_size' => size_format( $best_optimized_size, 2 ),
'thumbnails_count' => ! empty( $info['thumbnails_optimized'] ) ? $info['thumbnails_optimized'] : 0,
'total_saving' => ! empty( $info['diff_percent_all'] ) ? $info['diff_percent_all'] . '%' : '0%',
];
// Check errors.
if ( ! empty( $info['error_msg'] ) ) {
$log['type'] = 'error';
$log['error_msg'] = $info['error_msg'];
}
return [ $log ];
}
/**
* @param int $object_id
* @param string $format Format type: 'webp' or 'avif'. Default 'webp'.
*
* @since 1.3.9
*/
public function get_last_converted_image( $object_id, $format = 'webp' ) {
global $wpdb;
// Validate format
if ( ! in_array( $format, [ 'webp', 'avif' ], true ) ) {
$format = 'webp';
}
$items = [];
$db_table = RIO_Process_Queue::table_name();
$sql = $wpdb->prepare(
"SELECT * FROM {$db_table}
WHERE object_id = %d AND item_type = %s AND result_status IN (%s, %s)
ORDER BY original_size DESC
LIMIT 1;",
(int) $object_id,
$format,
RIO_Process_Queue::STATUS_SUCCESS,
RIO_Process_Queue::STATUS_ERROR
);
$model = $wpdb->get_row( $sql, ARRAY_A );
if ( ! empty( $model ) ) {
$items[] = $this->format_webp_for_log( new RIO_Process_Queue( $model ) );
}
return $items;
}
/**
* Format a queue record for the optimization log display.
* Works universally for attachment, webp, and avif item types.
*
* @param RIO_Process_Queue $queue_model Queue model instance.
*
* @return array<string, mixed>
* @throws \Exception If invalid model provided.
* @since 1.3.9
*/
protected function format_for_log( $queue_model ) {
if ( ! $queue_model instanceof RIO_Process_Queue ) {
throw new Exception( 'Variable $queue_model must be an instance of RIO_Process_Queue!' );
}
$extra_data = $queue_model->get_extra_data();
$object_id = $queue_model->get_object_id();
$item_type = $queue_model->item_type;
$original_size = $queue_model->get_original_size();
$final_size = min( $original_size, $queue_model->get_final_size() );
$formatted_data = [
'id' => $queue_model->get_id(),
'attachment_id' => $object_id,
'item_type' => $item_type,
'url' => admin_url( sprintf( 'post.php?post=%d&action=edit', $object_id ) ),
'original_url' => null,
'thumbnail_url' => null,
'file_name' => null,
'original_size' => size_format( $original_size, 2 ),
'original_size_bytes' => $original_size,
'optimized_size' => size_format( $final_size, 2 ),
'type' => 'success',
'webp_size' => null,
'avif_size' => null,
'original_saving' => 0,
'thumbnails_count' => 0,
'total_saving' => 0,
'final_size_bytes' => $final_size,
'converted_from' => null,
];
// Get URLs and file name based on item type
if ( in_array( $item_type, [ 'webp', 'avif' ], true ) && $extra_data instanceof RIOP_WebP_Extra_Data ) {
// For webp/avif, use source_src from extra_data
$original_url = $extra_data->get_source_src();
$formatted_data['original_url'] = $original_url;
$formatted_data['file_name'] = wp_basename( $original_url );
$formatted_data['thumbnail_url'] = $original_url;
$formatted_data['converted_from'] = $extra_data->get_converted_from_size();
// Set the appropriate size field
if ( 'avif' === $item_type ) {
$formatted_data['avif_size'] = size_format( $final_size, 2 );
} else {
$formatted_data['webp_size'] = size_format( $final_size, 2 );
}
if ( $extra_data->get_thumbnails_count() ) {
$formatted_data['thumbnails_count'] = $extra_data->get_thumbnails_count();
}
} else {
// For attachment type, use WordPress attachment metadata
$upload_dir = wp_upload_dir();
$attachment_meta = wp_get_attachment_metadata( $object_id );
if ( ! empty( $attachment_meta ) ) {
$image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
$formatted_data['original_url'] = $image_url;
$formatted_data['file_name'] = wp_basename( $attachment_meta['file'] );
$formatted_data['thumbnail_url'] = $image_url;
if ( isset( $attachment_meta['sizes']['thumbnail'] ) ) {
$image_basename = wp_basename( $image_url );
$formatted_data['thumbnail_url'] = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
}
if ( ! empty( $extra_data ) && method_exists( $extra_data, 'get_thumbnails_count' ) ) {
$formatted_data['thumbnails_count'] = $extra_data->get_thumbnails_count();
}
} else {
// Fallback to post guid
$attachment = get_post( $object_id );
if ( ! empty( $attachment ) ) {
$formatted_data['original_url'] = $attachment->guid;
$formatted_data['thumbnail_url'] = $attachment->guid;
$formatted_data['file_name'] = wp_basename( $attachment->guid );
}
}
}
// Calculate total saving directly from the row's original_size and final_size
if ( is_numeric( $original_size ) && $original_size > 0 && is_numeric( $final_size ) ) {
$total_saving = ( $original_size - $final_size ) * 100 / $original_size;
$total_saving = max( 0, min( $total_saving, 100 ) );
$formatted_data['total_saving'] = round( $total_saving, 2 ) . '%';
}
// Handle errors
if ( RIO_Process_Queue::STATUS_ERROR === $queue_model->get_result_status() ) {
$error_message = null;
if ( ! empty( $extra_data ) && method_exists( $extra_data, 'get_error_msg' ) ) {
$error_message = $extra_data->get_error_msg();
}
$formatted_data['type'] = 'error';
$formatted_data['error_msg'] = ! empty( $error_message ) ? $error_message : __( 'Unknown error', 'robin-image-optimizer' );
}
return $formatted_data;
}
/**
* Format WebP/AVIF record for log display.
*
* @param RIO_Process_Queue $queue_model Queue model instance.
*
* @return array<string, mixed>
* @throws \Exception If invalid model provided.
* @since 1.5.3
*/
protected function format_webp_for_log( $queue_model ) {
if ( ! $queue_model instanceof RIO_Process_Queue ) {
throw new Exception( 'Variable $queue_model must be an instance of RIO_Process_Queue!' );
}
/**
* @var RIO_Attachment_Extra_Data $extra_data
*/
$extra_data = $queue_model->get_extra_data();
$default_formated_data = [
'id' => $queue_model->get_id(),
'attachment_id' => $queue_model->get_object_id(),
'item_type' => $queue_model->item_type,
'url' => admin_url( sprintf( 'post.php?post=%d&action=edit', $queue_model->get_object_id() ) ),
'original_url' => null,
'thumbnail_url' => null,
'file_name' => null,
'original_size' => 0,
'optimized_size' => 0,
'type' => 'success',
'webp_size' => null,
'avif_size' => null,
'original_saving' => 0,
'thumbnails_count' => 0,
'total_saving' => 0,
];
$upload_dir = wp_upload_dir();
$attachment_meta = wp_get_attachment_metadata( $queue_model->get_object_id() );
$formated_data = [];
if ( ! empty( $attachment_meta ) ) {
$image_url = trailingslashit( $upload_dir['baseurl'] ) . $attachment_meta['file'];
$thumbnail_url = $image_url;
if ( isset( $attachment_meta['sizes']['thumbnail'] ) ) {
$image_basename = wp_basename( $image_url );
$thumbnail_url = str_replace( $image_basename, $attachment_meta['sizes']['thumbnail']['file'], $image_url );
}
// Get the extension from the item type (webp or avif)
$converted_extension = '.' . $queue_model->item_type;
// Determine the field name based on format type
$size_field_name = 'avif' === $queue_model->item_type ? 'avif_size' : 'webp_size';
$formated_data = wp_parse_args(
[
'original_url' => $image_url . $converted_extension,
'thumbnail_url' => $thumbnail_url,
'file_name' => wp_basename( $attachment_meta['file'] ) . $converted_extension,
'original_size' => size_format( $queue_model->get_original_size(), 2 ),
'optimized_size' => '-',
$size_field_name => size_format( $queue_model->get_final_size(), 2 ),
],
$default_formated_data
);
$main_file = trailingslashit( $upload_dir['basedir'] ) . $attachment_meta['file'];
// An extra data may be empty after a failed migration or an unknown error.
if ( ! empty( $extra_data ) ) {
$original_main_size = $extra_data->get_original_main_size();
if ( $original_main_size ) {
$current_main_size = $this->get_file_size( $main_file );
$original_saving = ( $original_main_size - $current_main_size ) * 100 / $original_main_size;
$formated_data['original_saving'] = round( $original_saving ) . '%';
}
$formated_data['thumbnails_count'] = $extra_data->get_thumbnails_count();
}
if ( $queue_model->get_original_size() ) {
$total_saving = ( $queue_model->get_original_size() - $queue_model->get_final_size() ) * 100 / $queue_model->get_original_size();
$formated_data['total_saving'] = round( $total_saving, 2 ) . '%';
}
} else {
$attachment = get_post( $queue_model->get_object_id() );
if ( ! empty( $attachment ) ) {
$formated_data = [
'original_url' => $attachment->guid,
'thumbnail_url' => $attachment->guid,
'file_name' => wp_basename( $attachment->guid ),
];
}
$formated_data = wp_parse_args( $formated_data, $default_formated_data );
}
// We collect information about errors
if ( RIO_Process_Queue::STATUS_ERROR === $queue_model->get_result_status() ) {
$error_message = null;
if ( ! empty( $extra_data ) && method_exists( $extra_data, 'get_error_msg' ) ) {
$error_message = $extra_data->get_error_msg();
}
$formated_data['type'] = 'error';
$formated_data['error_msg'] = ! empty( $error_message ) ? $error_message : __( 'Unknown error', 'robin-image-optimizer' );
return $formated_data;
}
return $formated_data;
}
/**
* Возвращает общий процент оптимизированных изображений
*
* @return int общий процент оптимизации
*/
public function getOptimizedPercent() {
if ( isset( $this->statistic['optimized_percent'] ) ) {
return $this->statistic['optimized_percent'];
}
return 0;
}
/**
* Пересчёт размера файла в байтах на человекопонятный вид
*
* Пример: вводим 67894 байт, получаем 67.8 KB
* Пример: вводим 6789477 байт, получаем 6.7 MB
*
* @param int $size размер файла в байтах
*
* @return string
*/
public function convertToReadableSize( $size ) {
return wrio_convert_bytes( $size );
}
/**
* Get the main/full size conversion record for an attachment
*
* @param int $object_id Attachment ID
* @param string $format 'webp' or 'avif'
*
* @return RIO_Process_Queue|null
*/
protected function get_conversion_record( $object_id, $format ) {
global $wpdb;
$db_table = RIO_Process_Queue::table_name();
// Query for conversion records with this attachment ID and format
$sql = $wpdb->prepare(
"SELECT * FROM {$db_table}
WHERE object_id = %d
AND item_type = %s
AND result_status = %s
ORDER BY original_size DESC",
$object_id,
$format,
RIO_Process_Queue::STATUS_SUCCESS
);
$models = $wpdb->get_results( $sql, ARRAY_A );
if ( empty( $models ) ) {
return null;
}
// Find the record with converted_from_size = 'original' in extra_data
foreach ( $models as $model ) {
if ( ! empty( $model['extra_data'] ) ) {
$extra_data = json_decode( $model['extra_data'], true );
if ( isset( $extra_data['converted_from_size'] ) && $extra_data['converted_from_size'] === 'original' ) {
return new RIO_Process_Queue( $model );
}
}
}
// Fallback: return the largest one (highest original_size) which is likely the main image
return new RIO_Process_Queue( $models[0] );
}
}