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

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