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 | includes/class-wp-optimize-gzip-compression.php +198 -27 3.2.20 → 4.7.0 View file →
@@ -1,5 +1,6 @@
1 1 <?php
2 +if (!defined('ABSPATH')) die('Access denied.');
2 3
3 4 /**
4 5 * Class WP_Optimize_Gzip_Compression
5 6 */
@@ -4,14 +5,16 @@
4 5 * Class WP_Optimize_Gzip_Compression
5 6 */
6 7 class WP_Optimize_Gzip_Compression {
7 8
9 + use WP_Optimize_HTTP_Error_Codes_Trait;
10 +
8 11 /**
9 12 * WP_Optimize_Htaccess instance.
10 13 *
11 14 * @var WP_Optimize_Htaccess
12 15 */
13 - private $_htaccess = null;
16 + private $_htaccess;
14 17
15 18 /**
16 19 * WP_Optimize instance.
17 20 *
@@ -16,12 +19,12 @@
16 19 * WP_Optimize instance.
17 20 *
18 21 * @var WP_Optimize
19 22 */
20 - private $_wp_optimize = null;
23 + private $_wp_optimize;
21 24
22 25 /**
23 - * Gzip section in htaccess will wrapped with this comment
26 + * Gzip section in htaccess will be wrapped with this comment
24 27 *
25 28 * @var string
26 29 */
27 30 private $_htaccess_section_comment = 'WP-Optimize Gzip compression';
@@ -47,20 +50,42 @@
47 50 return $_instance;
48 51 }
49 52
50 53 /**
51 - * Make http request to theme style.css, get 'server' line and check headers for gzip/brotli encoding option.
54 + * Make http request to $url, get 'server' line and check headers for gzip/brotli encoding option.
52 55 *
56 + * @param string $url
57 + *
53 58 * @return array|WP_Error
54 59 */
55 - public function get_headers_information() {
56 - static $headers_information;
57 - if (isset($headers_information)) return $headers_information;
60 + public function get_headers_information($url) {
61 + static $cached_headers_information = array();
62 + if (isset($cached_headers_information[$url])) return $cached_headers_information[$url];
58 63
59 - $headers = WP_Optimize()->get_stylesheet_headers();
64 + $response = wp_remote_get($url, array('timeout' => 10));
60 65
61 - if (is_wp_error($headers)) return $headers;
66 + if (is_wp_error($response)) {
67 + return $response;
68 + }
62 69
70 + $response_code = wp_remote_retrieve_response_code($response);
71 +
72 + if (200 !== $response_code) {
73 + // translators: %1$s is a requested URL, %2$s is the HTTP response code
74 + return new WP_Error($response_code, sprintf(__('Unexpected response code when trying to get response for %1$s: %2$s (expected 200)', 'wp-optimize'), $url, $response_code));
75 + }
76 +
77 + $headers = wp_remote_retrieve_headers($response);
78 +
79 + if (empty($headers)) {
80 + // translators: %s is a requested URL
81 + return new WP_Error($response_code, sprintf(__('Unable to retrieve HTTP headers information for %s', 'wp-optimize'), $url));
82 + }
83 +
84 + if (is_object($headers) && method_exists($headers, 'getAll')) {
85 + $headers = $headers->getAll();
86 + }
87 +
63 88 $headers_information = array(
64 89 'server' => array_key_exists('server', $headers) ? $headers['server'] : '',
65 90 );
66 91
@@ -70,13 +95,17 @@
70 95 $this->disable();
71 96 } elseif (array_key_exists('content-encoding', $headers) && preg_match('/gzip/i', $headers['content-encoding'])) {
72 97 // check if there exists Content-encoding header with gzip value.
73 98 $headers_information['compression'] = 'gzip';
74 -
99 + } elseif (array_key_exists('content-encoding', $headers) && preg_match('/zstd/i', $headers['content-encoding'])) {
100 + // check if there exists Content-encoding header with zstd value.
101 + $headers_information['compression'] = 'zstd';
75 102 } else {
76 103 $headers_information['compression'] = false;
77 104 }
78 105
106 + $cached_headers_information[$url] = $headers_information;
107 +
79 108 return $headers_information;
80 109 }
81 110
82 111 /**
@@ -108,28 +137,24 @@
108 137
109 138 /**
110 139 * Check if Gzip compression is enabled.
111 140 *
112 - * @param boolean $force_check - force the check
141 + * @param boolean $use_cache - use cached data
113 142 * @return bool|WP_Error
114 143 */
115 - public function is_gzip_compression_enabled($force_check = false) {
144 + public function is_gzip_compression_enabled($use_cache = true) {
116 145
117 - if (!$force_check) return WP_Optimize()->get_options()->get_option('is_gzip_compression_enabled');
146 + $compression_types = $this->get_compression_types($use_cache);
118 147
119 - // trying to get info about gzip in headers.
120 - $headers_info = $this->get_headers_information();
148 + $is_gzip_compression_enabled = true;
121 149
122 - // we can't determine then return WP_Error.
123 - if (is_wp_error($headers_info)) return $headers_info;
150 + foreach ($compression_types as $compression) {
151 + if (is_wp_error($compression)) return $compression;
152 + if (!in_array($compression, array('gzip', 'brotli', 'zstd'))) $is_gzip_compression_enabled = false;
153 + }
124 154
125 - $is_gzip_compression_enabled = $headers_info['compression'];
126 -
127 - // if we got error then trying to get info from api otherwise get result from check_headers_for_gzip().
128 - // $is_gzip_compression_enabled = is_wp_error($is_gzip_compression_enabled) ? $this->check_api_for_gzip() : $is_gzip_compression_enabled;
129 -
130 - // if Gzip is not enabled but we have added settings and Apache modules nt loaded then return error.
131 - if (false == $is_gzip_compression_enabled && $this->is_gzip_compression_section_exists()) {
155 + // if Gzip is not enabled, but we have added settings and Apache modules nt loaded then return error.
156 + if (!$is_gzip_compression_enabled && $this->is_gzip_compression_section_exists()) {
132 157 if (false === $this->_wp_optimize->is_apache_module_loaded(array('mod_filter', 'mod_deflate'))) {
133 158 return new WP_Error('gzip_missing_module', __('We successfully added Gzip compression settings into .htaccess file.', 'wp-optimize').' '.__('However, the test file we fetched was not Gzip-compressed.', 'wp-optimize').' '.__('It seems one of Apache modules - mod_filter or mod_deflate - is not active.', 'wp-optimize'));
134 159 } elseif (WP_Optimize()->is_apache_server()) {
135 160 return new WP_Error('gzip_missing_module', __('We successfully added Gzip compression settings into .htaccess file.', 'wp-optimize').' '.__('However, the test file we fetched was not Gzip-compressed.', 'wp-optimize').' '.__('Possible causes include that Apache (your webserver) is not configured to allow .htaccess files to take effect, or one of Apache modules - mod_filter or mod_deflate - is not active, or the webserver is configured to disallow Gzip compression.', 'wp-optimize').' '.__('You should speak to your web hosting support to find how to enable it.', 'wp-optimize'));
@@ -137,14 +162,35 @@
137 162 return new WP_Error('gzip_unsuccessful', __('We successfully added Gzip compression settings into .htaccess file.', 'wp-optimize').' '.__('However, the test file we fetched was not Gzip-compressed.', 'wp-optimize').' '.__('You should speak to your web hosting support to find how to enable it.', 'wp-optimize'));
138 163 }
139 164 }
140 165
141 - WP_Optimize()->get_options()->update_option('is_gzip_compression_enabled', $is_gzip_compression_enabled);
166 + // Stored value used to restore gzip compression settings used when plugin being activated,
167 + // i.e. we need to update it only when we have added settings to .htaccess or gzip is disabled
168 + if (!$is_gzip_compression_enabled || $this->is_gzip_compression_section_exists()) {
169 + WP_Optimize()->get_options()->update_option('is_gzip_compression_enabled', $is_gzip_compression_enabled);
170 + }
142 171
143 172 return $is_gzip_compression_enabled;
144 173 }
145 174
146 175 /**
176 + * Returns the compression type of the given URL.
177 + *
178 + * @param string $url
179 + * @return string|WP_Error
180 + */
181 + private function get_compression_type($url) {
182 +
183 + $headers_info = $this->get_headers_information($url);
184 +
185 + if (is_wp_error($headers_info)) return $headers_info;
186 +
187 + if (!isset($headers_info['compression'])) return '';
188 +
189 + return $headers_info['compression'];
190 + }
191 +
192 + /**
147 193 * Check if section with Gzip options already exists in htaccess file.
148 194 *
149 195 * @return bool
150 196 */
@@ -185,9 +231,9 @@
185 231 */
186 232 public function enable_gzip_command_handler($params) {
187 233 $section_updated = false;
188 234
189 - $enable = (isset($params['enable']) && $params['enable']) ? true : false;
235 + $enable = isset($params['enable']) && $params['enable'];
190 236
191 237 if ($this->_htaccess->is_writable()) {
192 238
193 239 // update commented section
@@ -204,9 +250,9 @@
204 250 // set correct $section-updated flag.
205 251 $section_updated = $enable === $section_exists;
206 252 }
207 253
208 - $is_gzip_compression_enabled = $this->is_gzip_compression_enabled(true);
254 + $is_gzip_compression_enabled = $this->is_gzip_compression_enabled(false);
209 255
210 256 if ($section_updated) {
211 257 return array(
212 258 'success' => true,
@@ -217,10 +263,12 @@
217 263 } else {
218 264 $gzip_section = $this->prepare_gzip_section();
219 265
220 266 if ($is_gzip_compression_enabled) {
267 + // translators: %s is a file name
221 268 $message = sprintf(__("We can\'t update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to remove following lines manually:', 'wp-optimize');
222 269 } else {
270 + // translators: %s is a file name
223 271 $message = sprintf(__("We can\'t update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to add following lines manually:', 'wp-optimize');
224 272 }
225 273
226 274 return array(
@@ -232,8 +280,131 @@
232 280 join(PHP_EOL, $this->_htaccess->get_flat_array($gzip_section)).
233 281 PHP_EOL.$this->_htaccess->get_section_end_comment($this->_htaccess_section_comment)),
234 282 );
235 283 }
284 + }
285 +
286 + /**
287 + * Retrieve the compression statuses for HTML, CSS, and JS resources in HTML format.
288 + *
289 + * @param bool $use_cache if true, the cached value will be returned if possible
290 + * @return string
291 + */
292 + public function get_compression_test_results_html($use_cache = false) {
293 +
294 + $compression_types = $this->get_compression_types($use_cache);
295 +
296 + $result_html = '';
297 +
298 + foreach ($compression_types as $title => $compression) {
299 + if (is_wp_error($compression)) {
300 + $value = $compression->get_error_message();
301 + } elseif (!empty($compression)) {
302 + $value = '<b>'.$compression.'</b>';
303 + } else {
304 + $value = __('No compression', 'wp-optimize');
305 + }
306 +
307 + $result_html .= $title.': '. $value . '<br>';
308 + }
309 +
310 + return wp_kses_post($result_html);
311 + }
312 +
313 + /**
314 + * Get list of content types for which enabled/disabled gzip compression (html, css, js).
315 + *
316 + * @param bool $use_cache if true, the cached value will be returned if possible
317 + *
318 + * @return array
319 + */
320 + public function get_enabled_disabled_compression_content_types($use_cache = false) {
321 + $result = array(
322 + 'enabled' => array(),
323 + 'disabled' => array(),
324 + );
325 +
326 + $compression_types = $this->get_compression_types($use_cache);
327 +
328 + foreach ($compression_types as $type => $status) {
329 + if (false !== $status && '' !== $status && !is_wp_error($status)) {
330 + $result['enabled'][] = $type;
331 + } else {
332 + $result['disabled'][] = $type;
333 + }
334 + }
335 +
336 + return $result;
337 + }
338 +
339 + /**
340 + * Get compression types for html, css, js files.
341 + *
342 + * @param bool $use_cache if true, the cached value will be returned if possible
343 + *
344 + * @return array
345 + */
346 + private function get_compression_types($use_cache = false) {
347 + $transient_key = 'wpo_compression_test_results';
348 + $compression_types = array('HTML' => '', 'CSS' => '', 'JS' => '');
349 + $cached_compression_types = array();
350 +
351 + if ($use_cache) {
352 + $cached_compression_types = get_transient($transient_key);
353 + }
354 +
355 + $should_update_cache = false;
356 +
357 + foreach ($compression_types as $content_type => $compression) {
358 + // if we have cached value and it is not WP_Error then use it, otherwise get compression type and update cache later.
359 + if ($use_cache && isset($cached_compression_types[$content_type]) && 'WP_Error' !== $cached_compression_types[$content_type]) {
360 + $compression_types[$content_type] = $cached_compression_types[$content_type];
361 + } else {
362 + $compression_types[$content_type] = $this->get_compression_type_by_content_type($content_type);
363 + $should_update_cache = true;
364 + }
365 + }
366 +
367 + if ($should_update_cache) {
368 + $compression_types_for_cache = $compression_types;
369 + foreach ($compression_types_for_cache as $content_type => $compression) {
370 + if (is_wp_error($compression)) {
371 + $compression_types_for_cache[$content_type] = 'WP_Error';
372 + }
373 + }
374 + set_transient($transient_key, $compression_types_for_cache, HOUR_IN_SECONDS);
375 + }
376 +
377 + return $compression_types;
378 + }
379 +
380 + /**
381 + * Get compression type for the given content type (html, css, js).
382 + *
383 + * @param string $content_type - content type (html, css, js)
384 + * @return string|false|WP_Error
385 + */
386 + private function get_compression_type_by_content_type($content_type) {
387 + $content_type = strtoupper($content_type);
388 + switch ($content_type) {
389 + case 'HTML':
390 + return $this->get_compression_type(get_home_url(null, '?cache=false'));
391 + case 'CSS':
392 + return $this->get_compression_type($this->css_resource_url());
393 + case 'JS':
394 + return $this->get_compression_type(site_url('wp-includes/js/admin-bar.min.js'));
395 + default:
396 + return '';
397 + }
398 + }
399 +
400 + /**
401 + * Get URL to the CSS resource for checking Gzip compression status of CSS files.
402 + *
403 + * @return string
404 + */
405 + public function css_resource_url() {
406 + return WPO_PLUGIN_URL . 'css/wp-optimize-admin.css';
236 407 }
237 408
238 409 /**
239 410 * Prepare array with options to switch on gzip in htaccess.