PluginProbe ʕ •ᴥ•ʔ
LiteSpeed Cache / 7.6.1
LiteSpeed Cache v7.6.1
trunk 1.0.15 1.9.1.1 2.9.9.2 3.6.4 4.6 5.7.0.1 6.5.4 7.0.0.1 7.0.1 7.1 7.2 7.3 7.3.0.1 7.4 7.5 7.5.0.1 7.6 7.6.1 7.6.2 7.7 7.8 7.8.0.1 7.8.1
litespeed-cache / src / vary.cls.php
litespeed-cache / src Last commit date
cdn 7 months ago data_structure 7 months ago activation.cls.php 7 months ago admin-display.cls.php 7 months ago admin-settings.cls.php 7 months ago admin.cls.php 7 months ago api.cls.php 7 months ago avatar.cls.php 7 months ago base.cls.php 7 months ago cdn.cls.php 7 months ago cloud.cls.php 7 months ago conf.cls.php 7 months ago control.cls.php 7 months ago core.cls.php 7 months ago crawler-map.cls.php 7 months ago crawler.cls.php 7 months ago css.cls.php 7 months ago data.cls.php 7 months ago data.upgrade.func.php 7 months ago db-optm.cls.php 7 months ago debug2.cls.php 7 months ago doc.cls.php 7 months ago error.cls.php 7 months ago esi.cls.php 7 months ago file.cls.php 7 months ago gui.cls.php 7 months ago health.cls.php 7 months ago htaccess.cls.php 7 months ago img-optm.cls.php 7 months ago import.cls.php 7 months ago import.preset.cls.php 7 months ago lang.cls.php 7 months ago localization.cls.php 7 months ago media.cls.php 7 months ago metabox.cls.php 7 months ago object-cache-wp.cls.php 7 months ago object-cache.cls.php 7 months ago object.lib.php 7 months ago optimize.cls.php 7 months ago optimizer.cls.php 7 months ago placeholder.cls.php 7 months ago purge.cls.php 7 months ago report.cls.php 7 months ago rest.cls.php 7 months ago root.cls.php 7 months ago router.cls.php 7 months ago str.cls.php 7 months ago tag.cls.php 7 months ago task.cls.php 7 months ago tool.cls.php 7 months ago ucss.cls.php 7 months ago utility.cls.php 7 months ago vary.cls.php 7 months ago vpi.cls.php 7 months ago
vary.cls.php
774 lines
1 <?php
2 // phpcs:ignoreFile
3
4 /**
5 * The plugin vary class to manage X-LiteSpeed-Vary
6 *
7 * @since 1.1.3
8 */
9
10 namespace LiteSpeed;
11
12 defined('WPINC') || exit();
13
14 class Vary extends Root {
15
16 const LOG_TAG = '🔱';
17 const X_HEADER = 'X-LiteSpeed-Vary';
18
19 private static $_vary_name = '_lscache_vary'; // this default vary cookie is used for logged in status check
20 private static $_can_change_vary = false; // Currently only AJAX used this
21
22 /**
23 * Adds the actions used for setting up cookies on log in/out.
24 *
25 * Also checks if the database matches the rewrite rule.
26 *
27 * @since 1.0.4
28 */
29 // public function init()
30 // {
31 // $this->_update_vary_name();
32 // }
33
34 /**
35 * Update the default vary name if changed
36 *
37 * @since 4.0
38 * @since 7.0 Moved to after_user_init to allow ESI no-vary no conflict w/ LSCACHE_VARY_COOKIE/O_CACHE_LOGIN_COOKIE
39 */
40 private function _update_vary_name() {
41 $db_cookie = $this->conf(Base::O_CACHE_LOGIN_COOKIE); // [3.0] todo: check if works in network's sites
42 // If no vary set in rewrite rule
43 if (!isset($_SERVER['LSCACHE_VARY_COOKIE'])) {
44 if ($db_cookie) {
45 // Check if is from ESI req or not. If from ESI no-vary, no need to set no-cache
46 $something_wrong = true;
47 if (!empty($_GET[ESI::QS_ACTION]) && !empty($_GET['_control'])) {
48 // Have to manually build this checker bcoz ESI is not init yet.
49 $control = explode(',', $_GET['_control']);
50 if (in_array('no-vary', $control)) {
51 self::debug('no-vary control existed, bypass vary_name update');
52 $something_wrong = false;
53 self::$_vary_name = $db_cookie;
54 }
55 }
56
57 if (defined('LITESPEED_CLI') || wp_doing_cron()) {
58 $something_wrong = false;
59 }
60
61 if ($something_wrong) {
62 // Display cookie error msg to admin
63 if (is_multisite() ? is_network_admin() : is_admin()) {
64 Admin_Display::show_error_cookie();
65 }
66 Control::set_nocache('❌❌ vary cookie setting error');
67 }
68 }
69 return;
70 }
71 // If db setting does not exist, skip checking db value
72 if (!$db_cookie) {
73 return;
74 }
75
76 // beyond this point, need to make sure db vary setting is in $_SERVER env.
77 $vary_arr = explode(',', $_SERVER['LSCACHE_VARY_COOKIE']);
78
79 if (in_array($db_cookie, $vary_arr)) {
80 self::$_vary_name = $db_cookie;
81 return;
82 }
83
84 if (is_multisite() ? is_network_admin() : is_admin()) {
85 Admin_Display::show_error_cookie();
86 }
87 Control::set_nocache('vary cookie setting lost error');
88 }
89
90 /**
91 * Hooks after user init
92 *
93 * @since 4.0
94 */
95 public function after_user_init() {
96 $this->_update_vary_name();
97
98 // logged in user
99 if (Router::is_logged_in()) {
100 // If not esi, check cache logged-in user setting
101 if (!$this->cls('Router')->esi_enabled()) {
102 // If cache logged-in, then init cacheable to private
103 if ($this->conf(Base::O_CACHE_PRIV) && !is_admin()) {
104 add_action('wp_logout', __NAMESPACE__ . '\Purge::purge_on_logout');
105
106 $this->cls('Control')->init_cacheable();
107 Control::set_private('logged in user');
108 }
109 // No cache for logged-in user
110 else {
111 Control::set_nocache('logged in user');
112 }
113 }
114 // ESI is on, can be public cache
115 elseif (!is_admin()) {
116 // Need to make sure vary is using group id
117 $this->cls('Control')->init_cacheable();
118 }
119
120 // register logout hook to clear login status
121 add_action('clear_auth_cookie', array( $this, 'remove_logged_in' ));
122 } else {
123 // Only after vary init, can detect if is Guest mode or not
124 // Here need `self::$_vary_name` to be set first.
125 $this->_maybe_guest_mode();
126
127 // Set vary cookie for logging in user, otherwise the user will hit public with vary=0 (guest version)
128 add_action('set_logged_in_cookie', array( $this, 'add_logged_in' ), 10, 4);
129 add_action('wp_login', __NAMESPACE__ . '\Purge::purge_on_logout');
130
131 $this->cls('Control')->init_cacheable();
132
133 // Check `login page` cacheable setting because they don't go through main WP logic
134 add_action('login_init', array( $this->cls('Tag'), 'check_login_cacheable' ), 5);
135
136 if (!empty($_GET['litespeed_guest'])) {
137 add_action('wp_loaded', array( $this, 'update_guest_vary' ), 20);
138 }
139 }
140
141 // Add comment list ESI
142 add_filter('comments_array', array( $this, 'check_commenter' ));
143
144 // Set vary cookie for commenter.
145 add_action('set_comment_cookies', array( $this, 'append_commenter' ));
146
147 /**
148 * Don't change for REST call because they don't carry on user info usually
149 *
150 * @since 1.6.7
151 */
152 add_action('rest_api_init', function () {
153 // this hook is fired in `init` hook
154 self::debug('Rest API init disabled vary change');
155 add_filter('litespeed_can_change_vary', '__return_false');
156 });
157 }
158
159 /**
160 * Check if is Guest mode or not
161 *
162 * @since 4.0
163 */
164 private function _maybe_guest_mode() {
165 if (defined('LITESPEED_GUEST')) {
166 self::debug('👒👒 Guest mode ' . (LITESPEED_GUEST ? 'predefined' : 'turned off'));
167 return;
168 }
169
170 if (!$this->conf(Base::O_GUEST)) {
171 return;
172 }
173
174 // If vary is set, then not a guest
175 if (self::has_vary()) {
176 return;
177 }
178
179 // If has admin QS, then no guest
180 if (!empty($_GET[Router::ACTION])) {
181 return;
182 }
183
184 if (wp_doing_ajax()) {
185 return;
186 }
187
188 if (wp_doing_cron()) {
189 return;
190 }
191
192 // If is the request to update vary, then no guest
193 // Don't need anymore as it is always ajax call
194 // Still keep it in case some WP blocked the lightweight guest vary update script, WP can still update the vary
195 if (!empty($_GET['litespeed_guest'])) {
196 return;
197 }
198
199 /* @ref https://wordpress.org/support/topic/checkout-add-to-cart-executed-twice/ */
200 if (!empty($_GET['litespeed_guest_off'])) {
201 return;
202 }
203
204 self::debug('👒👒 Guest mode');
205
206 !defined('LITESPEED_GUEST') && define('LITESPEED_GUEST', true);
207
208 if ($this->conf(Base::O_GUEST_OPTM)) {
209 !defined('LITESPEED_GUEST_OPTM') && define('LITESPEED_GUEST_OPTM', true);
210 }
211 }
212
213 /**
214 * Update Guest vary
215 *
216 * @since 4.0
217 * @deprecated 4.1 Use independent lightweight guest.vary.php as a replacement
218 */
219 public function update_guest_vary() {
220 // This process must not be cached
221 !defined('LSCACHE_NO_CACHE') && define('LSCACHE_NO_CACHE', true);
222
223 $_guest = new Lib\Guest();
224 if ($_guest->always_guest() || self::has_vary()) {
225 // If contains vary already, don't reload to avoid infinite loop when parent page having browser cache
226 !defined('LITESPEED_GUEST') && define('LITESPEED_GUEST', true); // Reuse this const to bypass set vary in vary finalize
227 self::debug('🤠🤠 Guest');
228 echo '[]';
229 exit();
230 }
231
232 self::debug('Will update guest vary in finalize');
233
234 // return json
235 echo \json_encode(array( 'reload' => 'yes' ));
236 exit();
237 }
238
239 /**
240 * Hooked to the comments_array filter.
241 *
242 * Check if the user accessing the page has the commenter cookie.
243 *
244 * If the user does not want to cache commenters, just check if user is commenter.
245 * Otherwise if the vary cookie is set, unset it. This is so that when the page is cached, the page will appear as if the user was a normal user.
246 * Normal user is defined as not a logged in user and not a commenter.
247 *
248 * @since 1.0.4
249 * @access public
250 * @global type $post
251 * @param array $comments The current comments to output
252 * @return array The comments to output.
253 */
254 public function check_commenter( $comments ) {
255 /**
256 * Hook to bypass pending comment check for comment related plugins compatibility
257 *
258 * @since 2.9.5
259 */
260 if (apply_filters('litespeed_vary_check_commenter_pending', true)) {
261 $pending = false;
262 foreach ($comments as $comment) {
263 if (!$comment->comment_approved) {
264 // current user has pending comment
265 $pending = true;
266 break;
267 }
268 }
269
270 // No pending comments, don't need to add private cache
271 if (!$pending) {
272 self::debug('No pending comment');
273 $this->remove_commenter();
274
275 // Remove commenter prefilled info if exists, for public cache
276 foreach ($_COOKIE as $cookie_name => $cookie_value) {
277 if (strlen($cookie_name) >= 15 && strpos($cookie_name, 'comment_author_') === 0) {
278 unset($_COOKIE[$cookie_name]);
279 }
280 }
281
282 return $comments;
283 }
284 }
285
286 // Current user/visitor has pending comments
287 // set vary=2 for next time vary lookup
288 $this->add_commenter();
289
290 if ($this->conf(Base::O_CACHE_COMMENTER)) {
291 Control::set_private('existing commenter');
292 } else {
293 Control::set_nocache('existing commenter');
294 }
295
296 return $comments;
297 }
298
299 /**
300 * Check if default vary has a value
301 *
302 * @since 1.1.3
303 * @access public
304 */
305 public static function has_vary() {
306 if (empty($_COOKIE[self::$_vary_name])) {
307 return false;
308 }
309 return $_COOKIE[self::$_vary_name];
310 }
311
312 /**
313 * Append user status with logged in
314 *
315 * @since 1.1.3
316 * @since 1.6.2 Removed static referral
317 * @access public
318 */
319 public function add_logged_in( $logged_in_cookie = false, $expire = false, $expiration = false, $uid = false ) {
320 self::debug('add_logged_in');
321
322 /**
323 * NOTE: Run before `$this->_update_default_vary()` to make vary changeable
324 *
325 * @since 2.2.2
326 */
327 self::can_ajax_vary();
328
329 // If the cookie is lost somehow, set it
330 $this->_update_default_vary($uid, $expire);
331 }
332
333 /**
334 * Remove user logged in status
335 *
336 * @since 1.1.3
337 * @since 1.6.2 Removed static referral
338 * @access public
339 */
340 public function remove_logged_in() {
341 self::debug('remove_logged_in');
342
343 /**
344 * NOTE: Run before `$this->_update_default_vary()` to make vary changeable
345 *
346 * @since 2.2.2
347 */
348 self::can_ajax_vary();
349
350 // Force update vary to remove login status
351 $this->_update_default_vary(-1);
352 }
353
354 /**
355 * Allow vary can be changed for ajax calls
356 *
357 * @since 2.2.2
358 * @since 2.6 Changed to static
359 * @access public
360 */
361 public static function can_ajax_vary() {
362 self::debug('_can_change_vary -> true');
363 self::$_can_change_vary = true;
364 }
365
366 /**
367 * Check if can change default vary
368 *
369 * @since 1.6.2
370 * @access private
371 */
372 private function can_change_vary() {
373 // Don't change for ajax due to ajax not sending webp header
374 if (Router::is_ajax()) {
375 if (!self::$_can_change_vary) {
376 self::debug('can_change_vary bypassed due to ajax call');
377 return false;
378 }
379 }
380
381 /**
382 * POST request can set vary to fix #820789 login "loop" guest cache issue
383 *
384 * @since 1.6.5
385 */
386 if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] !== 'GET' && $_SERVER['REQUEST_METHOD'] !== 'POST') {
387 self::debug('can_change_vary bypassed due to method not get/post');
388 return false;
389 }
390
391 /**
392 * Disable vary change if is from crawler
393 *
394 * @since 2.9.8 To enable woocommerce cart not empty warm up (@Taba)
395 */
396 if (!empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], Crawler::FAST_USER_AGENT) === 0) {
397 self::debug('can_change_vary bypassed due to crawler');
398 return false;
399 }
400
401 if (!apply_filters('litespeed_can_change_vary', true)) {
402 self::debug('can_change_vary bypassed due to litespeed_can_change_vary hook');
403 return false;
404 }
405
406 return true;
407 }
408
409 /**
410 * Update default vary
411 *
412 * @since 1.6.2
413 * @since 1.6.6.1 Add ran check to make it only run once ( No run multiple times due to login process doesn't have valid uid )
414 * @access private
415 */
416 private function _update_default_vary( $uid = false, $expire = false ) {
417 // Make sure header output only run once
418 if (!defined('LITESPEED_DID_' . __FUNCTION__)) {
419 define('LITESPEED_DID_' . __FUNCTION__, true);
420 } else {
421 self::debug2('_update_default_vary bypassed due to run already');
422 return;
423 }
424
425 // ESI shouldn't change vary (Let main page do only)
426 if (defined('LSCACHE_IS_ESI') && LSCACHE_IS_ESI) {
427 self::debug2('_update_default_vary bypassed due to ESI');
428 return;
429 }
430
431 // If the cookie is lost somehow, set it
432 $vary = $this->finalize_default_vary($uid);
433 $current_vary = self::has_vary();
434 if ($current_vary !== $vary && $current_vary !== 'commenter' && $this->can_change_vary()) {
435 // $_COOKIE[ self::$_vary_name ] = $vary; // not needed
436
437 // save it
438 if (!$expire) {
439 $expire = time() + 2 * DAY_IN_SECONDS;
440 }
441 $this->_cookie($vary, $expire);
442 // Control::set_nocache( 'changing default vary' . " $current_vary => $vary" );
443 }
444 }
445
446 /**
447 * Get vary name
448 *
449 * @since 1.9.1
450 * @access public
451 */
452 public function get_vary_name() {
453 return self::$_vary_name;
454 }
455
456 /**
457 * Check if one user role is in vary group settings
458 *
459 * @since 1.2.0
460 * @since 3.0 Moved here from conf.cls
461 * @access public
462 * @param string $role The user role
463 * @return int The set value if already set
464 */
465 public function in_vary_group( $role ) {
466 $group = 0;
467 $vary_groups = $this->conf(Base::O_CACHE_VARY_GROUP);
468
469 $roles = explode(',', $role);
470 if ($found = array_intersect($roles, array_keys($vary_groups))) {
471 $groups = array();
472 foreach ($found as $curr_role) {
473 $groups[] = $vary_groups[$curr_role];
474 }
475 $group = implode(',', array_unique($groups));
476 } elseif (in_array('administrator', $roles)) {
477 $group = 99;
478 }
479
480 if ($group) {
481 self::debug2('role in vary_group [group] ' . $group);
482 }
483
484 return $group;
485 }
486
487 /**
488 * Finalize default Vary Cookie
489 *
490 * Get user vary tag based on admin_bar & role
491 *
492 * NOTE: Login process will also call this because it does not call wp hook as normal page loading
493 *
494 * @since 1.6.2
495 * @access public
496 */
497 public function finalize_default_vary( $uid = false ) {
498 // Must check this to bypass vary generation for guests
499 // Must check this to avoid Guest page's CSS/JS/CCSS/UCSS get non-guest vary filename
500 if (defined('LITESPEED_GUEST') && LITESPEED_GUEST) {
501 return false;
502 }
503
504 $vary = array();
505
506 if ($this->conf(Base::O_GUEST)) {
507 $vary['guest_mode'] = 1;
508 }
509
510 if (!$uid) {
511 $uid = get_current_user_id();
512 } else {
513 self::debug('uid: ' . $uid);
514 }
515
516 // get user's group id
517 $role = Router::get_role($uid);
518
519 if ($uid > 0 && $role) {
520 $vary['logged-in'] = 1;
521
522 // parse role group from settings
523 if ($role_group = $this->in_vary_group($role)) {
524 $vary['role'] = $role_group;
525 }
526
527 // Get admin bar set
528 // see @_get_admin_bar_pref()
529 $pref = get_user_option('show_admin_bar_front', $uid);
530 self::debug2('show_admin_bar_front: ' . $pref);
531 $admin_bar = $pref === false || $pref === 'true';
532
533 if ($admin_bar) {
534 $vary['admin_bar'] = 1;
535 self::debug2('admin bar : true');
536 }
537 } else {
538 // Guest user
539 self::debug('role id: failed, guest');
540 }
541
542 /**
543 * Add filter
544 *
545 * @since 1.6 Added for Role Excludes for optimization cls
546 * @since 1.6.2 Hooked to webp (checked in v4, no webp anymore)
547 * @since 3.0 Used by 3rd hooks too
548 */
549 $vary = apply_filters('litespeed_vary', $vary);
550
551 if (!$vary) {
552 return false;
553 }
554
555 ksort($vary);
556 $res = array();
557 foreach ($vary as $key => $val) {
558 $res[] = $key . ':' . $val;
559 }
560
561 $res = implode(';', $res);
562 if (defined('LSCWP_LOG')) {
563 return $res;
564 }
565 // Encrypt in production
566 return md5($this->conf(Base::HASH) . $res);
567 }
568
569 /**
570 * Get the hash of all vary related values
571 *
572 * @since 4.0
573 */
574 public function finalize_full_varies() {
575 $vary = $this->_finalize_curr_vary_cookies(true);
576 $vary .= $this->finalize_default_vary(get_current_user_id());
577 $vary .= $this->get_env_vary();
578 return $vary;
579 }
580
581 /**
582 * Get request environment Vary
583 *
584 * @since 4.0
585 */
586 public function get_env_vary() {
587 $env_vary = isset($_SERVER['LSCACHE_VARY_VALUE']) ? $_SERVER['LSCACHE_VARY_VALUE'] : false;
588 if (!$env_vary) {
589 $env_vary = isset($_SERVER['HTTP_X_LSCACHE_VARY_VALUE']) ? $_SERVER['HTTP_X_LSCACHE_VARY_VALUE'] : false;
590 }
591 return $env_vary;
592 }
593
594 /**
595 * Append user status with commenter
596 *
597 * This is ONLY used when submit a comment
598 *
599 * @since 1.1.6
600 * @access public
601 */
602 public function append_commenter() {
603 $this->add_commenter(true);
604 }
605
606 /**
607 * Correct user status with commenter
608 *
609 * @since 1.1.3
610 * @access private
611 * @param boolean $from_redirect If the request is from redirect page or not
612 */
613 private function add_commenter( $from_redirect = false ) {
614 // If the cookie is lost somehow, set it
615 if (self::has_vary() !== 'commenter') {
616 self::debug('Add commenter');
617 // $_COOKIE[ self::$_vary_name ] = 'commenter'; // not needed
618
619 // save it
620 // only set commenter status for current domain path
621 $this->_cookie('commenter', time() + apply_filters('comment_cookie_lifetime', 30000000), self::_relative_path($from_redirect));
622 // Control::set_nocache( 'adding commenter status' );
623 }
624 }
625
626 /**
627 * Remove user commenter status
628 *
629 * @since 1.1.3
630 * @access private
631 */
632 private function remove_commenter() {
633 if (self::has_vary() === 'commenter') {
634 self::debug('Remove commenter');
635 // remove logged in status from global var
636 // unset( $_COOKIE[ self::$_vary_name ] ); // not needed
637
638 // save it
639 $this->_cookie(false, false, self::_relative_path());
640 // Control::set_nocache( 'removing commenter status' );
641 }
642 }
643
644 /**
645 * Generate relative path for cookie
646 *
647 * @since 1.1.3
648 * @access private
649 * @param boolean $from_redirect If the request is from redirect page or not
650 */
651 private static function _relative_path( $from_redirect = false ) {
652 $path = false;
653 $tag = $from_redirect ? 'HTTP_REFERER' : 'SCRIPT_URL';
654 if (!empty($_SERVER[$tag])) {
655 $path = parse_url($_SERVER[$tag]);
656 $path = !empty($path['path']) ? $path['path'] : false;
657 self::debug('Cookie Vary path: ' . $path);
658 }
659 return $path;
660 }
661
662 /**
663 * Builds the vary header.
664 *
665 * NOTE: Non caccheable page can still set vary ( for logged in process )
666 *
667 * Currently, this only checks post passwords and 3rd party.
668 *
669 * @since 1.0.13
670 * @access public
671 * @global $post
672 * @return mixed false if the user has the postpass cookie. Empty string if the post is not password protected. Vary header otherwise.
673 */
674 public function finalize() {
675 // Finalize default vary
676 if (!defined('LITESPEED_GUEST') || !LITESPEED_GUEST) {
677 $this->_update_default_vary();
678 }
679
680 $tp_cookies = $this->_finalize_curr_vary_cookies();
681
682 if (!$tp_cookies) {
683 self::debug2('no custimzed vary');
684 return;
685 }
686
687 self::debug('finalized 3rd party cookies', $tp_cookies);
688
689 return self::X_HEADER . ': ' . implode(',', $tp_cookies);
690 }
691
692 /**
693 * Gets vary cookies or their values unique hash that are already added for the current page.
694 *
695 * @since 1.0.13
696 * @access private
697 * @return array List of all vary cookies currently added.
698 */
699 private function _finalize_curr_vary_cookies( $values_json = false ) {
700 global $post;
701
702 $cookies = array(); // No need to append default vary cookie name
703
704 if (!empty($post->post_password)) {
705 $postpass_key = 'wp-postpass_' . COOKIEHASH;
706 if ($this->_get_cookie_val($postpass_key)) {
707 self::debug('finalize bypassed due to password protected vary ');
708 // If user has password cookie, do not cache & ignore existing vary cookies
709 Control::set_nocache('password protected vary');
710 return false;
711 }
712
713 $cookies[] = $values_json ? $this->_get_cookie_val($postpass_key) : $postpass_key;
714 }
715
716 $cookies = apply_filters('litespeed_vary_curr_cookies', $cookies);
717 if ($cookies) {
718 $cookies = array_filter(array_unique($cookies));
719 self::debug('vary cookies changed by filter litespeed_vary_curr_cookies', $cookies);
720 }
721
722 if (!$cookies) {
723 return false;
724 }
725 // Format cookie name data or value data
726 sort($cookies); // This is to maintain the cookie val orders for $values_json=true case.
727 foreach ($cookies as $k => $v) {
728 $cookies[$k] = $values_json ? $this->_get_cookie_val($v) : 'cookie=' . $v;
729 }
730
731 return $values_json ? \json_encode($cookies) : $cookies;
732 }
733
734 /**
735 * Get one vary cookie value
736 *
737 * @since 4.0
738 */
739 private function _get_cookie_val( $key ) {
740 if (!empty($_COOKIE[$key])) {
741 return $_COOKIE[$key];
742 }
743
744 return false;
745 }
746
747 /**
748 * Set the vary cookie.
749 *
750 * If vary cookie changed, must set non cacheable.
751 *
752 * @since 1.0.4
753 * @access private
754 * @param int|false $val The value to update.
755 * @param int $expire Expire time.
756 * @param bool $path False if use wp root path as cookie path
757 */
758 private function _cookie( $val = false, $expire = 0, $path = false ) {
759 if (!$val) {
760 $expire = 1;
761 }
762
763 /**
764 * Add HTTPS bypass in case clients use both HTTP and HTTPS version of site
765 *
766 * @since 1.7
767 */
768 $is_ssl = $this->conf(Base::O_UTIL_NO_HTTPS_VARY) ? false : is_ssl();
769
770 setcookie(self::$_vary_name, $val, $expire, $path ?: COOKIEPATH, COOKIE_DOMAIN, $is_ssl, true);
771 self::debug('set_cookie ---> [k] ' . self::$_vary_name . " [v] $val [ttl] " . ($expire - time()));
772 }
773 }
774