PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 2.2.11
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v2.2.11
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 3.8.0 All 110 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 2.2.11, at includes/class-wp-optimize-browser-cache.php

286 lines 8.2 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 * Check headers for Cache-Control and Etag. And if they are exist return true.
38 *
39 * @return bool|WP_Error
40 */
41 public function is_cache_enabled() {
42 $style = get_template_directory_uri() . '/style.css';
43
44 $response = wp_remote_get($style, array('timeout' => 15));
45
46 if (is_a($response, 'WP_Error')) return $response;
47
48 $headers = wp_remote_retrieve_headers($response);
49
50 if (is_a($headers, 'Requests_Utility_CaseInsensitiveDictionary')) {
51 $headers = $headers->getAll();
52 }
53
54 if (false === array_key_exists('etag', $headers) && array_key_exists('cache-control', $headers)) {
55 return true;
56 }
57
58 if ($this->is_browser_cache_section_exists() && !$this->_wp_optimize->is_apache_module_loaded(array('mod_expires', 'mod_headers'))) {
59 return new WP_Error('Browser cache', __('We successfully updated your .htaccess file. But it seems one of Apache modules - mod_expires or mod_headers is not active.', 'wp-optimize'));
60 }
61
62 return false;
63 }
64
65 /**
66 * Enable browser cache - add settings into .htaccess.
67 *
68 * @param string $expiry_time
69 */
70 public function enable($expiry_time = '1 month') {
71 $this->_htaccess->update_commented_section($this->prepare_browser_cache_section($expiry_time), $this->_htaccess_section_comment);
72 $this->_htaccess->write_file();
73 }
74
75 /**
76 * Disable cache - remove settings from .htaccess added in enable() function.
77 */
78 public function disable() {
79 $this->_htaccess->remove_commented_section($this->_htaccess_section_comment);
80 $this->_htaccess->write_file();
81 }
82
83 /**
84 * Check if section with browser cache settings already exists.
85 */
86 public function is_browser_cache_section_exists() {
87 return $this->_htaccess->is_commented_section_exists($this->_htaccess_section_comment);
88 }
89
90 /**
91 * Handle for enable_browser_cache command used in WP_Optimize_Commands.
92 *
93 * @param array $params - ['browser_cache_expire' => '1 month 15 days 2 hours' || '' - for disable cache]
94 * @return array
95 */
96 public function enable_browser_cache_command_handler($params) {
97 $expire_days = isset($params['browser_cache_expire_days']) ? $params['browser_cache_expire_days'] : '';
98 $expire_hours = isset($params['browser_cache_expire_hours']) ? $params['browser_cache_expire_hours'] : '';
99
100 $current_expire_days = $this->_options->get_option('browser_cache_expire_days', '');
101 $current_expire_hours = $this->_options->get_option('browser_cache_expire_hours', '');
102
103 $section_updated = false;
104
105 $expiry_time = $this->prepare_interval($expire_days, $expire_hours);
106
107 $enable = ('' == $expiry_time) ? false : true;
108
109 /**
110 * If we don't need to do anything in .htaccess then return message.
111 */
112 if ($enable == $this->_htaccess->is_commented_section_exists() && $expire_days == $current_expire_days && $expire_hours == $current_expire_hours) {
113 $message = __('Browser static caching settings already exists in the .htaccess file', 'wp-optimize');
114
115 return array(
116 'success' => true,
117 'enabled' => $enable,
118 'message' => $message,
119 );
120 }
121
122 if ($this->_htaccess->is_writable()) {
123 // update commented section
124
125 if ($enable) {
126 $this->enable($expiry_time);
127 } else {
128 $this->disable();
129 }
130
131 // read updated file.
132 $this->_htaccess->read_file();
133 // check if section added or removed successfully.
134 $section_exists = $this->_htaccess->is_commented_section_exists();
135 // set correct $section-updated flag.
136 $section_updated = $enable === $section_exists;
137 }
138
139 if ($section_updated) {
140 $enabled = $this->is_cache_enabled();
141
142 // save $expire value to options.
143 $this->_options->update_option('browser_cache_expire_days', $expire_days);
144 $this->_options->update_option('browser_cache_expire_hours', $expire_hours);
145
146 if (is_wp_error($enabled)) {
147 return array(
148 'success' => true,
149 'enabled' => $enabled,
150 'error_message' => $enabled->get_error_message(),
151 );
152 } else {
153 return array(
154 'success' => true,
155 'enabled' => $enabled,
156 'message' => __('We successfully updated your .htaccess file.', 'wp-optimize'),
157 );
158 }
159 } else {
160 $cache_section = $this->prepare_browser_cache_section($expiry_time);
161
162 if ($enable) {
163 $message = sprintf(__('We can\'t update your %s file. Please try to add following lines manually:', 'wp-optimize'), $this->_htaccess->get_filename());
164 $output = htmlentities($this->_htaccess->get_section_begin_comment() . PHP_EOL .
165 join(PHP_EOL, $this->_htaccess->get_flat_array($cache_section)).
166 PHP_EOL . $this->_htaccess->get_section_end_comment());
167 } else {
168 $message = sprintf(__('We can\'t update your %s file. Please try to remove following lines manually:', 'wp-optimize'), $this->_htaccess->get_filename());
169 $output = htmlentities($this->_htaccess->get_section_begin_comment() . PHP_EOL .
170 ' ... ... ... '.
171 PHP_EOL . $this->_htaccess->get_section_end_comment());
172 }
173
174 return array(
175 'success' => false,
176 'enabled' => $this->is_cache_enabled(),
177 'error_message' => $message,
178 'output' => $output,
179 );
180 }
181 }
182
183 /**
184 * 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.
185 *
186 * @param int $days
187 * @param int $hours
188 * @return string
189 */
190 private function prepare_interval($days, $hours) {
191
192 $days = floor($days);
193 $hours = floor($hours);
194
195 if (0 == $days && 0 == $hours) {
196 return '';
197 }
198
199 $parts = array();
200
201 // if hours value more than one day then fix it.
202 $days += floor($hours / 24);
203 $hours = $hours % 24;
204
205 $years = floor($days / 365);
206 $days = $days % 365;
207 $months = floor($days / 30);
208 $days = $days % 30;
209
210 if ($years > 0) {
211 $parts[] = $years . ($years > 1 ? ' years' : ' year');
212 }
213
214 if ($months > 0) {
215 $parts[] = $months . ($months > 1 ? ' months' : ' month');
216 }
217
218 if ($days > 0) {
219 $parts[] = $days . ($days > 1 ? ' days' : ' day');
220 }
221
222 if ($hours > 0) {
223 $parts[] = $hours . ($hours > 1 ? ' hours' : ' hour');
224 }
225
226 return join(' ', $parts);
227 }
228
229 /**
230 * Build browser cache section array.
231 *
232 * @param string $expire - value like - 1 day 12 hours 15 minutes
233 * @return array
234 */
235 public function prepare_browser_cache_section($expire) {
236 return array(
237 array(
238 '<IfModule mod_expires.c>',
239 'ExpiresActive On',
240 'ExpiresByType text/css "access '.$expire.'"',
241 'ExpiresByType text/html "access '.$expire.'"',
242 'ExpiresByType image/gif "access '.$expire.'"',
243 'ExpiresByType image/png "access '.$expire.'"',
244 'ExpiresByType image/jpg "access '.$expire.'"',
245 'ExpiresByType image/jpeg "access '.$expire.'"',
246 'ExpiresByType image/webp "access '.$expire.'"',
247 'ExpiresByType image/x-icon "access '.$expire.'"',
248 'ExpiresByType application/pdf "access '.$expire.'"',
249 'ExpiresByType application/javascript "access '.$expire.'"',
250 'ExpiresByType text/x-javascript "access '.$expire.'"',
251 'ExpiresByType application/x-shockwave-flash "access '.$expire.'"',
252 'ExpiresDefault "access '.$expire.'"',
253 '</IfModule>',
254 ),
255 '',
256 array(
257 '<IfModule mod_headers.c>',
258 array(
259 '<filesMatch "\.(ico|jpe?g|png|gif|webp|swf)$">',
260 'Header set Cache-Control "public"',
261 '</filesMatch>',
262 ),
263 array(
264 '<filesMatch "\.(css)$">',
265 'Header set Cache-Control "public"',
266 '</filesMatch>',
267 ),
268 array(
269 '<filesMatch "\.(js)$">',
270 'Header set Cache-Control "private"',
271 '</filesMatch>',
272 ),
273 array(
274 '<filesMatch "\.(x?html?|php)$">',
275 'Header set Cache-Control "private, must-revalidate"',
276 '</filesMatch>',
277 ),
278 '</IfModule>',
279 ),
280 '',
281 '#Disable ETag',
282 'FileETag None',
283 );
284 }
285 }
286