PluginProbe
Plus WebP or AVIF / 4.11
Plus WebP or AVIF v4.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 4.11, at lib/class-pluswebp.php

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