PluginProbe ʕ •ᴥ•ʔ
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents / 4.5.1
EmbedPress – PDF Embedder, 3D PDF FlipBook, Google Reviews, YouTube Videos, Upload & Embed PDF documents v4.5.1
4.6.0 4.5.6 4.5.5 4.5.4 4.5.3 4.5.2 trunk 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.5.0 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 2.0.0 2.0.1 2.0.2 2.0.3 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.2.0 2.2.1 2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.4.0 2.4.1 2.5.0 2.5.1 2.5.2 2.5.3 2.5.4 2.5.5 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.1.0 3.1.1 3.1.2 3.1.3 3.2.0 3.2.1 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.4.0 3.4.1 3.4.2 3.4.3 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.6.5 3.6.6 3.6.7 3.6.8 3.7.0 3.7.1 3.7.2 3.7.3 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.9.0 3.9.1 3.9.10 3.9.11 3.9.12 3.9.13 3.9.14 3.9.15 3.9.16 3.9.17 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9 4.0.0 4.0.1 4.0.10 4.0.11 4.0.12 4.0.13 4.0.14 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.0.9 4.1.0 4.1.1 4.1.10 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.1.7 4.1.8 4.1.9 4.2.0 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.8 4.2.9 4.3.0 4.3.1 4.4.0 4.4.1 4.4.10 4.4.11 4.4.2 4.4.3 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5.0 4.5.1
embedpress / EmbedPress / Includes / Classes / Pdf_Thumbnail_Handler.php
embedpress / EmbedPress / Includes / Classes Last commit date
Analytics 2 months ago Database 5 months 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 2 months ago Extend_CustomPlayer_Controls.php 1 year ago Extend_Elementor_Controls.php 1 year ago FeatureNoticeManager.php 8 months ago FeatureNotices.php 8 months ago Feature_Enhancer.php 2 months ago Helper.php 2 months ago Pdf_Thumbnail_Handler.php 2 months ago PermalinkHelper.php 10 months ago README_FEATURE_NOTICES.md 8 months 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