PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.20
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.20
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-browser-cache.php

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

313 lines 9.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 if (!defined('WPO_VERSION')) die('No direct access allowed');
4
5 require_once 'class-wp-optimize-htaccess.php';
6
7 /**
8 * Class WP_Optimize_Browser_Cache
9 */
10 class WP_Optimize_Browser_Cache {
11
12 private $_htaccess = null;
13
14 private $_options = null;
15
16 private $_wp_optimize = null;
17
18 /**
19 * Browser cache section in htaccess will wrapped with this comment
20 *
21 * @var string
22 */
23 private $_htaccess_section_comment = 'WP-Optimize Browser Cache';
24
25 /**
26 * WP_Optimize_Browser_Cache constructor.
27 */
28 public function __construct() {
29 $this->_wp_optimize = WP_Optimize();
30
31 $this->_htaccess = new WP_Optimize_Htaccess();
32
33 $this->_options = $this->_wp_optimize->get_options();
34 }
35
36 /**
37 * Returns singleton instance object
38 *
39 * @return WP_Optimize_Browser_Cache Returns `WP_Optimize_Browser_Cache` object
40 */
41 public static function instance() {
42 static $_instance = null;
43 if (null === $_instance) {
44 $_instance = new self();
45 }
46 return $_instance;
47 }
48
49 /**
50 * Check headers for Cache-Control and Etag. And if they are exist return true.
51 *
52 * @return bool|WP_Error
53 **/
54 public function is_enabled() {
55
56 static $is_enabled;
57 if (isset($is_enabled)) return $is_enabled;
58
59 $headers = WP_Optimize()->get_stylesheet_headers();
60
61 if (is_wp_error($headers)) return $headers;
62
63 if (array_key_exists('cache-control', $headers) && array_key_exists('expires', $headers)) {
64 $is_enabled = true;
65 } else {
66 $is_enabled = false;
67 }
68
69 if ($this->is_browser_cache_section_exists() && false === $this->_wp_optimize->is_apache_module_loaded(array('mod_expires', 'mod_headers'))) {
70 $is_enabled = new WP_Error('Browser cache', __('We successfully updated your .htaccess file.', 'wp-optimize') . ' ' . __('But it seems one of Apache modules - mod_expires or mod_headers is not active.', 'wp-optimize'));
71 }
72
73 return $is_enabled;
74 }
75
76 /**
77 * Enable browser cache - add settings into .htaccess.
78 *
79 * @param string $expiry_time
80 */
81 public function enable($expiry_time = '1 month') {
82 $this->_htaccess->update_commented_section($this->prepare_browser_cache_section($expiry_time), $this->_htaccess_section_comment);
83 $this->_htaccess->write_file();
84 $this->_options->update_option('enable_browser_cache', true);
85 }
86
87 /**
88 * Disable cache - remove settings from .htaccess added in enable() function.
89 */
90 public function disable() {
91 $this->_htaccess->remove_commented_section($this->_htaccess_section_comment);
92 $this->_htaccess->write_file();
93 $this->_options->update_option('enable_browser_cache', false);
94 }
95
96 /**
97 * Check if browser cache option is set to true then add section with gzip settings into .htaccess (used when plugin being activated).
98 */
99 public function restore() {
100 $expire_days = $this->_options->get_option('browser_cache_expire_days', '');
101 $expire_hours = $this->_options->get_option('browser_cache_expire_hours', '');
102
103 $expiry_time = $this->prepare_interval($expire_days, $expire_hours);
104
105 $enabled = ('' == $expiry_time) ? false : true;
106
107 if ($enabled && $this->_htaccess->is_writable()) $this->enable($expiry_time);
108 }
109
110 /**
111 * Check if section with browser cache settings already exists.
112 */
113 public function is_browser_cache_section_exists() {
114 return $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
115 }
116
117 /**
118 * Handle for enable_browser_cache command used in WP_Optimize_Commands.
119 *
120 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
121 * @return array
122 */
123 public function enable_browser_cache_command_handler($params) {
124 $expire_days = isset($params['browser_cache_expire_days']) ? $params['browser_cache_expire_days'] : '';
125 $expire_hours = isset($params['browser_cache_expire_hours']) ? $params['browser_cache_expire_hours'] : '';
126
127 $current_expire_days = $this->_options->get_option('browser_cache_expire_days', '');
128 $current_expire_hours = $this->_options->get_option('browser_cache_expire_hours', '');
129
130 $section_updated = false;
131
132 $expiry_time = $this->prepare_interval($expire_days, $expire_hours);
133
134 $enable = ('' == $expiry_time) ? false : true;
135
136 /**
137 * If we don't need to do anything in .htaccess then return message.
138 */
139 if ($enable == $this->_htaccess->is_commented_section_exists() && $expire_days == $current_expire_days && $expire_hours == $current_expire_hours) {
140 $message = __('Browser static caching settings already exists in the .htaccess file', 'wp-optimize');
141
142 return array(
143 'success' => true,
144 'enabled' => $enable,
145 'message' => $message,
146 );
147 }
148
149 if ($this->_htaccess->is_writable()) {
150 // update commented section
151
152 if ($enable) {
153 $this->enable($expiry_time);
154 } else {
155 $this->disable();
156 }
157
158 // read updated file.
159 $this->_htaccess->read_file();
160 // check if section added or removed successfully.
161 $section_exists = $this->_htaccess->is_commented_section_exists();
162 // set correct $section-updated flag.
163 $section_updated = $enable === $section_exists;
164 }
165
166 if ($section_updated) {
167 $enabled = $this->is_enabled();
168
169 // save $expire value to options.
170 $this->_options->update_option('browser_cache_expire_days', $expire_days);
171 $this->_options->update_option('browser_cache_expire_hours', $expire_hours);
172
173 if (is_wp_error($enabled)) {
174 return array(
175 'success' => true,
176 'enabled' => $enabled,
177 'error_message' => $enabled->get_error_message(),
178 );
179 } else {
180 return array(
181 'success' => true,
182 'enabled' => $enabled,
183 'message' => __('We successfully updated your .htaccess file.', 'wp-optimize'),
184 );
185 }
186 } else {
187 $cache_section = $this->prepare_browser_cache_section($expiry_time);
188
189 if ($enable) {
190 $message = sprintf(__("We can\'t update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to add following lines manually:', 'wp-optimize');
191 $output = htmlentities($this->_htaccess->get_section_begin_comment() . PHP_EOL .
192 join(PHP_EOL, $this->_htaccess->get_flat_array($cache_section)).
193 PHP_EOL . $this->_htaccess->get_section_end_comment());
194 } else {
195 $message = sprintf(__("We can\'t update your %s file.", 'wp-optimize'), $this->_htaccess->get_filename()) . ' ' . __('Please try to remove following lines manually:', 'wp-optimize');
196 $output = htmlentities($this->_htaccess->get_section_begin_comment() . PHP_EOL .
197 ' ... ... ... '.
198 PHP_EOL . $this->_htaccess->get_section_end_comment());
199 }
200
201 return array(
202 'success' => false,
203 'enabled' => $this->is_enabled(),
204 'error_message' => $message,
205 'output' => $output,
206 );
207 }
208 }
209
210 /**
211 * Use $days an $hours values to build correct time interval as a string like '2 days 3 hours' or empty string if date is empty.
212 *
213 * @param int $days
214 * @param int $hours
215 * @return string
216 */
217 private function prepare_interval($days, $hours) {
218
219 $days = is_numeric($days) ? floor($days) : 0;
220 $hours = is_numeric($hours) ? floor($hours) : 0;
221
222 if (0 == $days && 0 == $hours) {
223 return '';
224 }
225
226 $parts = array();
227
228 // if hours value more than one day then fix it.
229 $days += floor($hours / 24);
230 $hours = $hours % 24;
231
232 $years = floor($days / 365);
233 $days = $days % 365;
234 $months = floor($days / 30);
235 $days = $days % 30;
236
237 if ($years > 0) {
238 $parts[] = $years . ($years > 1 ? ' years' : ' year');
239 }
240
241 if ($months > 0) {
242 $parts[] = $months . ($months > 1 ? ' months' : ' month');
243 }
244
245 if ($days > 0) {
246 $parts[] = $days . ($days > 1 ? ' days' : ' day');
247 }
248
249 if ($hours > 0) {
250 $parts[] = $hours . ($hours > 1 ? ' hours' : ' hour');
251 }
252
253 return join(' ', $parts);
254 }
255
256 /**
257 * Build browser cache section array.
258 *
259 * @param string $expire - value like - 1 day 12 hours 15 minutes
260 * @return array
261 */
262 public function prepare_browser_cache_section($expire) {
263 return array(
264 array(
265 '<IfModule mod_expires.c>',
266 'ExpiresActive On',
267 'ExpiresByType text/css "access '.$expire.'"',
268 'ExpiresByType text/html "access '.$expire.'"',
269 'ExpiresByType image/gif "access '.$expire.'"',
270 'ExpiresByType image/png "access '.$expire.'"',
271 'ExpiresByType image/jpg "access '.$expire.'"',
272 'ExpiresByType image/jpeg "access '.$expire.'"',
273 'ExpiresByType image/webp "access '.$expire.'"',
274 'ExpiresByType image/x-icon "access '.$expire.'"',
275 'ExpiresByType application/pdf "access '.$expire.'"',
276 'ExpiresByType application/javascript "access '.$expire.'"',
277 'ExpiresByType text/x-javascript "access '.$expire.'"',
278 'ExpiresByType application/x-shockwave-flash "access '.$expire.'"',
279 'ExpiresDefault "access '.$expire.'"',
280 '</IfModule>',
281 ),
282 '',
283 array(
284 '<IfModule mod_headers.c>',
285 array(
286 '<filesMatch "\.(ico|jpe?g|png|gif|webp|swf)$">',
287 'Header set Cache-Control "public"',
288 '</filesMatch>',
289 ),
290 array(
291 '<filesMatch "\.(css)$">',
292 'Header set Cache-Control "public"',
293 '</filesMatch>',
294 ),
295 array(
296 '<filesMatch "\.(js)$">',
297 'Header set Cache-Control "private"',
298 '</filesMatch>',
299 ),
300 array(
301 '<filesMatch "\.(x?html?|php)$">',
302 'Header set Cache-Control "private, must-revalidate"',
303 '</filesMatch>',
304 ),
305 '</IfModule>',
306 ),
307 '',
308 '#Disable ETag',
309 'FileETag None',
310 );
311 }
312 }
313