PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.7.0
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.7.0
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
← All changes | webp/class-wpo-webp-alter-html.php +80 -66 4.5.3 → 4.7.0 View file →
@@ -5,23 +5,31 @@
5 5 if (!class_exists('WPO_WebP_Alter_HTML')) :
6 6
7 7 class WPO_WebP_Alter_HTML {
8 8
9 - private $tags = array('img', 'source', 'input', 'iframe', 'div', 'li', 'link', 'a', 'section', 'video');
10 -
11 9 /**
12 - * Constructor
10 + * HTML tags that may contain image-related attributes eligible for WebP replacement.
13 11 */
12 + const SUPPORTED_TAGS = array('img', 'source', 'input', 'iframe', 'div', 'li', 'link', 'a', 'section', 'video');
13 +
14 + /**
15 + * Regex pattern to identify image-related attribute names such as src, srcset,
16 + * poster, and common data-* attributes used for lazy loading or responsive images.
17 + */
18 + const IMAGE_ATTRIBUTE_PATTERN = '#^(src|srcset|poster|(data-[^=]*(lazy|small|slide|img|large|src|thumb|source|set|bg-url)[^=]*))$#i';
19 +
20 + /**
21 + * Constructor — private to enforce singleton pattern.
22 + */
14 23 private function __construct() {
15 -
16 24 }
17 25
18 26 /**
19 - * Returns singleton instance
27 + * Returns singleton instance.
20 28 *
21 - * @return WPO_WebP_Alter_HTML
29 + * @return self
22 30 */
23 - public static function get_instance() {
31 + public static function get_instance(): self {
24 32 static $_instance = null;
25 33 if (null === $_instance) {
26 34 $_instance = new self();
27 35 }
@@ -26,13 +34,13 @@
26 34 $_instance = new self();
27 35 }
28 36 return $_instance;
29 37 }
30 -
38 +
31 39 /**
32 - * Alter html to change image related tags to specify webp images
40 + * Alter HTML to replace image-related attributes with WebP URLs where available.
33 41 *
34 - * @param string $html - HTML document as string
42 + * @param string $html HTML document as string.
35 43 * @return string
36 44 */
37 45 public function alter_html(string $html): string {
38 46 if (apply_filters('wpo_disable_webp_alter_html', false)) {
@@ -38,26 +46,33 @@
38 46 if (apply_filters('wpo_disable_webp_alter_html', false)) {
39 47 return $html;
40 48 }
41 49
42 - // MAX_FILE_SIZE is defined in simple_html_dom.
43 - // For safety, we make sure it is defined before using
44 - defined('MAX_FILE_SIZE') || define('MAX_FILE_SIZE', 600000);
50 + // MAX_FILE_SIZE is defined in simple_html_dom — ensure it has a safe default.
51 + WP_Optimize_Utils::define_maxfile_size_constant();
45 52
46 53 $dom = WP_Optimize_Utils::get_simple_html_dom_object($html);
47 54
48 55 if (false === $dom) {
49 - if (strlen($html) > MAX_FILE_SIZE) {
50 - return $html . "\n" . "<!-- Alter HTML was skipped because the HTML is too big to process! " .
51 - "(limit is set to " . MAX_FILE_SIZE . " bytes) -->";
52 - }
53 - return $html . "\n" . "<!-- Alter HTML was skipped because the helper library refused to process the html -->";
56 + return $this->get_skipped_html($html);
54 57 }
55 58
56 - // Replace attributes (src, srcset, data-src, etc)
57 - foreach ($this->tags as $tag) {
58 - $elems = $dom->find($tag);
59 - foreach ($elems as $elem) {
59 + $this->replace_image_attributes($dom);
60 +
61 + return $dom->save();
62 + }
63 +
64 + /**
65 + * Walks all supported tags in the DOM and replaces image attribute values
66 + * with their WebP counterparts when available.
67 + *
68 + * @param simplehtmldom\HtmlDocument $dom A simple_html_dom instance.
69 + *
70 + * @return void
71 + */
72 + private function replace_image_attributes($dom): void {
73 + foreach (self::SUPPORTED_TAGS as $tag) {
74 + foreach ($dom->find($tag) as $elem) {
60 75 $attributes = $elem->getAllAttributes();
61 76 foreach ($attributes as $attr_name => $attr_value) {
62 77 if ($this->is_image_attribute($attr_name)) {
63 78 $elem->setAttribute($attr_name, $this->handle_attribute($attr_value));
@@ -64,53 +79,49 @@
64 79 }
65 80 }
66 81 }
67 82 }
68 -
69 - $result = $dom->save();
70 - return $result;
71 83 }
72 84
73 85 /**
74 - * Append image urls with `.webp` extension
86 + * Returns the original HTML annotated with a comment explaining why
87 + * the WebP alteration was skipped.
75 88 *
76 - * @param string $url - Image URL
89 + * @param string $html The original HTML document.
77 90 * @return string
78 91 */
79 - private function replace_url($url) {
80 - return $url . '.webp';
92 + private function get_skipped_html($html): string {
93 + if (strlen($html) > MAX_FILE_SIZE) {
94 + return $html . "\n" . "<!-- Alter HTML was skipped because the HTML is too big to process! " .
95 + "(limit is set to " . MAX_FILE_SIZE . " bytes) -->";
96 + }
97 + return $html . "\n" . "<!-- Alter HTML was skipped because the helper library refused to process the html -->";
81 98 }
82 99
83 100 /**
84 - * If webp version for supplied image url is available then replace extension
101 + * Returns the URL with a .webp extension appended if a WebP version exists on disk.
85 102 *
86 - * @param string $url - URL of image
103 + * @param string $url URL of the original image.
87 104 * @return string
88 105 */
89 - private function maybe_replace_url($url) {
106 + private function maybe_replace_url($url): string {
90 107 if ($this->is_webp_version_available($url)) {
91 - $url = $this->replace_url($url);
108 + $url .= '.webp';
92 109 }
93 110 return $url;
94 111 }
95 112
96 113 /**
97 - * Modifies src attribute value, if needed
114 + * Processes a srcset attribute value, replacing each image URL with its
115 + * WebP counterpart when available.
98 116 *
99 - * @param string $attr_value
100 - * @return string
101 - */
102 - private function handle_src($attr_value) {
103 - return $this->maybe_replace_url($attr_value);
104 - }
105 -
106 - /**
107 - * Modified `srcset` attribute value, if needed
117 + * A srcset value is a comma-separated list of entries such as
118 + * "image.jpg 520w" or "image.jpg 2x" or just "image.jpg".
108 119 *
109 - * @param string $attr_value
120 + * @param string $attr_value The raw srcset attribute value.
110 121 * @return string
111 122 */
112 - private function handle_srcset($attr_value) {
123 + private function handle_srcset($attr_value): string {
113 124 // $attr_value is ie: <img data-x="1.jpg 1000w, 2.jpg">
114 125 $srcset_arr = explode(',', $attr_value);
115 126 foreach ($srcset_arr as $i => $srcset_entry) {
116 127 // $srcset_entry is ie "image.jpg 520w", but can also lack width, ie just "image.jpg"
@@ -116,9 +127,10 @@
116 127 // $srcset_entry is ie "image.jpg 520w", but can also lack width, ie just "image.jpg"
117 128 // it can also be ie "image.jpg 2x"
118 129 $srcset_entry = trim($srcset_entry);
119 130 $entry_parts = preg_split('/\s+/', $srcset_entry, 2);
120 - if (2 === count($entry_parts)) {
131 +
132 + if (is_array($entry_parts) && 2 === count($entry_parts)) {
121 133 list($src, $descriptors) = $entry_parts;
122 134 } else {
123 135 $src = $srcset_entry;
124 136 $descriptors = null;
@@ -130,52 +142,54 @@
130 142 return implode(', ', $srcset_arr);
131 143 }
132 144
133 145 /**
134 - * Decides whether given value is a `srcset` or not
146 + * Determines whether an attribute value resembles a srcset declaration
147 + * (contains a width or pixel-density descriptor).
135 148 *
136 - * @param string $value
149 + * @param string $value The attribute value to inspect.
137 150 * @return bool
138 151 */
139 - private function looks_like_srcset($value) {
140 - if (preg_match('#\s\d*(w|x)#', $value)) {
141 - return true;
142 - }
143 - return false;
152 + private function looks_like_srcset($value): bool {
153 + return (bool) preg_match('#\s\d*(w|x)#', $value);
144 154 }
145 155
146 156 /**
147 - * Handle attribute value based on attribute name, src or srcset
157 + * Dispatches attribute value handling based on whether it looks like a
158 + * srcset or a plain image source URL.
148 159 *
149 - * @param string $value
160 + * @param string $value The attribute value.
150 161 * @return string
151 162 */
152 - private function handle_attribute($value) {
163 + private function handle_attribute($value): string {
153 164 if ($this->looks_like_srcset($value)) {
154 165 return $this->handle_srcset($value);
155 166 }
156 - return $this->handle_src($value);
167 + return $this->maybe_replace_url($value);
157 168 }
158 169
159 170 /**
160 - * Decide whether given attribute name is an image attribute or not
171 + * Determines whether an attribute name is image-related and should be
172 + * considered for WebP replacement.
161 173 *
162 - * @param string $attr_name
174 + * @param string $attr_name The attribute name.
163 175 * @return bool
164 176 */
165 - private function is_image_attribute($attr_name) {
166 - return preg_match('#^(src|srcset|poster|(data-[^=]*(lazy|small|slide|img|large|src|thumb|source|set|bg-url)[^=]*))$#i', $attr_name);
177 + private function is_image_attribute($attr_name): bool {
178 + return (bool) preg_match(self::IMAGE_ATTRIBUTE_PATTERN, $attr_name);
167 179 }
168 180
169 181 /**
170 - * Does webp image file exists
182 + * Checks whether a WebP version of the given image URL exists on disk.
171 183 *
172 - * @param string $url
173 - * @return boolean
184 + * @param string $url The original image URL.
185 + * @return bool
174 186 */
175 - private function is_webp_version_available($url) {
187 + private function is_webp_version_available($url): bool {
176 188 $filename = WP_Optimize_Utils::get_file_path($url);
177 - if (empty($filename)) return false;
189 + if (empty($filename)) {
190 + return false;
191 + }
178 192 return file_exists($filename . '.webp');
179 193 }
180 194 }
181 195