wp_create_nonce('hithto_process_webp_queue_nonce'),
]);
}
public static function ajax_process_queue()
{
check_ajax_referer('hithto_process_webp_queue_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error('Unauthorized');
}
$size_instance = Size::get_instance();
$size_instance->process_image_queue();
$queue_status = $size_instance->get_queue_status();
wp_send_json_success(['remaining' => $queue_status['count']]);
}
public static function add_admin_menu()
{
add_management_page(
'WebP Optimization Test',
'WebP Test',
'manage_options',
'webp-optimization-test',
[__CLASS__, 'render_test_page']
);
}
public static function render_test_page()
{
// Handle rebuild action
$rebuild_message = '';
if (isset($_POST['rebuild_webp']) && check_admin_referer('rebuild_webp_action', 'rebuild_webp_nonce')) {
$size_instance = Size::get_instance();
$force_rebuild = isset($_POST['force_rebuild']) && $_POST['force_rebuild'] === '1';
$queued_count = $size_instance->rebuild_all_webp_images($force_rebuild);
if ($queued_count > 0) {
$rebuild_message = '
🎨 WebP Optimization Test Results
get_queue_status();
?>
🔄 Rebuild WebP Images
Use this tool to regenerate all WebP images in the background. The process will queue all image attachments and process them via cron.
0): ?>
⏳ Queue Status: images waiting to be processed.
0): ?>
Note: Images are processed in batches every minute via WordPress cron. Large libraries may take some time to complete.
'attachment',
'post_mime_type' => 'image',
'posts_per_page' => 20,
'orderby' => 'date',
'order' => 'DESC'
]);
if (empty($images)) {
echo '
No images found. Please upload some images first.
';
echo '
Go to Media Library
';
return;
}
// Initialize Size class
$size_instance = Size::get_instance();
// Get fly directory
$fly_base_dir = $size_instance->get_fly_dir();
$total_original_size = 0;
$total_webp_size = 0;
$total_png_size = 0;
$webp_count = 0;
$png_count = 0;
$results = [];
foreach ($images as $image) {
$attachment_id = $image->ID;
$original_path = get_attached_file($attachment_id);
if (!file_exists($original_path)) continue;
$extension = strtolower(pathinfo($original_path, PATHINFO_EXTENSION));
if (in_array($extension, ['svg', 'avif', 'heic', 'heif'])) continue;
$original_size = filesize($original_path);
$total_original_size += $original_size;
// Check fly directory for this attachment
$fly_dir = $fly_base_dir . DIRECTORY_SEPARATOR . $attachment_id;
if (!is_dir($fly_dir)) continue;
$files = glob($fly_dir . DIRECTORY_SEPARATOR . '*');
foreach ($files as $file) {
$file_size = filesize($file);
$file_name = basename($file);
$file_ext = pathinfo($file, PATHINFO_EXTENSION);
$is_webp = $file_ext === 'webp';
if ($is_webp) {
$total_webp_size += $file_size;
$webp_count++;
} else {
$total_png_size += $file_size;
$png_count++;
}
// Extract dimensions from filename (format: name-WIDTHxHEIGHT.ext)
preg_match('/(\d+)x(\d+)/', $file_name, $matches);
$width = isset($matches[1]) ? intval($matches[1]) : 0;
$height = isset($matches[2]) ? intval($matches[2]) : 0;
// Determine quality based on width (same logic as code)
$expected_quality = 75;
if ($width >= 1920) {
$expected_quality = 60;
} elseif ($width >= 1280) {
$expected_quality = 65;
} elseif ($width >= 640) {
$expected_quality = 70;
}
$savings = $original_size - $file_size;
$savings_percent = $original_size > 0 ? ($savings / $original_size) * 100 : 0;
$results[] = [
'attachment_id' => $attachment_id,
'filename' => $file_name,
'type' => $is_webp ? 'WebP' : strtoupper($file_ext),
'dimensions' => $width . 'x' . $height,
'width' => $width,
'size' => $file_size,
'expected_quality' => $expected_quality,
'savings' => $savings,
'savings_percent' => $savings_percent,
'is_webp' => $is_webp
];
}
}
// Calculate overall stats
$total_savings = $total_original_size - $total_webp_size;
$savings_percent = $total_original_size > 0 ? ($total_savings / $total_original_size) * 100 : 0;
$avg_webp_size = $webp_count > 0 ? $total_webp_size / $webp_count : 0;
$avg_png_size = $png_count > 0 ? $total_png_size / $png_count : 0;
?>
📊 Overall Statistics
0 && $avg_png_size > 0): ?>
Average file size:
WebP: |
PNG/JPG: |
Difference: % smaller
🔍 WebP Support Check
| imagewebp function |
|
| GD Version |
|
| WebP Support |
|
| Fly Images Directory |
|
'attachment','post_mime_type'=>'image','posts_per_page'=>1,'fields'=>'ids']);
$test_file = !empty($test_images) ? get_attached_file($test_images[0]) : null;
$editor = $test_file ? wp_get_image_editor($test_file) : null;
?>
| WP Image Editor class |
get_error_message() : 'no image found'))); ?> |
| supports_mime_type(image/webp) |
supports_mime_type('image/webp')) ? '✅ Yes' : '❌ No'; ?> |
| WP_Image_Editor_GD::supports_mime_type(image/webp) |
|
📝 Adaptive Quality Settings
| Image Width |
WebP Quality |
Reason |
Files Using This Quality |
0,
65 => 0,
70 => 0,
75 => 0
];
foreach ($results as $result) {
if ($result['is_webp'] && isset($quality_counts[$result['expected_quality']])) {
$quality_counts[$result['expected_quality']]++;
}
}
?>
| ≥ 1920px |
60% |
Very large images tolerate higher compression |
files |
| ≥ 1280px |
65% |
Large images, good balance |
files |
| ≥ 640px |
70% |
Medium images |
files |
| < 640px |
75% |
Small images need better quality |
files |
get_webp_logs();
$log_counts = ['success' => 0, 'error' => 0, 'warning' => 0, 'info' => 0];
foreach ($webp_logs as $log) {
if (isset($log_counts[$log['level']])) {
$log_counts[$log['level']]++;
}
}
?>
📋 Conversion Logs
No conversion logs yet. Trigger a rebuild to generate logs.
Filter:
| Time |
Level |
Attach. ID |
Size |
Message |
|
|
' . intval($log['attachment_id']) . '' : '-'; ?> |
|
|
🚀 Next Steps
- ✅ Upload a new image to test the optimization in real-time
- ✅ Check file sizes - WebP should be 20-35% smaller than originals
- ✅ Verify no PNG/JPG fallbacks are created (unless WebP is unsupported)
- ✅ Monitor cron job
hithto_images_process_queue for queue processing
Upload New Image
View Tools
Refresh Test