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

296 lines 10.7 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 $this->disable();
71 } elseif (array_key_exists('content-encoding', $headers) && preg_match('/gzip/i', $headers['content-encoding'])) {
72 // check if there exists Content-encoding header with gzip value.
73 $headers_information['compression'] = 'gzip';
74
75 } else {
76 $headers_information['compression'] = false;
77 }
78
79 return $headers_information;
80 }
81
82 /**
83 * Make request to checkgzipcompression.com api and check if gzip option enabled.
84 *
85 * @return bool|WP_Error
86 */
87 public function check_api_for_gzip() {
88 $url = get_template_directory_uri() . '/style.css';
89
90 $api_url = 'https://checkgzipcompression.com/js/checkgzip.json?url=' . urlencode($url);
91
92 $result = wp_remote_get($api_url, array('timeout' => 10));
93
94 if (is_wp_error($result)) return $result;
95
96 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'));
97
98 $body = json_decode($result['body']);
99
100 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'));
101
102 if ($body->result->gzipenabled && !$body->error) {
103 return true;
104 }
105
106 return false;
107 }
108
109 /**
110 * Check if Gzip compression is enabled.
111 *
112 * @param boolean $force_check - force the check
113 * @return bool|WP_Error
114 */
115 public function is_gzip_compression_enabled($force_check = false) {
116
117 if (!$force_check) return WP_Optimize()->get_options()->get_option('is_gzip_compression_enabled');
118
119 // trying to get info about gzip in headers.
120 $headers_info = $this->get_headers_information();
121
122 // we can't determine then return WP_Error.
123 if (is_wp_error($headers_info)) return $headers_info;
124
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()) {
132 if (false === $this->_wp_optimize->is_apache_module_loaded(array('mod_filter', 'mod_deflate'))) {
133 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 } elseif (WP_Optimize()->is_apache_server()) {
135 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'));
136 } else {
137 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 }
139 }
140
141 WP_Optimize()->get_options()->update_option('is_gzip_compression_enabled', $is_gzip_compression_enabled);
142
143 return $is_gzip_compression_enabled;
144 }
145
146 /**
147 * Check if section with Gzip options already exists in htaccess file.
148 *
149 * @return bool
150 */
151 public function is_gzip_compression_section_exists() {
152 return $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
153 }
154
155 /**
156 * Enable Gzip compression - add settings into .htaccess.
157 */
158 public function enable() {
159 $this->_htaccess->update_commented_section($this->prepare_gzip_section(), $this->_htaccess_section_comment);
160 $this->_htaccess->write_file();
161 }
162
163 /**
164 * Disable Gzip compression - remove settings from .htaccess.
165 */
166 public function disable() {
167 $this->_htaccess->remove_commented_section($this->_htaccess_section_comment);
168 $this->_htaccess->write_file();
169 }
170
171 /**
172 * Check if gzip compression option is set to true then add section with gzip settings into .htaccess (used when plugin being activated).
173 */
174 public function restore() {
175 $enabled = WP_Optimize()->get_options()->get_option('is_gzip_compression_enabled');
176
177 if ($enabled && $this->_htaccess->is_writable()) $this->enable();
178 }
179
180 /**
181 * Handler for Gzip compression enable command, called from WP_Optimize_Commands.
182 *
183 * @param array $params - ['enable' => true|false]
184 * @return array
185 */
186 public function enable_gzip_command_handler($params) {
187 $section_updated = false;
188
189 $enable = (isset($params['enable']) && $params['enable']) ? true : false;
190
191 if ($this->_htaccess->is_writable()) {
192
193 // update commented section
194 if ($enable) {
195 $this->enable();
196 } else {
197 $this->disable();
198 }
199
200 // read updated file.
201 $this->_htaccess->read_file();
202 // check if section added or removed successfully.
203 $section_exists = $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
204 // set correct $section-updated flag.
205 $section_updated = $enable === $section_exists;
206 }
207
208 $is_gzip_compression_enabled = $this->is_gzip_compression_enabled(true);
209
210 if ($section_updated) {
211 return array(
212 'success' => true,
213 'enabled' => is_wp_error($is_gzip_compression_enabled) ? false : $is_gzip_compression_enabled,
214 // if we can't determine gzip status then return error message.
215 'message' => is_wp_error($is_gzip_compression_enabled) ? $is_gzip_compression_enabled->get_error_message() : '',
216 );
217 } else {
218 $gzip_section = $this->prepare_gzip_section();
219
220 if ($is_gzip_compression_enabled) {
221 $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 } else {
223 $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 }
225
226 return array(
227 'success' => false,
228 'enabled' => is_wp_error($is_gzip_compression_enabled) ? false : $is_gzip_compression_enabled,
229 'message' => $message,
230 'output' =>
231 htmlentities($this->_htaccess->get_section_begin_comment($this->_htaccess_section_comment).PHP_EOL.
232 join(PHP_EOL, $this->_htaccess->get_flat_array($gzip_section)).
233 PHP_EOL.$this->_htaccess->get_section_end_comment($this->_htaccess_section_comment)),
234 );
235 }
236 }
237
238 /**
239 * Prepare array with options to switch on gzip in htaccess.
240 *
241 * @return array
242 */
243 private function prepare_gzip_section() {
244 return array(
245 array(
246 '<IfModule mod_filter.c>',
247 array(
248 '<IfModule mod_deflate.c>',
249 '# Compress HTML, CSS, JavaScript, Text, XML and fonts',
250 'AddType application/vnd.ms-fontobject .eot',
251 'AddType font/ttf .ttf',
252 'AddType font/otf .otf',
253 'AddType font/x-woff .woff',
254 'AddType image/svg+xml .svg',
255 '',
256 'AddOutputFilterByType DEFLATE application/javascript',
257 'AddOutputFilterByType DEFLATE application/rss+xml',
258 'AddOutputFilterByType DEFLATE application/vnd.ms-fontobject',
259 'AddOutputFilterByType DEFLATE application/x-font',
260 'AddOutputFilterByType DEFLATE application/x-font-opentype',
261 'AddOutputFilterByType DEFLATE application/x-font-otf',
262 'AddOutputFilterByType DEFLATE application/x-font-truetype',
263 'AddOutputFilterByType DEFLATE application/x-font-ttf',
264 'AddOutputFilterByType DEFLATE application/x-font-woff',
265 'AddOutputFilterByType DEFLATE application/x-javascript',
266 'AddOutputFilterByType DEFLATE application/xhtml+xml',
267 'AddOutputFilterByType DEFLATE application/xml',
268 'AddOutputFilterByType DEFLATE font/opentype',
269 'AddOutputFilterByType DEFLATE font/otf',
270 'AddOutputFilterByType DEFLATE font/ttf',
271 'AddOutputFilterByType DEFLATE font/woff',
272 'AddOutputFilterByType DEFLATE image/svg+xml',
273 'AddOutputFilterByType DEFLATE image/x-icon',
274 'AddOutputFilterByType DEFLATE text/css',
275 'AddOutputFilterByType DEFLATE text/html',
276 'AddOutputFilterByType DEFLATE text/javascript',
277 'AddOutputFilterByType DEFLATE text/plain',
278 'AddOutputFilterByType DEFLATE text/xml',
279 '',
280 '# Remove browser bugs (only needed for really old browsers)',
281 'BrowserMatch ^Mozilla/4 gzip-only-text/html',
282 'BrowserMatch ^Mozilla/4\.0[678] no-gzip',
283 'BrowserMatch \bMSIE !no-gzip !gzip-only-text/html',
284 array(
285 '<IfModule mod_headers.c>',
286 'Header append Vary User-Agent',
287 '</IfModule>',
288 ),
289 '</IfModule>',
290 ),
291 '</IfModule>',
292 ),
293 );
294 }
295 }
296