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

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