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

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