PluginProbe
Plus WebP or AVIF / 5.11
Plus WebP or AVIF v5.11
5.21 5.20 5.12 5.11 trunk 1.00 1.01 1.02 1.03 1.04 1.05 1.06 1.07 1.08 1.09 1.10 1.11 1.12 1.13 2.00 2.01 2.02 2.03 2.04 2.05 All 47 releases
plus-webp / lib / class-pluswebp.php

class-pluswebp.php in Plus WebP or AVIF 5.11, at lib/class-pluswebp.php

552 lines 18.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plus WebP or AVIF
4 *
5 * @package Plus WebP or AVIF
6 * @subpackage PlusWebp Main function
7 /* Copyright (c) 2019- Katsushi Kawamori (email : dodesyoswift312@gmail.com)
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; version 2 of the License.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21
22 if ( ! defined( 'ABSPATH' ) ) {
23 exit;
24 }
25
26 $pluswebp = new PlusWebp();
27
28 /** ==================================================
29 * Class Main function
30 *
31 * @since 1.00
32 */
33 class PlusWebp {
34
35 /** ==================================================
36 * Dir
37 *
38 * @var $upload_dir DIR.
39 */
40 private $upload_dir;
41
42 /** ==================================================
43 * URL
44 *
45 * @var $upload_url URL.
46 */
47 private $upload_url;
48
49 /** ==================================================
50 * Construct
51 *
52 * @since 1.00
53 */
54 public function __construct() {
55
56 $wp_uploads = wp_upload_dir();
57
58 $upload_dir = wp_normalize_path( $wp_uploads['basedir'] );
59 $upload_url = $wp_uploads['baseurl'];
60 if ( is_ssl() ) {
61 $upload_url = str_replace( 'http:', 'https:', $upload_url );
62 }
63 $this->upload_dir = untrailingslashit( $upload_dir );
64 $this->upload_url = untrailingslashit( $upload_url );
65
66 /* Generate metadata */
67 add_filter( 'wp_generate_attachment_metadata', array( $this, 'generate_webp' ), 10, 2 );
68 /* Original hook */
69 add_filter( 'pluswebp_get_allimages', array( $this, 'get_allimages' ), 10, 2 );
70 add_filter( 'pluswebp_mail_messages', array( $this, 'mail_messages' ), 10, 2 );
71 add_action( 'pluswebp_mail_generate_message', array( $this, 'mail_generate_message' ), 10, 2 );
72
73 /* Raise memory */
74 add_filter( 'pluswebp_memory_limit', array( $this, 'raise_memory_limit' ) );
75 /* webp generation control */
76 add_filter( 'wp_upload_image_mime_transforms', array( $this, 'control_mime_type' ), 10, 2 );
77 }
78
79 /** ==================================================
80 * Webp of AVIF generate
81 *
82 * @param array $metadata metadata.
83 * @param int $attachment_id ID.
84 * @return array $metadata metadata.
85 * @since 1.00
86 */
87 public function generate_webp( $metadata, $attachment_id ) {
88
89 $pluswebp_settings = get_option( 'pluswebp' );
90
91 switch ( $pluswebp_settings['output_mime'] ) {
92 case 'image/webp':
93 $ext = 'webp';
94 break;
95 case 'image/avif':
96 $ext = 'avif';
97 break;
98 default:
99 $ext = 'webp';
100 }
101
102 $mime_type = get_post_mime_type( $attachment_id );
103 if ( in_array( $mime_type, $pluswebp_settings['types'] ) ) {
104 $metadata_webp = $metadata;
105 $file_webp = $this->change_ext( $metadata['file'], $ext, $pluswebp_settings['addext'] );
106 $metadata_webp['file'] = $file_webp;
107 if ( '.' === dirname( $file_webp ) ) {
108 $dir_name_url = '/';
109 $dir_name_path = wp_normalize_path( '/' );
110 } else {
111 $dir_name_url = '/' . dirname( $file_webp ) . '/';
112 $dir_name_path = wp_normalize_path( $dir_name_url );
113 }
114 $url = $this->upload_url . $dir_name_url;
115 $path = $this->upload_dir . $dir_name_path;
116
117 foreach ( (array) $metadata['sizes'] as $key => $value ) {
118 $file_thumb = $value['file'];
119 $file_thumb_webp = $this->change_ext( $file_thumb, $ext, $pluswebp_settings['addext'] );
120 $ret = $this->create_webp( $path . $file_thumb, $mime_type, $path . $file_thumb_webp, $pluswebp_settings['quality'], $pluswebp_settings['output_mime'] );
121 /* $ret -> ignore : Some metadata also has duplicate filenames */
122 $metadata_webp['sizes'][ $key ]['file'] = $file_thumb_webp;
123 $metadata_webp['sizes'][ $key ]['mime-type'] = $pluswebp_settings['output_mime'];
124 $webp_size = filesize( $path . wp_basename( $file_thumb_webp ) );
125 $metadata_webp['sizes'][ $key ]['filesize'] = $webp_size;
126 if ( $pluswebp_settings['replace'] ) {
127 wp_delete_file( $path . $file_thumb );
128 $this->change_db( $url . $file_thumb, $url . $file_thumb_webp );
129 }
130 }
131
132 $org_img_file = null;
133 if ( array_key_exists( 'original_image', $metadata ) && ! empty( $metadata['original_image'] ) ) {
134 $org_img_file = wp_normalize_path( wp_get_original_image_path( $attachment_id, false ) );
135 $org_webp_file = $this->change_ext( $org_img_file, $ext, $pluswebp_settings['addext'] );
136 $ret = $this->create_webp( $org_img_file, $mime_type, $org_webp_file, $pluswebp_settings['quality'], $pluswebp_settings['output_mime'] );
137 if ( $ret ) {
138 $metadata_webp['original_image'] = wp_basename( $org_webp_file );
139 }
140 }
141
142 $ret = $this->create_webp( $this->upload_dir . '/' . $metadata['file'], $mime_type, $path . wp_basename( $file_webp ), $pluswebp_settings['quality'], $pluswebp_settings['output_mime'] );
143 $webp_size = filesize( $path . wp_basename( $file_webp ) );
144 $metadata_webp['filesize'] = $webp_size;
145 if ( $ret ) {
146 if ( $pluswebp_settings['replace'] ) {
147 $up_post = array(
148 'ID' => $attachment_id,
149 'guid' => $this->upload_url . '/' . $file_webp,
150 'post_mime_type' => $pluswebp_settings['output_mime'],
151 );
152 wp_update_post( $up_post );
153 update_post_meta( $attachment_id, '_wp_attached_file', $file_webp );
154 /* for bulk generate */
155 update_post_meta( $attachment_id, '_wp_attachment_metadata', $metadata_webp );
156 /* delete org file */
157 wp_delete_file( $this->upload_dir . '/' . $metadata['file'] );
158 if ( $org_img_file ) {
159 wp_delete_file( $org_img_file );
160 }
161 /* Replace */
162 $this->change_db( $this->upload_url . '/' . $metadata['file'], $this->upload_url . '/' . $file_webp );
163 /* for hook */
164 $metadata = $metadata_webp;
165 /* for mail */
166 $attach_id = $attachment_id;
167 } else {
168 $post = get_post( $attachment_id );
169 $title = $post->post_title;
170 $attachment = array(
171 'guid' => $this->upload_url . '/' . $file_webp,
172 'post_mime_type' => $pluswebp_settings['output_mime'],
173 'post_title' => $title,
174 'post_content' => '',
175 'post_status' => 'inherit',
176 );
177 $file = $this->upload_dir . '/' . $file_webp;
178 $attach_id = wp_insert_attachment( $attachment, $file );
179
180 /* for XAMPP [ get_attached_file( $attach_id ): Unable to get correct value ] */
181 $metapath_name = str_replace( $this->upload_dir . '/', '', $file );
182 update_post_meta( $attach_id, '_wp_attached_file', $metapath_name );
183
184 wp_update_attachment_metadata( $attach_id, $metadata_webp );
185
186 $author = get_userdata( $post->post_author );
187 $userid = $author->ID;
188 $postdate = get_the_date( 'Y-m-d H:i:s', $attachment_id );
189 $postdategmt = get_gmt_from_date( $postdate );
190 $up_post = array(
191 'ID' => $attach_id,
192 'post_author' => $userid,
193 'post_date' => $postdate,
194 'post_date_gmt' => $postdategmt,
195 'post_modified' => $postdate,
196 'post_modified_gmt' => $postdategmt,
197 );
198 wp_update_post( $up_post );
199 }
200
201 update_option( 'pluswebp_generate', $attach_id );
202
203 /* for Media Library folders term by Organize Media Folder */
204 do_action( 'omf_folders_term_update', $metadata_webp, $attach_id );
205
206 /* for Term filter update by Organize Media Folder */
207 do_action( 'omf_term_filter_update' );
208
209 }
210 }
211
212 return $metadata;
213 }
214
215 /** ==================================================
216 * Thumbnail urls
217 *
218 * @param int $attach_id attach_id.
219 * @param array $metadata metadata.
220 * @param string $upload_url upload_url.
221 * @return array $image_thumbnail(string), $imagethumburls(array)
222 * @since 2.00
223 */
224 private function thumbnail_urls( $attach_id, $metadata, $upload_url ) {
225
226 $image_attr_thumbnail = wp_get_attachment_image_src( $attach_id, 'thumbnail', true );
227 $image_thumbnail = $image_attr_thumbnail[0];
228
229 $imagethumburls = array();
230 if ( ! empty( $metadata ) && array_key_exists( 'sizes', $metadata ) ) {
231 $thumbnails = $metadata['sizes'];
232 $path_file = get_post_meta( $attach_id, '_wp_attached_file', true );
233 $filename = wp_basename( $path_file );
234 $media_path = str_replace( $filename, '', $path_file );
235 $media_url = $upload_url . '/' . $media_path;
236 foreach ( $thumbnails as $key => $key2 ) {
237 $imagethumburls[ $key ] = $media_url . $key2['file'];
238 }
239 }
240
241 return array( $image_thumbnail, $imagethumburls );
242 }
243
244 /** ==================================================
245 * Output datas
246 *
247 * @param int $attach_id attach_id.
248 * @param array $metadata metadata.
249 * @return array (string) $attachment_link, $attachment_url, $filename, $original_image_url, $original_filename, $mime_type(string), $stamptime, $file_size
250 * @since 2.00
251 */
252 private function output_datas( $attach_id, $metadata ) {
253
254 $attachment_link = get_attachment_link( $attach_id );
255 $attachment_url = wp_get_attachment_url( $attach_id );
256 $filename = wp_basename( $attachment_url );
257 if ( ! empty( $metadata ) && array_key_exists( 'original_image', $metadata ) && ! empty( $metadata['original_image'] ) ) {
258 $original_image_url = wp_get_original_image_url( $attach_id );
259 $original_filename = wp_basename( $original_image_url );
260 } else {
261 $original_image_url = null;
262 $original_filename = null;
263 }
264 $mime_type = get_post_mime_type( $attach_id );
265
266 $stamptime = get_the_time( 'Y-n-j ', $attach_id ) . get_the_time( 'G:i:s', $attach_id );
267 if ( ! empty( $metadata ) && array_key_exists( 'filesize', $metadata ) && ! empty( $metadata['filesize'] ) ) {
268 $file_size = $metadata['filesize'];
269 } else {
270 $file_size = @filesize( get_attached_file( $attach_id ) );
271 }
272 if ( ! $file_size ) {
273 $file_size = __( 'Could not retrieve.', 'plus-webp' );
274 } else {
275 $file_size = size_format( $file_size );
276 }
277
278 return array( $attachment_link, $attachment_url, $filename, $original_image_url, $original_filename, $mime_type, $stamptime, $file_size );
279 }
280
281 /** ==================================================
282 * Get All Images
283 *
284 * @param array $types mime types.
285 * @param string $output_mime output mime type.
286 * @since 2.00
287 */
288 public function get_allimages( $types, $output_mime ) {
289
290 if ( empty( $types ) ) {
291 return array( array(), array() );
292 }
293
294 $args = array(
295 'post_type' => 'attachment',
296 'post_status' => 'inherit',
297 'post_mime_type' => $types,
298 'posts_per_page' => -1,
299 'orderby' => 'date',
300 'order' => 'DESC',
301 );
302 $posts = get_posts( $args );
303
304 global $wpdb;
305 $webp_titles = $wpdb->get_col(
306 $wpdb->prepare(
307 "
308 SELECT post_title
309 FROM {$wpdb->prefix}posts
310 WHERE post_type = 'attachment'
311 AND post_mime_type IN ( %s )
312 AND post_status = 'inherit'
313 ",
314 $output_mime,
315 )
316 );
317
318 $post_ids = array();
319 $no_file_ids = array();
320 $count = 0;
321 foreach ( $posts as $post ) {
322 if ( ! in_array( $post->post_title, $webp_titles ) ) {
323 if ( file_exists( get_attached_file( $post->ID ) ) ) {
324 $post_ids[] = $post->ID;
325 } else {
326 $no_file_ids[] = $post->ID;
327 }
328 }
329 }
330
331 return array( $post_ids, $no_file_ids );
332 }
333
334 /** ==================================================
335 * Mail messages hook
336 *
337 * @param array $messages messages.
338 * @param int $webp_id webp ID or avif ID.
339 *
340 * @since 4.00
341 */
342 public function mail_messages( $messages, $webp_id ) {
343
344 $metadata = wp_get_attachment_metadata( $webp_id );
345
346 $message = null;
347 if ( $metadata ) {
348 /* Thumbnail urls */
349 list( $image_thumbnail, $imagethumburls ) = $this->thumbnail_urls( $webp_id, $metadata, $this->upload_url );
350 /* Output datas*/
351 list( $attachment_link, $attachment_url, $filename, $original_image_url, $original_filename, $mime_type, $stamptime, $file_size ) = $this->output_datas( $webp_id, $metadata );
352
353 $message = 'ID: ' . $webp_id . "\n";
354 $message .= __( 'Title', 'plus-webp' ) . ': ' . get_the_title( $webp_id ) . "\n";
355 $message .= __( 'Permalink:', 'plus-webp' ) . ' ' . $attachment_link . "\n";
356 $message .= 'URL: ' . $attachment_url . "\n";
357 $message .= __( 'File name:', 'plus-webp' ) . ' ' . $filename . "\n";
358 if ( ! empty( $original_image_url ) ) {
359 $message .= __( 'Original URL:', 'plus-webp' ) . ' ' . $original_image_url . "\n";
360 $message .= __( 'Original File name:', 'plus-webp' ) . ' ' . $original_filename . "\n";
361 }
362 $message .= __( 'Date/Time', 'plus-webp' ) . ': ' . $stamptime . "\n";
363 $message .= __( 'File size:', 'plus-webp' ) . ' ' . $file_size . "\n";
364 if ( ! empty( $imagethumburls ) ) {
365 foreach ( $imagethumburls as $thumbsize => $imagethumburl ) {
366 $message .= $thumbsize . ': ' . $imagethumburl . "\n";
367 }
368 }
369 $message .= "\n";
370 $messages[] = $message;
371 }
372
373 return array( $message, $messages );
374 }
375
376 /** ==================================================
377 * Mail sent for Generate Messages
378 *
379 * @param array $messages mail messages.
380 * @param int $count convert count.
381 * @since 4.02
382 */
383 public function mail_generate_message( $messages, $count ) {
384
385 if ( function_exists( 'wp_date' ) ) {
386 $now_date_time = wp_date( 'Y-m-d H:i:s' );
387 } else {
388 $now_date_time = date_i18n( 'Y-m-d H:i:s' );
389 }
390 /* translators: Date and Time */
391 $message_head = sprintf( __( 'Plus WebP or AVIF : %s', 'plus-webp' ), $now_date_time ) . "\r\n\r\n";
392 /* translators: Generated count */
393 $message_head .= sprintf( __( 'Webp or AVIF generated %d.', 'plus-webp' ), $count ) . "\r\n\r\n";
394
395 $to = get_option( 'admin_email' );
396 /* translators: blogname for subject */
397 $subject = sprintf( __( '[%s] WebP or AVIF generate', 'plus-webp' ), get_option( 'blogname' ) );
398 wp_mail( $to, $subject, $message_head . implode( $messages ) );
399 }
400
401 /** ==================================================
402 * WebP or AVIF create
403 *
404 * @param string $filename input filename for pictures.
405 * @param string $mime_type mimetype.
406 * @param string $filename_webp output filename for webp or avif.
407 * @param int $quality quality of webp.
408 * @param string $output_mime output mime type.
409 * @return bool $ret create bool.
410 * @since 1.00
411 */
412 private function create_webp( $filename, $mime_type, $filename_webp, $quality, $output_mime ) {
413
414 if ( ! file_exists( $filename ) ) {
415 return false;
416 }
417 if ( file_exists( $filename_webp ) ) {
418 return false;
419 }
420
421 @set_time_limit( 60 );
422 wp_raise_memory_limit( 'pluswebp' );
423
424 $ret = false;
425 switch ( $mime_type ) {
426 case 'image/jpeg':
427 $src = imagecreatefromjpeg( $filename );
428 $img = imagecreatetruecolor( imagesx( $src ), imagesy( $src ) );
429 $bgcolor = imagecolorallocate( $img, 255, 255, 255 );
430 imagefill( $img, 0, 0, $bgcolor );
431 imagealphablending( $img, true );
432 break;
433 case 'image/png':
434 $src = imagecreatefrompng( $filename );
435 $img = imagecreatetruecolor( imagesx( $src ), imagesy( $src ) );
436 imagealphablending( $img, false );
437 imagesavealpha( $img, true );
438 $bgcolor = imagecolorallocatealpha( $img, 0, 0, 0, 127 );
439 imagefill( $img, 0, 0, $bgcolor );
440 imagecolortransparent( $img, $bgcolor );
441 break;
442 case 'image/bmp':
443 $src = imagecreatefrombmp( $filename );
444 $img = imagecreatetruecolor( imagesx( $src ), imagesy( $src ) );
445 break;
446 case 'image/gif':
447 $src = imagecreatefromgif( $filename );
448 $img = imagecreatetruecolor( imagesx( $src ), imagesy( $src ) );
449 $bgcolor = imagecolorallocatealpha( $img, 0, 0, 0, 127 );
450 imagefill( $img, 0, 0, $bgcolor );
451 imagecolortransparent( $img, $bgcolor );
452 break;
453 }
454
455 imagecopy( $img, $src, 0, 0, 0, 0, imagesx( $src ), imagesy( $src ) );
456 imagedestroy( $src );
457
458 switch ( $output_mime ) {
459 case 'image/webp':
460 $ret = imagewebp( $img, $filename_webp, $quality );
461 break;
462 case 'image/avif':
463 $ret = imageavif( $img, $filename_webp, $quality );
464 break;
465 default:
466 $ret = imagewebp( $img, $filename_webp, $quality );
467 }
468
469 imagedestroy( $img );
470
471 return $ret;
472 }
473
474 /** ==================================================
475 * Change ext
476 *
477 * @param string $before_file_name before_file_name.
478 * @param string $ext ext.
479 * @param bool $addext addext.
480 * @return array $after_file_name after_file_name.
481 * @since 1.00
482 */
483 private function change_ext( $before_file_name, $ext, $addext ) {
484
485 if ( $addext ) {
486 $after_file_name = $before_file_name . '.' . $ext;
487 } else {
488 $exts = explode( '.', $before_file_name );
489 $before_ext = '.' . end( $exts );
490 $after_ext = '.' . $ext;
491 $after_file_name = str_replace( $before_ext, $after_ext, $before_file_name );
492 }
493
494 return $after_file_name;
495 }
496
497 /** ==================================================
498 * Change DB
499 *
500 * @param string $before_url before_url.
501 * @param string $after_url after_url.
502 * @since 1.00
503 */
504 private function change_db( $before_url, $after_url ) {
505
506 global $wpdb;
507
508 /* Replace */
509 $wpdb->query(
510 $wpdb->prepare(
511 "
512 UPDATE {$wpdb->prefix}posts
513 SET post_content = replace( post_content, %s, %s )
514 ",
515 $before_url,
516 $after_url
517 )
518 );
519
520 /* Advanced change database */
521 list( $before_url, $after_url ) = apply_filters( 'plus_webp_advanced_change_db', $before_url, $after_url );
522 }
523
524 /** ==================================================
525 * Filter Raise Memory limit
526 *
527 * @since 3.00
528 *
529 * @param string $filtered_limit Memory limit.
530 */
531 public function raise_memory_limit( $filtered_limit ) {
532
533 return '256M';
534 }
535
536 /** ==================================================
537 * Filter the output mime types for a given input mime type and image size.
538 *
539 * @since 3.00
540 *
541 * @param array $image_mime_transforms A map with the valid mime transforms where the key is the source file mime type
542 * and the value is one or more mime file types to generate.
543 * @param int $attachment_id The ID of the attachment where the hook was dispatched.
544 */
545 public function control_mime_type( $image_mime_transforms, $attachment_id ) {
546
547 $image_mime_transforms = array();
548
549 return $image_mime_transforms;
550 }
551 }
552