PluginProbe
ezCache / 1.3.11
ezCache v1.3.11
2.6.5 2.6.4 2.6.2 2.6.3 2.6.1 2.6.0 2.5.6 2.5.5 2.5.4 2.5.3 2.5.2 2.5.1 2.5 2.2.1 2.2.2 trunk 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.3 1.3.1 1.3.10 1.3.11 All 49 releases
ezcache / includes / FileOptimizer / WebpConverter.php

WebpConverter.php in ezCache 1.3.11, at includes/FileOptimizer/WebpConverter.php

137 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Upress\EzCache\FileOptimizer;
3
4 use Upress\EzCache\BackgroundProcesses\ConvertWebpProcess;
5 use wpdb;
6
7 class WebpConverter extends BaseFileOptimizer {
8 /** @var string $cache_dir */
9 protected $cache_dir;
10 /** @var string $cache_file */
11 protected $cache_file;
12 /** @var ConvertWebpProcess $webp_processor */
13 protected $webp_processor;
14 /** @var wpdb $wpdb */
15 protected $wpdb;
16
17 function __construct( $cache_dir, $cache_file, $webp_processor, $wpdb ) {
18 $this->cache_dir = $cache_dir;
19 $this->cache_file = $cache_file;
20 $this->webp_processor = $webp_processor;
21 $this->wpdb = $wpdb;
22 }
23
24 /**
25 * Minifies CSS files
26 *
27 * @param string $html HTML content.
28 *
29 * @return string
30 */
31 public function optimize( $html ) {
32 /*
33 * we need to make sure to handle multiple formats
34 * <img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
35 * <img srcset="elva-fairy-320w.jpg 320w, elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w" sizes="(max-width: 320px) 280px, (max-width: 480px) 440px, 800px" src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
36 * <picture><source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg"><img srv="elva-480w-close-portrait.jpg" alt="Elva dressed as a fairy"></picture>
37 * <div style="background: url(elva-480w-close-portrait.jpg);">
38 * <div style="background-image: url(elva-480w-close-portrait.jpg);">
39 */
40 $images = $this->find( '<img\s+([^>]+[\s"\'])?src\s*=\s*[\'"]\s*?([^\'"]+(?:\?[^\'"]*)?)\s*?[\'"]([^>]+)?\/?>', $html );
41
42 if ( ! $images ) {
43 return $html;
44 }
45
46 $need_to_process = false;
47 foreach ( $images as $image ) {
48 $image_url = $image[2];
49
50 // we don't process external files or files that don't exist
51
52 if($this->is_external_file( $image_url )) {
53 continue;
54 }
55
56 $image_path = $this->get_file_path( $image[2] );
57 if( ! file_exists( $image_path ) ) {
58 continue;
59 }
60
61 $ext = pathinfo( $image_path, PATHINFO_EXTENSION );
62 $mime = mime_content_type( $image_path );
63
64
65
66 $ext_quoted = preg_quote( $ext, '/' );
67 $image_webp_url = preg_replace( '/^(.+\.)'.$ext_quoted.'(\?.+)?$/u', '$1' . substr( md5( $ext ), -6 ) . '.webp$2', $image_url );
68 $image_webp_path = preg_replace( '/^(.+\.)'.$ext_quoted.'$/u', '$1' . substr( md5( $ext ), -6 ) . '.webp', $image_path );
69
70 // and skip non-images or images already in webp format
71 if ( 'webp' == $ext || ! preg_match( '/image\/.+/i', $mime ) || preg_match( '/image\/(svg.*|ico|gif|webp)/i', $mime ) ) {
72 continue;
73 }
74
75 // check if the image has a webp version and if it has then just replace it in the html
76 $image = $this->wpdb->get_row(
77 $this->wpdb->prepare(
78 "SELECT * FROM `{$this->wpdb->prefix}ezcache_webp_images` WHERE `uid` = %s LIMIT 1",
79 [ sha1( $image_path ) ]
80 )
81 );
82
83 if ( $image && 'completed' == $image->status ) {
84 $html = preg_replace( '/\b' . preg_quote( $image_url, '/' ) . '\b/u', $image->webp_url, $html );
85 continue;
86 }
87
88 if ( $image && 'pending' == $image->status ) {
89 // image is being processed in background
90 continue;
91 }
92
93 if ( $image && 'failed' == $image->status ) {
94 // if the image has failed we need to requeue it
95 $this->wpdb->query(
96 $this->wpdb->prepare(
97 "DELETE FROM `{$this->wpdb->prefix}ezcache_webp_images` WHERE `id` = %d",
98 [ $image->id ]
99 )
100 );
101 }
102
103 // otherwise send the image to process
104 // this should parse the images and set a callback to update the cache file
105 $this->wpdb->query(
106 $this->wpdb->prepare(
107 "INSERT INTO `{$this->wpdb->prefix}ezcache_webp_images` (`uid`, `url`, `webp_url`, `path`, `webp_path`, `status`, `created_at`, `updated_at`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",
108 [ sha1( $image_path ), $image_url, $image_webp_url, $image_path, $image_webp_path, 'pending', date( 'Y-m-d H:i:s' ), date( 'Y-m-d H:i:s' ) ]
109 )
110 );
111
112 if ( empty( $this->wpdb->last_error ) ) {
113 $need_to_process = true;
114 $this->webp_processor->push_to_queue( [
115 'row_id' => $this->wpdb->insert_id,
116 'image_url' => $image_url,
117 'image_path' => $image_path,
118 'image_webp_url' => $image_webp_url,
119 'image_webp_path' => $image_webp_path,
120 'cache_file' => $this->cache_file,
121 ] );
122 } else {
123 error_log( 'ezCache WebP Converter Error: ' . $this->wpdb->last_error );
124 }
125 }
126
127 if ( $need_to_process ) {
128 add_filter( 'http_headers_useragent', function () {
129 return 'webp background processor';
130 }, 9999 );
131 $this->webp_processor->save();
132 }
133
134 return $html;
135 }
136 }
137