PluginProbe
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions / trunk
s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions vtrunk
260909 260829 260814 260805 110710 110731 110812 110815 110912 110913 110915 110926 110927 111002 111003 111011 111017 111029 111105 111206 111216 111220 120213 120219 120301 All 187 releases
s2member / src / includes / classes / no-cache.inc.php

no-cache.inc.php in s2Member – Excellent for All Kinds of Memberships, Content Restriction Paywalls & Member Access Subscriptions trunk, at src/includes/classes/no-cache.inc.php

389 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // @codingStandardsIgnoreFile
3 /**
4 * No-cache routines.
5 *
6 * Copyright: © 2009-2011
7 * {@link http://websharks-inc.com/ WebSharks, Inc.}
8 * (coded in the USA)
9 *
10 * Released under the terms of the GNU General Public License.
11 * You should have received a copy of the GNU General Public License,
12 * along with this software. In the main directory, see: /licensing/
13 * If not, see: {@link http://www.gnu.org/licenses/}.
14 *
15 * @package s2Member\No_Cache
16 * @since 3.5
17 */
18 if(!defined('WPINC')) // MUST have WordPress.
19 exit ('Do not access this file directly.');
20
21 if(!class_exists('c_ws_plugin__s2member_no_cache'))
22 {
23 /**
24 * No-cache routines.
25 *
26 * @package s2Member\No_Cache
27 * @since 3.5
28 */
29 class c_ws_plugin__s2member_no_cache
30 {
31 /**
32 * No-cache headers required?
33 *
34 * @package s2Member\No_Cache
35 * @since 111115
36 *
37 * @var null|bool
38 */
39 public static $headers;
40
41 /**
42 * Sets up no-cache header behavior mode.
43 *
44 * This runs on `init` so s2Member options are available (options are configured after hooks are included).
45 *
46 * @package s2Member\No_Cache
47 * @since 260307
48 *
49 * @attaches-to ``add_action('init');``
50 *
51 * @return void
52 */
53 public static function setup_no_cache_headers_mode()
54 {
55 static $once; // Run only once per request.
56
57 if($once)
58 return;
59
60 $once = TRUE;
61
62 $mode = (!empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['no_cache_headers_mode']))
63 ? (string)$GLOBALS['WS_PLUGIN__']['s2member']['o']['no_cache_headers_mode']
64 : 'always';
65
66 if($mode === 'evaluative' || !empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['no_cache_headers_debug']))
67 add_filter('wp_headers', 'c_ws_plugin__s2member_no_cache::no_cache_wp_headers', 9999); //260309 Run last; also adds debug header in all modes when enabled.
68
69 if($mode === 'evaluative')
70 {
71 add_filter('ws_plugin__s2member_no_cache_headers_selective', '__return_true');
72 c_ws_plugin__s2member_no_cache::no_cache_constants(FALSE);
73
74 add_action('wp', 'c_ws_plugin__s2member_no_cache::evaluative_no_cache_scan', 3); //260308 Rename staged scan to evaluative scan.
75 }
76 else
77 {
78 if($mode === 'selective')
79 add_filter('ws_plugin__s2member_no_cache_headers_selective', '__return_true');
80
81 c_ws_plugin__s2member_no_cache::no_cache(FALSE);
82 }
83 }
84
85 /**
86 * Evaluative mode: scans queried post content for s2Member shortcodes before headers are sent.
87 *
88 * Shortcodes execute after headers (during rendering), so evaluative mode must pre-detect likely s2Member
89 * shortcodes to ensure no-cache headers are applied when needed.
90 *
91 * @package s2Member\No_Cache
92 * @since 260307
93 *
94 * @attaches-to ``add_action('wp');``
95 *
96 * @return void
97 */
98 public static function evaluative_no_cache_scan()
99 {
100 if(!is_singular())
101 return;
102
103 $post = get_queried_object();
104 if(!is_object($post) || empty($post->post_content) || !is_string($post->post_content))
105 return;
106
107 //260307 Conservative pre-detection of s2Member shortcodes in post content.
108 // This intentionally errs on the safe side (prevents caching) for any `[s2...` usage.
109 if(stripos($post->post_content, '[s2') !== FALSE)
110 c_ws_plugin__s2member_no_cache::no_cache_constants(true);
111 }
112
113 /**
114 * Handles no-cache constants, and no-cache headers.
115 *
116 * @package s2Member\No_Cache
117 * @since 3.5
118 *
119 * @attaches-to ``add_action('init');``
120 * @also-called-by Other routines within s2Member.
121 *
122 * @param bool $no_cache Optional. Defaults to false. If true, force no-cache if at all possible.
123 *
124 * @return bool This function will always return `true`.
125 */
126 public static function no_cache($no_cache = FALSE)
127 {
128 do_action('ws_plugin__s2member_before_no_cache', get_defined_vars());
129
130 c_ws_plugin__s2member_no_cache::no_cache_constants($no_cache).c_ws_plugin__s2member_no_cache::no_cache_headers($no_cache);
131
132 do_action('ws_plugin__s2member_after_no_cache', get_defined_vars());
133
134 return TRUE; // Always return true.
135 }
136
137 /**
138 * Defines no-cache constants for various WordPress plugins.
139 *
140 * This is compatible with Quick Cache, W3 Total Cache, and also with WP Super Cache.
141 * Quick Cache uses: ``QUICK_CACHE_ALLOWED``, and other plugins use: ``DONOTCACHEPAGE``.
142 * W3 Total Cache is also known to be compatible with ``DONOTCACHEOBJECT`` and ``DONOTCACHEDB``.
143 *
144 * Disallow caching if the ``$no_cache`` parameter is passed in as ``true``, by other routines.
145 * In addition, always disallow caching for logged in users, and GET requests with: `/?s2member` Systematics.
146 * For clarity on s2Member Systematics, see: {@link s2Member\Systematics\c_ws_plugin__s2member_systematics::is_s2_systematic_use_page()}.
147 *
148 * However, this routine will ALWAYS obey the `?qcAC` query string parameter.
149 * This Quick Cache parameter explicitly allows caching to occur.
150 *
151 * @package s2Member\No_Cache
152 * @since 3.5
153 *
154 * @also-called-by Other routines within s2Member.
155 *
156 * @param bool $no_cache Optional. Defaults to false. If true, force no-cache if at all possible.
157 *
158 * @return bool This function will always return `true`.
159 */
160 public static function no_cache_constants($no_cache = FALSE)
161 {
162 static $once; // We only need to set these constants once.
163
164 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
165 do_action('ws_plugin__s2member_before_no_cache_constants', get_defined_vars());
166 unset($__refs, $__v); // Housekeeping.
167
168 if(!$once && (empty($_GET['qcAC']) || !filter_var($_GET['qcAC'], FILTER_VALIDATE_BOOLEAN))
169 && (
170 $no_cache === TRUE // Forces no-cache constants; if `TRUE` explicitly.
171 || ($no_cache === 'restricted' && (!defined('COMET_CACHE_WHEN_LOGGED_IN') || !COMET_CACHE_WHEN_LOGGED_IN) && (!defined('ZENCACHE_WHEN_LOGGED_IN') || !ZENCACHE_WHEN_LOGGED_IN) && (!defined('QUICK_CACHE_WHEN_LOGGED_IN') || !QUICK_CACHE_WHEN_LOGGED_IN))
172 || (is_user_logged_in() && (!defined('COMET_CACHE_WHEN_LOGGED_IN') || !COMET_CACHE_WHEN_LOGGED_IN) && (!defined('ZENCACHE_WHEN_LOGGED_IN') || !ZENCACHE_WHEN_LOGGED_IN) && (!defined('QUICK_CACHE_WHEN_LOGGED_IN') || !QUICK_CACHE_WHEN_LOGGED_IN))
173 || c_ws_plugin__s2member_systematics::is_s2_systematic_use_page()
174 )
175 )
176 {
177 /**
178 * No-cache DB queries for plugins.
179 *
180 * @package s2Member\No_Cache
181 * @since 111115
182 *
183 * @var bool
184 */
185 if(!defined('DONOTCACHEDB'))
186 define('DONOTCACHEDB', TRUE);
187
188 /**
189 * No-cache Page for plugins.
190 *
191 * @package s2Member\No_Cache
192 * @since 3.5
193 *
194 * @var bool
195 */
196 if(!defined('DONOTCACHEPAGE'))
197 define('DONOTCACHEPAGE', TRUE);
198
199 /**
200 * No-cache Objects for plugins.
201 *
202 * @package s2Member\No_Cache
203 * @since 111115
204 *
205 * @var bool
206 */
207 if(!defined('DONOTCACHEOBJECT'))
208 define('DONOTCACHEOBJECT', TRUE);
209
210 /**
211 * No-cache anything for Comet Cache plugin.
212 *
213 * @package s2Member\No_Cache
214 * @since 160222
215 *
216 * @var bool
217 */
218 if(!defined('COMET_CACHE_ALLOWED'))
219 define('COMET_CACHE_ALLOWED', FALSE);
220
221 /**
222 * No-cache anything for ZenCache plugin.
223 *
224 * @package s2Member\No_Cache
225 * @since 3.5
226 *
227 * @var bool
228 */
229 if(!defined('ZENCACHE_ALLOWED'))
230 define('ZENCACHE_ALLOWED', FALSE);
231
232 /**
233 * No-cache anything for Quick Cache plugin.
234 *
235 * @package s2Member\No_Cache
236 * @since 3.5
237 *
238 * @var bool
239 */
240 if(!defined('QUICK_CACHE_ALLOWED'))
241 define('QUICK_CACHE_ALLOWED', FALSE);
242
243 $once = TRUE; // Set these one time only.
244
245 c_ws_plugin__s2member_no_cache::$headers = TRUE;
246
247 do_action('ws_plugin__s2member_during_no_cache_constants', get_defined_vars());
248 }
249 do_action('ws_plugin__s2member_after_no_cache_constants', get_defined_vars());
250
251 return TRUE; // Always return true.
252 }
253
254 /**
255 * Filters HTTP headers (wp_headers) to apply no-cache headers when needed.
256 *
257 * This is used by the `evaluative` no-cache headers mode. It allows s2Member runtime checks/shortcodes
258 * (e.g., `[s2If]`) to set no-cache constants/flags during rendering, while still applying no-cache
259 * headers during WordPress's standard header-sending stage (wp_headers/send_headers).
260 *
261 * Obeys `?qcABC`, `?zcABC`, and `?ccABC` query string parameters, which explicitly allow caching.
262 *
263 * @package s2Member\No_Cache
264 * @since 260307
265 *
266 * @param array $headers An associative array of HTTP headers.
267 *
268 * @return array Possibly modified headers.
269 */
270 public static function no_cache_wp_headers($headers = array())
271 {
272 static $once; // We only need to filter these headers one time.
273
274 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
275 do_action('ws_plugin__s2member_before_no_cache_headers', get_defined_vars());
276 unset($__refs, $__v); // Housekeeping.
277
278 $mode = (!empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['no_cache_headers_mode']))
279 ? (string)$GLOBALS['WS_PLUGIN__']['s2member']['o']['no_cache_headers_mode']
280 : 'always';
281 $no_cache = (bool)apply_filters('ws_plugin__s2member_no_cache', FALSE, get_defined_vars());
282 $using_selective_behavior = (bool)apply_filters('ws_plugin__s2member_no_cache_headers_selective', FALSE, get_defined_vars());
283
284 if($mode === 'evaluative' && !$no_cache && $using_selective_behavior && !c_ws_plugin__s2member_no_cache::$headers) //260309 Evaluative mode: pre-detect s2 shortcodes in queried content.
285 {
286 global $wp_query;
287
288 if(!empty($wp_query) && !empty($wp_query->post) && is_object($wp_query->post) && !empty($wp_query->post->post_content))
289 if(stripos((string)$wp_query->post->post_content, '[s2') !== FALSE)
290 c_ws_plugin__s2member_no_cache::$headers = TRUE;
291 }
292
293 //260308 Debug header (support use only).
294 if(!empty($GLOBALS['WS_PLUGIN__']['s2member']['o']['no_cache_headers_debug']))
295 {
296 $_st = 's2member;desc="mode='.$mode.';no_cache='.(int)$no_cache.';selective='.(int)$using_selective_behavior.';headers='.(int)c_ws_plugin__s2member_no_cache::$headers.'"';
297
298 if(!empty($headers['Server-Timing']))
299 $headers['Server-Timing'] .= ', '.$_st;
300 else
301 $headers['Server-Timing'] = $_st;
302
303 unset($_st); // Housekeeping.
304 }
305
306 if($mode === 'evaluative' && !$once
307 && (empty($_GET['ccABC']) || !filter_var($_GET['ccABC'], FILTER_VALIDATE_BOOLEAN))
308 && (empty($_GET['zcABC']) || !filter_var($_GET['zcABC'], FILTER_VALIDATE_BOOLEAN))
309 && (empty($_GET['qcABC']) || !filter_var($_GET['qcABC'], FILTER_VALIDATE_BOOLEAN))
310 && ($no_cache || !$using_selective_behavior || c_ws_plugin__s2member_no_cache::$headers)
311 )
312 if(!apply_filters('ws_plugin__s2member_disable_no_cache_headers', FALSE, get_defined_vars()))
313 {
314 $nocache_headers = wp_get_nocache_headers();
315
316 foreach(array('Expires', 'Cache-Control', 'Pragma') as $_k)
317 if(isset($headers[$_k])) unset($headers[$_k]);
318
319 foreach((array)$nocache_headers as $_k => $_v)
320 $headers[$_k] = $_v;
321
322 unset($_k, $_v); // Housekeeping.
323
324 $once = TRUE; // This is static var. Only apply once.
325
326 do_action('ws_plugin__s2member_during_no_cache_headers', get_defined_vars());
327 }
328 do_action('ws_plugin__s2member_after_no_cache_headers', get_defined_vars());
329
330 return $headers;
331 }
332
333 /**
334 * Sends Cache-Control (no-cache) headers.
335 *
336 * Disallow browser caching if the ``$no_cache`` parameter is passed in as ``true``, by other routines.
337 * Disallow browser caching when/if no-cache Constants are set by {@link s2Member\No_Cache\c_ws_plugin__s2member_no_cache::no_cache_constants()},
338 * via static variable boolean value for: ``c_ws_plugin__s2member_no_cache::$headers``.
339 *
340 * However, this routine will ALWAYS obey the `?qcABC` query string parameter.
341 * This Quick Cache parameter explicitly allows browser caching to occur.
342 *
343 * @package s2Member\No_Cache
344 * @since 3.5
345 *
346 * @also-called-by Other routines within s2Member.
347 *
348 * @param bool $no_cache Optional. Defaults to false. If true, force no-cache if at all possible.
349 *
350 * @return bool This function will always return `true`.
351 */
352 public static function no_cache_headers($no_cache = FALSE)
353 {
354 static $once; // We only need to set these headers one time.
355
356 foreach(array_keys(get_defined_vars()) as $__v) $__refs[$__v] =& $$__v;
357 do_action('ws_plugin__s2member_before_no_cache_headers', get_defined_vars());
358 unset($__refs, $__v); // Housekeeping.
359
360 $using_selective_behavior = apply_filters('ws_plugin__s2member_no_cache_headers_selective', FALSE, get_defined_vars());
361
362 if(!$once && !headers_sent() // Only once, and only if possible.
363 && (empty($_GET['ccABC']) || !filter_var($_GET['ccABC'], FILTER_VALIDATE_BOOLEAN))
364 && (empty($_GET['zcABC']) || !filter_var($_GET['zcABC'], FILTER_VALIDATE_BOOLEAN))
365 && (empty($_GET['qcABC']) || !filter_var($_GET['qcABC'], FILTER_VALIDATE_BOOLEAN))
366 && ($no_cache || !$using_selective_behavior || c_ws_plugin__s2member_no_cache::$headers)
367 )
368 if(!apply_filters('ws_plugin__s2member_disable_no_cache_headers', FALSE, get_defined_vars()))
369 {
370 foreach(headers_list() as $header) // No-cache headers already sent? We need to check here.
371 if(stripos($header, 'no-cache') !== FALSE) // No-cache headers already sent?
372 {
373 $no_cache_headers_already_sent = TRUE; // Yep, sent.
374 break; // Break now, no need to continue further.
375 }
376 if(!isset ($no_cache_headers_already_sent)) // Not yet?
377 nocache_headers(); // Only if NOT already sent.
378
379 $once = TRUE; // This is static var. Only send headers once.
380
381 do_action('ws_plugin__s2member_during_no_cache_headers', get_defined_vars());
382 }
383 do_action('ws_plugin__s2member_after_no_cache_headers', get_defined_vars());
384
385 return TRUE; // Always return true.
386 }
387 }
388 }
389