PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 4.5.3
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v4.5.3
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
wp-optimize / includes / class-wp-optimize-gzip-compression.php

class-wp-optimize-gzip-compression.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 4.5.3, at includes/class-wp-optimize-gzip-compression.php

301 lines 10.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('Access denied.');
3
4 /**
5 * Class WP_Optimize_Gzip_Compression
6 */
7 class WP_Optimize_Gzip_Compression {
8
9 use WP_Optimize_HTTP_Error_Codes_Trait;
10
11 /**
12 * WP_Optimize_Htaccess instance.
13 *
14 * @var WP_Optimize_Htaccess
15 */
16 private $_htaccess;
17
18 /**
19 * WP_Optimize instance.
20 *
21 * @var WP_Optimize
22 */
23 private $_wp_optimize;
24
25 /**
26 * Gzip section in htaccess will be wrapped with this comment
27 *
28 * @var string
29 */
30 private $_htaccess_section_comment = 'WP-Optimize Gzip compression';
31
32 /**
33 * WP_Optimize_Gzip_Compression constructor.
34 */
35 public function __construct() {
36 $this->_wp_optimize = WP_Optimize();
37 $this->_htaccess = $this->_wp_optimize->get_htaccess();
38 }
39
40 /**
41 * Returns singleton instance object
42 *
43 * @return WP_Optimize_Gzip_Compression Returns `WP_Optimize_Gzip_Compression` object
44 */
45 public static function instance() {
46 static $_instance = null;
47 if (null === $_instance) {
48 $_instance = new self();
49 }
50 return $_instance;
51 }
52
53 /**
54 * Make http request to theme style.css, get 'server' line and check headers for gzip/brotli encoding option.
55 *
56 * @return array|WP_Error
57 */
58 public function get_headers_information() {
59 static $headers_information;
60 if (isset($headers_information)) return $headers_information;
61
62 $headers = $this->get_stylesheet_headers();
63
64 if (is_wp_error($headers)) return $headers;
65
66 $headers_information = array(
67 'server' => array_key_exists('server', $headers) ? $headers['server'] : '',
68 );
69
70 if (array_key_exists('content-encoding', $headers) && preg_match('/^(.*\W|)br(\W.*|)$/i', $headers['content-encoding'])) {
71 // check if there exists Content-encoding header with br(Brotli) value.
72 $headers_information['compression'] = 'brotli';
73 $this->disable();
74 } elseif (array_key_exists('content-encoding', $headers) && preg_match('/gzip/i', $headers['content-encoding'])) {
75 // check if there exists Content-encoding header with gzip value.
76 $headers_information['compression'] = 'gzip';
77
78 } else {
79 $headers_information['compression'] = false;
80 }
81
82 return $headers_information;
83 }
84
85 /**
86 * Make request to checkgzipcompression.com api and check if gzip option enabled.
87 *
88 * @return bool|WP_Error
89 */
90 public function check_api_for_gzip() {
91 $url = get_template_directory_uri() . '/style.css';
92
93 $api_url = 'https://checkgzipcompression.com/js/checkgzip.json?url=' . urlencode($url);
94
95 $result = wp_remote_get($api_url, array('timeout' => 10));
96
97 if (is_wp_error($result)) return $result;
98
99 if (!isset($result['body'])) return new WP_Error('Gzip', __("We can't definitely determine Gzip status as API doesn't return correct answer.", 'wp-optimize'));
100
101 $body = json_decode($result['body']);
102
103 if (isset($body->error) && $body->error) return new WP_Error('Gzip', __("We can't definitely determine Gzip status as API doesn't return correct answer.", 'wp-optimize'));
104
105 if ($body->result->gzipenabled && !$body->error) {
106 return true;
107 }
108
109 return false;
110 }
111
112 /**
113 * Check if Gzip compression is enabled.
114 *
115 * @param boolean $force_check - force the check
116 * @return bool|WP_Error
117 */
118 public function is_gzip_compression_enabled($force_check = false) {
119
120 if (!$force_check) return WP_Optimize()->get_options()->get_option('is_gzip_compression_enabled');
121
122 // trying to get info about gzip in headers.
123 $headers_info = $this->get_headers_information();
124
125 // we can't determine then return WP_Error.
126 if (is_wp_error($headers_info)) return $headers_info;
127
128 $is_gzip_compression_enabled = $headers_info['compression'];
129
130 // if we got error then trying to get info from api otherwise get result from check_headers_for_gzip().
131 // $is_gzip_compression_enabled = is_wp_error($is_gzip_compression_enabled) ? $this->check_api_for_gzip() : $is_gzip_compression_enabled;
132
133 // if Gzip is not enabled, but we have added settings and Apache modules nt loaded then return error.
134 if (!$is_gzip_compression_enabled && $this->is_gzip_compression_section_exists()) {
135 if (false === $this->_wp_optimize->is_apache_module_loaded(array('mod_filter', 'mod_deflate'))) {
136 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'));
137 } elseif (WP_Optimize()->is_apache_server()) {
138 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'));
139 } else {
140 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'));
141 }
142 }
143
144 WP_Optimize()->get_options()->update_option('is_gzip_compression_enabled', $is_gzip_compression_enabled);
145
146 return $is_gzip_compression_enabled;
147 }
148
149 /**
150 * Check if section with Gzip options already exists in htaccess file.
151 *
152 * @return bool
153 */
154 public function is_gzip_compression_section_exists() {
155 return $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
156 }
157
158 /**
159 * Enable Gzip compression - add settings into .htaccess.
160 */
161 public function enable() {
162 $this->_htaccess->update_commented_section($this->prepare_gzip_section(), $this->_htaccess_section_comment);
163 $this->_htaccess->write_file();
164 }
165
166 /**
167 * Disable Gzip compression - remove settings from .htaccess.
168 */
169 public function disable() {
170 $this->_htaccess->remove_commented_section($this->_htaccess_section_comment);
171 $this->_htaccess->write_file();
172 }
173
174 /**
175 * Check if gzip compression option is set to true then add section with gzip settings into .htaccess (used when plugin being activated).
176 */
177 public function restore() {
178 $enabled = WP_Optimize()->get_options()->get_option('is_gzip_compression_enabled');
179
180 if ($enabled && $this->_htaccess->is_writable()) $this->enable();
181 }
182
183 /**
184 * Handler for Gzip compression enable command, called from WP_Optimize_Commands.
185 *
186 * @param array $params - ['enable' => true|false]
187 * @return array
188 */
189 public function enable_gzip_command_handler($params) {
190 $section_updated = false;
191
192 $enable = isset($params['enable']) && $params['enable'];
193
194 if ($this->_htaccess->is_writable()) {
195
196 // update commented section
197 if ($enable) {
198 $this->enable();
199 } else {
200 $this->disable();
201 }
202
203 // read updated file.
204 $this->_htaccess->read_file();
205 // check if section added or removed successfully.
206 $section_exists = $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
207 // set correct $section-updated flag.
208 $section_updated = $enable === $section_exists;
209 }
210
211 $is_gzip_compression_enabled = $this->is_gzip_compression_enabled(true);
212
213 if ($section_updated) {
214 return array(
215 'success' => true,
216 'enabled' => is_wp_error($is_gzip_compression_enabled) ? false : $is_gzip_compression_enabled,
217 // if we can't determine gzip status then return error message.
218 'message' => is_wp_error($is_gzip_compression_enabled) ? $is_gzip_compression_enabled->get_error_message() : '',
219 );
220 } else {
221 $gzip_section = $this->prepare_gzip_section();
222
223 if ($is_gzip_compression_enabled) {
224 // translators: %s is a file name
225 $message = sprintf(__("We can\'t update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to remove following lines manually:', 'wp-optimize');
226 } else {
227 // translators: %s is a file name
228 $message = sprintf(__("We can\'t update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to add following lines manually:', 'wp-optimize');
229 }
230
231 return array(
232 'success' => false,
233 'enabled' => is_wp_error($is_gzip_compression_enabled) ? false : $is_gzip_compression_enabled,
234 'message' => $message,
235 'output' =>
236 htmlentities($this->_htaccess->get_section_begin_comment($this->_htaccess_section_comment).PHP_EOL.
237 join(PHP_EOL, $this->_htaccess->get_flat_array($gzip_section)).
238 PHP_EOL.$this->_htaccess->get_section_end_comment($this->_htaccess_section_comment)),
239 );
240 }
241 }
242
243 /**
244 * Prepare array with options to switch on gzip in htaccess.
245 *
246 * @return array
247 */
248 private function prepare_gzip_section() {
249 return array(
250 array(
251 '<IfModule mod_filter.c>',
252 array(
253 '<IfModule mod_deflate.c>',
254 '# Compress HTML, CSS, JavaScript, Text, XML and fonts',
255 'AddType application/vnd.ms-fontobject .eot',
256 'AddType font/ttf .ttf',
257 'AddType font/otf .otf',
258 'AddType font/x-woff .woff',
259 'AddType image/svg+xml .svg',
260 '',
261 'AddOutputFilterByType DEFLATE application/javascript',
262 'AddOutputFilterByType DEFLATE application/rss+xml',
263 'AddOutputFilterByType DEFLATE application/vnd.ms-fontobject',
264 'AddOutputFilterByType DEFLATE application/x-font',
265 'AddOutputFilterByType DEFLATE application/x-font-opentype',
266 'AddOutputFilterByType DEFLATE application/x-font-otf',
267 'AddOutputFilterByType DEFLATE application/x-font-truetype',
268 'AddOutputFilterByType DEFLATE application/x-font-ttf',
269 'AddOutputFilterByType DEFLATE application/x-font-woff',
270 'AddOutputFilterByType DEFLATE application/x-javascript',
271 'AddOutputFilterByType DEFLATE application/xhtml+xml',
272 'AddOutputFilterByType DEFLATE application/xml',
273 'AddOutputFilterByType DEFLATE font/opentype',
274 'AddOutputFilterByType DEFLATE font/otf',
275 'AddOutputFilterByType DEFLATE font/ttf',
276 'AddOutputFilterByType DEFLATE font/woff',
277 'AddOutputFilterByType DEFLATE image/svg+xml',
278 'AddOutputFilterByType DEFLATE image/x-icon',
279 'AddOutputFilterByType DEFLATE text/css',
280 'AddOutputFilterByType DEFLATE text/html',
281 'AddOutputFilterByType DEFLATE text/javascript',
282 'AddOutputFilterByType DEFLATE text/plain',
283 'AddOutputFilterByType DEFLATE text/xml',
284 '',
285 '# Remove browser bugs (only needed for really old browsers)',
286 'BrowserMatch ^Mozilla/4 gzip-only-text/html',
287 'BrowserMatch ^Mozilla/4\.0[678] no-gzip',
288 'BrowserMatch \bMSIE !no-gzip !gzip-only-text/html',
289 array(
290 '<IfModule mod_headers.c>',
291 'Header append Vary User-Agent',
292 '</IfModule>',
293 ),
294 '</IfModule>',
295 ),
296 '</IfModule>',
297 ),
298 );
299 }
300 }
301