Analytics
2 weeks ago
Database
2 months ago
DynamicFieldResolver.php
1 month ago
Elementor_Enhancer.php
6 months ago
EmbedPress_Core_Installer.php
6 years ago
EmbedPress_Notice.php
3 months ago
EmbedPress_Plugin_Usage_Tracker.php
1 month ago
Extend_CustomPlayer_Controls.php
2 months ago
Extend_Elementor_Controls.php
1 year ago
FeatureNoticeManager.php
4 days ago
FeatureNotices.php
4 days ago
FeaturePreviewModal.php
4 days ago
Feature_Enhancer.php
1 month ago
GoogleReviewsAdminPage.php
4 days ago
GoogleReviewsApify.php
4 days ago
GoogleReviewsManaged.php
4 days ago
GoogleReviewsRenderer.php
4 days ago
GoogleReviewsRestController.php
4 days ago
GoogleReviewsStore.php
4 days ago
Helper.php
4 days ago
Pdf_Thumbnail_Handler.php
2 months ago
PermalinkHelper.php
10 months ago
View_Count_Display.php
2 weeks ago
Pdf_Thumbnail_Handler.php
221 lines
| 1 | <?php |
| 2 | |
| 3 | namespace EmbedPress\Includes\Classes; |
| 4 | |
| 5 | (defined('ABSPATH')) or die("No direct script access allowed."); |
| 6 | |
| 7 | /** |
| 8 | * Handles PDF thumbnail generation and upload via AJAX. |
| 9 | * Extracted from Embedpress_Pdf_Gallery to avoid Elementor dependency. |
| 10 | */ |
| 11 | class Pdf_Thumbnail_Handler |
| 12 | { |
| 13 | /** |
| 14 | * AJAX handler: generate a thumbnail for a PDF attachment. |
| 15 | */ |
| 16 | public static function ajax_generate_pdf_thumbnail() |
| 17 | { |
| 18 | check_ajax_referer('ep_pdf_gallery_nonce', 'nonce'); |
| 19 | |
| 20 | if (!current_user_can('upload_files')) { |
| 21 | wp_send_json_error(['message' => 'Insufficient permissions']); |
| 22 | } |
| 23 | |
| 24 | $attachment_id = isset($_POST['attachment_id']) ? intval($_POST['attachment_id']) : 0; |
| 25 | if (!$attachment_id) { |
| 26 | wp_send_json_error(['message' => 'Invalid attachment ID']); |
| 27 | } |
| 28 | |
| 29 | // Verify it's a PDF |
| 30 | if (get_post_mime_type($attachment_id) !== 'application/pdf') { |
| 31 | wp_send_json_error(['message' => 'Not a PDF file']); |
| 32 | } |
| 33 | |
| 34 | // Check cached thumbnail first (stored as post meta on the PDF attachment) |
| 35 | $cached_thumb_id = get_post_meta($attachment_id, '_ep_pdf_thumbnail_id', true); |
| 36 | if ($cached_thumb_id) { |
| 37 | $cached_url = wp_get_attachment_url($cached_thumb_id); |
| 38 | if ($cached_url) { |
| 39 | wp_send_json_success([ |
| 40 | 'url' => $cached_url, |
| 41 | 'id' => (int) $cached_thumb_id, |
| 42 | ]); |
| 43 | return; |
| 44 | } |
| 45 | // Cached thumbnail attachment no longer exists, clear stale meta |
| 46 | delete_post_meta($attachment_id, '_ep_pdf_thumbnail_id'); |
| 47 | } |
| 48 | |
| 49 | // Method 1: WordPress already generated a preview during upload |
| 50 | $thumb_src = wp_get_attachment_image_src($attachment_id, 'medium'); |
| 51 | if ($thumb_src && !empty($thumb_src[0])) { |
| 52 | wp_send_json_success([ |
| 53 | 'url' => $thumb_src[0], |
| 54 | 'id' => $attachment_id, |
| 55 | ]); |
| 56 | return; |
| 57 | } |
| 58 | |
| 59 | // Method 2: Try regenerating attachment metadata (triggers WP PDF preview) |
| 60 | $file_path = get_attached_file($attachment_id); |
| 61 | if ($file_path && file_exists($file_path)) { |
| 62 | require_once ABSPATH . 'wp-admin/includes/image.php'; |
| 63 | $metadata = wp_generate_attachment_metadata($attachment_id, $file_path); |
| 64 | if (!empty($metadata)) { |
| 65 | wp_update_attachment_metadata($attachment_id, $metadata); |
| 66 | $thumb_src = wp_get_attachment_image_src($attachment_id, 'medium'); |
| 67 | if ($thumb_src && !empty($thumb_src[0])) { |
| 68 | wp_send_json_success([ |
| 69 | 'url' => $thumb_src[0], |
| 70 | 'id' => $attachment_id, |
| 71 | ]); |
| 72 | return; |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | // Method 3: Direct Imagick rendering as last resort |
| 78 | if (class_exists('Imagick') && $file_path && file_exists($file_path)) { |
| 79 | try { |
| 80 | $imagick = new \Imagick(); |
| 81 | $imagick->setResolution(200, 200); |
| 82 | $imagick->readImage($file_path . '[0]'); |
| 83 | $imagick->setImageFormat('png'); |
| 84 | $imagick->setImageAlphaChannel(\Imagick::ALPHACHANNEL_REMOVE); |
| 85 | $imagick->setImageBackgroundColor('white'); |
| 86 | $imagick = $imagick->flattenImages(); |
| 87 | $imagick->thumbnailImage(800, 0); |
| 88 | |
| 89 | $upload_dir = wp_upload_dir(); |
| 90 | $base_name = pathinfo(basename($file_path), PATHINFO_FILENAME); |
| 91 | $thumb_file = 'pdf-thumb-' . sanitize_file_name($base_name) . '.png'; |
| 92 | $thumb_path = trailingslashit($upload_dir['path']) . $thumb_file; |
| 93 | |
| 94 | $imagick->writeImage($thumb_path); |
| 95 | $imagick->destroy(); |
| 96 | |
| 97 | $attachment = [ |
| 98 | 'post_mime_type' => 'image/png', |
| 99 | 'post_title' => sanitize_file_name($base_name) . ' - PDF Thumbnail', |
| 100 | 'post_content' => '', |
| 101 | 'post_status' => 'inherit', |
| 102 | ]; |
| 103 | |
| 104 | $thumb_id = wp_insert_attachment($attachment, $thumb_path); |
| 105 | if (!is_wp_error($thumb_id)) { |
| 106 | $meta = wp_generate_attachment_metadata($thumb_id, $thumb_path); |
| 107 | wp_update_attachment_metadata($thumb_id, $meta); |
| 108 | |
| 109 | // Cache thumbnail ID on the PDF attachment for future lookups |
| 110 | update_post_meta($attachment_id, '_ep_pdf_thumbnail_id', $thumb_id); |
| 111 | |
| 112 | wp_send_json_success([ |
| 113 | 'url' => wp_get_attachment_url($thumb_id), |
| 114 | 'id' => $thumb_id, |
| 115 | ]); |
| 116 | return; |
| 117 | } |
| 118 | } catch (\Exception $e) { |
| 119 | // Imagick failed, fall through |
| 120 | } |
| 121 | } |
| 122 | |
| 123 | wp_send_json_error(['message' => 'Could not generate thumbnail']); |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * AJAX handler: receive a client-rendered thumbnail (base64 PNG) and save as WP attachment. |
| 128 | */ |
| 129 | public static function ajax_upload_pdf_thumbnail() |
| 130 | { |
| 131 | check_ajax_referer('ep_pdf_gallery_nonce', 'nonce'); |
| 132 | |
| 133 | if (!current_user_can('upload_files')) { |
| 134 | wp_send_json_error(['message' => 'Insufficient permissions']); |
| 135 | } |
| 136 | |
| 137 | $image_data = isset($_POST['image_data']) ? $_POST['image_data'] : ''; |
| 138 | $pdf_url = isset($_POST['pdf_url']) ? esc_url_raw($_POST['pdf_url']) : ''; |
| 139 | $file_name = isset($_POST['file_name']) ? sanitize_file_name($_POST['file_name']) : ''; |
| 140 | $attachment_id = isset($_POST['attachment_id']) ? intval($_POST['attachment_id']) : 0; |
| 141 | |
| 142 | if (empty($image_data) || empty($pdf_url)) { |
| 143 | wp_send_json_error(['message' => 'Missing data']); |
| 144 | } |
| 145 | |
| 146 | // Check cached thumbnail for this PDF attachment |
| 147 | if ($attachment_id) { |
| 148 | $cached_thumb_id = get_post_meta($attachment_id, '_ep_pdf_thumbnail_id', true); |
| 149 | if ($cached_thumb_id) { |
| 150 | $cached_url = wp_get_attachment_url($cached_thumb_id); |
| 151 | if ($cached_url) { |
| 152 | wp_send_json_success([ |
| 153 | 'url' => $cached_url, |
| 154 | 'id' => (int) $cached_thumb_id, |
| 155 | ]); |
| 156 | return; |
| 157 | } |
| 158 | // Stale meta, clear it |
| 159 | delete_post_meta($attachment_id, '_ep_pdf_thumbnail_id'); |
| 160 | } |
| 161 | } |
| 162 | |
| 163 | // Strip data-URI prefix |
| 164 | $image_data = preg_replace('/^data:image\/\w+;base64,/', '', $image_data); |
| 165 | $decoded = base64_decode($image_data); |
| 166 | if (!$decoded || strlen($decoded) < 8) { |
| 167 | wp_send_json_error(['message' => 'Invalid image data']); |
| 168 | } |
| 169 | |
| 170 | // Detect MIME from raw bytes |
| 171 | $finfo = new \finfo(FILEINFO_MIME_TYPE); |
| 172 | $mime = $finfo->buffer($decoded); |
| 173 | if ($mime !== 'image/png' && $mime !== 'image/jpeg') { |
| 174 | wp_send_json_error(['message' => 'Invalid image format']); |
| 175 | } |
| 176 | |
| 177 | $ext = ($mime === 'image/jpeg') ? '.jpg' : '.png'; |
| 178 | $upload_dir = wp_upload_dir(); |
| 179 | $base_name = $file_name ? pathinfo($file_name, PATHINFO_FILENAME) : md5($pdf_url); |
| 180 | $thumb_file = 'pdf-thumb-' . sanitize_file_name($base_name) . $ext; |
| 181 | $thumb_path = trailingslashit($upload_dir['path']) . $thumb_file; |
| 182 | |
| 183 | // Avoid overwriting existing files |
| 184 | $counter = 0; |
| 185 | while (file_exists($thumb_path)) { |
| 186 | $counter++; |
| 187 | $thumb_file = 'pdf-thumb-' . sanitize_file_name($base_name) . '-' . $counter . $ext; |
| 188 | $thumb_path = trailingslashit($upload_dir['path']) . $thumb_file; |
| 189 | } |
| 190 | |
| 191 | // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents |
| 192 | file_put_contents($thumb_path, $decoded); |
| 193 | |
| 194 | $attachment = [ |
| 195 | 'post_mime_type' => $mime, |
| 196 | 'post_title' => sanitize_file_name($base_name) . ' - PDF Thumbnail', |
| 197 | 'post_content' => '', |
| 198 | 'post_status' => 'inherit', |
| 199 | ]; |
| 200 | |
| 201 | $thumb_id = wp_insert_attachment($attachment, $thumb_path); |
| 202 | if (is_wp_error($thumb_id)) { |
| 203 | wp_send_json_error(['message' => 'Failed to create attachment']); |
| 204 | } |
| 205 | |
| 206 | require_once ABSPATH . 'wp-admin/includes/image.php'; |
| 207 | $meta = wp_generate_attachment_metadata($thumb_id, $thumb_path); |
| 208 | wp_update_attachment_metadata($thumb_id, $meta); |
| 209 | |
| 210 | // Cache thumbnail ID on the PDF attachment for future lookups |
| 211 | if ($attachment_id) { |
| 212 | update_post_meta($attachment_id, '_ep_pdf_thumbnail_id', $thumb_id); |
| 213 | } |
| 214 | |
| 215 | wp_send_json_success([ |
| 216 | 'url' => wp_get_attachment_url($thumb_id), |
| 217 | 'id' => $thumb_id, |
| 218 | ]); |
| 219 | } |
| 220 | } |
| 221 |