Edit File by line
/home/zeestwma/richards.../wp-conte.../plugins/litespee.../src
File: control.cls.php
<?php
[0] Fix | Delete
/**
[1] Fix | Delete
* The plugin cache-control class for X-LiteSpeed-Cache-Control.
[2] Fix | Delete
*
[3] Fix | Delete
* Provides helpers for determining cacheability, emitting cache-control headers,
[4] Fix | Delete
* and honoring various LiteSpeed Cache configuration options.
[5] Fix | Delete
*
[6] Fix | Delete
* @package LiteSpeed
[7] Fix | Delete
* @since 1.1.3
[8] Fix | Delete
*/
[9] Fix | Delete
[10] Fix | Delete
namespace LiteSpeed;
[11] Fix | Delete
[12] Fix | Delete
defined( 'WPINC' ) || exit();
[13] Fix | Delete
[14] Fix | Delete
/**
[15] Fix | Delete
* Class Control
[16] Fix | Delete
*
[17] Fix | Delete
* Handles cache-control flags, TTL calculation, redirection checks,
[18] Fix | Delete
* role-based exclusions, and final header output.
[19] Fix | Delete
*/
[20] Fix | Delete
class Control extends Root {
[21] Fix | Delete
[22] Fix | Delete
const LOG_TAG = '💵';
[23] Fix | Delete
[24] Fix | Delete
const BM_CACHEABLE = 1;
[25] Fix | Delete
const BM_PRIVATE = 2;
[26] Fix | Delete
const BM_SHARED = 4;
[27] Fix | Delete
const BM_NO_VARY = 8;
[28] Fix | Delete
const BM_FORCED_CACHEABLE = 32;
[29] Fix | Delete
const BM_PUBLIC_FORCED = 64;
[30] Fix | Delete
const BM_STALE = 128;
[31] Fix | Delete
const BM_NOTCACHEABLE = 256;
[32] Fix | Delete
[33] Fix | Delete
const X_HEADER = 'X-LiteSpeed-Cache-Control';
[34] Fix | Delete
[35] Fix | Delete
/**
[36] Fix | Delete
* Bitmask control flags for current request.
[37] Fix | Delete
*
[38] Fix | Delete
* @var int
[39] Fix | Delete
*/
[40] Fix | Delete
protected static $_control = 0;
[41] Fix | Delete
[42] Fix | Delete
/**
[43] Fix | Delete
* Custom TTL for current request (seconds).
[44] Fix | Delete
*
[45] Fix | Delete
* @var int
[46] Fix | Delete
*/
[47] Fix | Delete
protected static $_custom_ttl = 0;
[48] Fix | Delete
[49] Fix | Delete
/**
[50] Fix | Delete
* Mapping of HTTP status codes to custom TTLs.
[51] Fix | Delete
*
[52] Fix | Delete
* @var array<string,int|string>
[53] Fix | Delete
*/
[54] Fix | Delete
private $_response_header_ttls = [];
[55] Fix | Delete
[56] Fix | Delete
/**
[57] Fix | Delete
* Init cache control.
[58] Fix | Delete
*
[59] Fix | Delete
* @since 1.6.2
[60] Fix | Delete
* @return void
[61] Fix | Delete
*/
[62] Fix | Delete
public function init() {
[63] Fix | Delete
/**
[64] Fix | Delete
* Add vary filter for Role Excludes.
[65] Fix | Delete
*
[66] Fix | Delete
* @since 1.6.2
[67] Fix | Delete
*/
[68] Fix | Delete
add_filter( 'litespeed_vary', [ $this, 'vary_add_role_exclude' ] );
[69] Fix | Delete
[70] Fix | Delete
// 301 redirect hook.
[71] Fix | Delete
add_filter( 'wp_redirect', [ $this, 'check_redirect' ], 10, 2 );
[72] Fix | Delete
[73] Fix | Delete
// Load response header conf.
[74] Fix | Delete
$this->_response_header_ttls = $this->conf( Base::O_CACHE_TTL_STATUS );
[75] Fix | Delete
foreach ( $this->_response_header_ttls as $k => $v ) {
[76] Fix | Delete
$v = explode( ' ', $v );
[77] Fix | Delete
if ( empty( $v[0] ) || empty( $v[1] ) ) {
[78] Fix | Delete
continue;
[79] Fix | Delete
}
[80] Fix | Delete
$this->_response_header_ttls[ $v[0] ] = $v[1];
[81] Fix | Delete
}
[82] Fix | Delete
[83] Fix | Delete
if ( $this->conf( Base::O_PURGE_STALE ) ) {
[84] Fix | Delete
$this->set_stale();
[85] Fix | Delete
}
[86] Fix | Delete
}
[87] Fix | Delete
[88] Fix | Delete
/**
[89] Fix | Delete
* Exclude role from optimization filter.
[90] Fix | Delete
*
[91] Fix | Delete
* @since 1.6.2
[92] Fix | Delete
* @access public
[93] Fix | Delete
*
[94] Fix | Delete
* @param array<string,mixed> $vary Existing vary map.
[95] Fix | Delete
* @return array<string,mixed>
[96] Fix | Delete
*/
[97] Fix | Delete
public function vary_add_role_exclude( $vary ) {
[98] Fix | Delete
if ( $this->in_cache_exc_roles() ) {
[99] Fix | Delete
$vary['role_exclude_cache'] = 1;
[100] Fix | Delete
}
[101] Fix | Delete
[102] Fix | Delete
return $vary;
[103] Fix | Delete
}
[104] Fix | Delete
[105] Fix | Delete
/**
[106] Fix | Delete
* Check if one user role is in exclude cache group settings.
[107] Fix | Delete
*
[108] Fix | Delete
* @since 1.6.2
[109] Fix | Delete
* @since 3.0 Moved here from conf.cls
[110] Fix | Delete
* @access public
[111] Fix | Delete
*
[112] Fix | Delete
* @param string|null $role The user role.
[113] Fix | Delete
* @return string|false Comma-separated roles if set, otherwise false.
[114] Fix | Delete
*/
[115] Fix | Delete
public function in_cache_exc_roles( $role = null ) {
[116] Fix | Delete
// Get user role.
[117] Fix | Delete
if ( null === $role ) {
[118] Fix | Delete
$role = Router::get_role();
[119] Fix | Delete
}
[120] Fix | Delete
[121] Fix | Delete
if ( ! $role ) {
[122] Fix | Delete
return false;
[123] Fix | Delete
}
[124] Fix | Delete
[125] Fix | Delete
$roles = explode( ',', $role );
[126] Fix | Delete
$found = array_intersect( $roles, $this->conf( Base::O_CACHE_EXC_ROLES ) );
[127] Fix | Delete
[128] Fix | Delete
return $found ? implode( ',', $found ) : false;
[129] Fix | Delete
}
[130] Fix | Delete
[131] Fix | Delete
/**
[132] Fix | Delete
* 1. Initialize cacheable status for `wp` hook
[133] Fix | Delete
* 2. Hook error page tags for cacheable pages
[134] Fix | Delete
*
[135] Fix | Delete
* @since 1.1.3
[136] Fix | Delete
* @access public
[137] Fix | Delete
* @return void
[138] Fix | Delete
*/
[139] Fix | Delete
public function init_cacheable() {
[140] Fix | Delete
// Hook `wp` to mark default cacheable status.
[141] Fix | Delete
// NOTE: Any process that does NOT run into `wp` hook will not get cacheable by default.
[142] Fix | Delete
add_action( 'wp', [ $this, 'set_cacheable' ], 5 );
[143] Fix | Delete
[144] Fix | Delete
// Hook WP REST to be cacheable.
[145] Fix | Delete
if ( $this->conf( Base::O_CACHE_REST ) ) {
[146] Fix | Delete
add_action( 'rest_api_init', [ $this, 'set_cacheable' ], 5 );
[147] Fix | Delete
}
[148] Fix | Delete
[149] Fix | Delete
// AJAX cache.
[150] Fix | Delete
$ajax_cache = $this->conf( Base::O_CACHE_AJAX_TTL );
[151] Fix | Delete
foreach ( $ajax_cache as $v ) {
[152] Fix | Delete
$v = explode( ' ', $v );
[153] Fix | Delete
if ( empty( $v[0] ) || empty( $v[1] ) ) {
[154] Fix | Delete
continue;
[155] Fix | Delete
}
[156] Fix | Delete
add_action(
[157] Fix | Delete
'wp_ajax_nopriv_' . $v[0],
[158] Fix | Delete
function () use ( $v ) {
[159] Fix | Delete
self::set_custom_ttl( $v[1] );
[160] Fix | Delete
self::force_cacheable( 'ajax Cache setting for action ' . $v[0] );
[161] Fix | Delete
},
[162] Fix | Delete
4
[163] Fix | Delete
);
[164] Fix | Delete
}
[165] Fix | Delete
[166] Fix | Delete
// Check error page.
[167] Fix | Delete
add_filter( 'status_header', [ $this, 'check_error_codes' ], 10, 2 );
[168] Fix | Delete
}
[169] Fix | Delete
[170] Fix | Delete
/**
[171] Fix | Delete
* Check if the page returns any error code.
[172] Fix | Delete
*
[173] Fix | Delete
* @since 1.0.13.1
[174] Fix | Delete
* @access public
[175] Fix | Delete
*
[176] Fix | Delete
* @param string $status_header Status header.
[177] Fix | Delete
* @param int $code HTTP status code.
[178] Fix | Delete
* @return string Original status header.
[179] Fix | Delete
*/
[180] Fix | Delete
public function check_error_codes( $status_header, $code ) {
[181] Fix | Delete
if ( array_key_exists( $code, $this->_response_header_ttls ) ) {
[182] Fix | Delete
if ( self::is_cacheable() && ! $this->_response_header_ttls[ $code ] ) {
[183] Fix | Delete
self::set_nocache( '[Ctrl] TTL is set to no cache [status_header] ' . $code );
[184] Fix | Delete
}
[185] Fix | Delete
[186] Fix | Delete
// Set TTL.
[187] Fix | Delete
self::set_custom_ttl( $this->_response_header_ttls[ $code ] );
[188] Fix | Delete
} elseif ( self::is_cacheable() ) {
[189] Fix | Delete
$first = substr( $code, 0, 1 );
[190] Fix | Delete
if ( '4' === $first || '5' === $first ) {
[191] Fix | Delete
self::set_nocache( '[Ctrl] 4xx/5xx default to no cache [status_header] ' . $code );
[192] Fix | Delete
}
[193] Fix | Delete
}
[194] Fix | Delete
[195] Fix | Delete
// Set cache tag.
[196] Fix | Delete
if ( in_array( $code, Tag::$error_code_tags, true ) ) {
[197] Fix | Delete
Tag::add( Tag::TYPE_HTTP . $code );
[198] Fix | Delete
}
[199] Fix | Delete
[200] Fix | Delete
// Give the default status_header back.
[201] Fix | Delete
return $status_header;
[202] Fix | Delete
}
[203] Fix | Delete
[204] Fix | Delete
/**
[205] Fix | Delete
* Set no vary setting.
[206] Fix | Delete
*
[207] Fix | Delete
* @access public
[208] Fix | Delete
* @since 1.1.3
[209] Fix | Delete
* @return void
[210] Fix | Delete
*/
[211] Fix | Delete
public static function set_no_vary() {
[212] Fix | Delete
if ( self::is_no_vary() ) {
[213] Fix | Delete
return;
[214] Fix | Delete
}
[215] Fix | Delete
self::$_control |= self::BM_NO_VARY;
[216] Fix | Delete
self::debug( 'X Cache_control -> no-vary', 3 );
[217] Fix | Delete
}
[218] Fix | Delete
[219] Fix | Delete
/**
[220] Fix | Delete
* Get no vary setting.
[221] Fix | Delete
*
[222] Fix | Delete
* @access public
[223] Fix | Delete
* @since 1.1.3
[224] Fix | Delete
* @return bool
[225] Fix | Delete
*/
[226] Fix | Delete
public static function is_no_vary() {
[227] Fix | Delete
return self::$_control & self::BM_NO_VARY;
[228] Fix | Delete
}
[229] Fix | Delete
[230] Fix | Delete
/**
[231] Fix | Delete
* Set stale.
[232] Fix | Delete
*
[233] Fix | Delete
* @access public
[234] Fix | Delete
* @since 1.1.3
[235] Fix | Delete
* @return void
[236] Fix | Delete
*/
[237] Fix | Delete
public function set_stale() {
[238] Fix | Delete
if ( self::is_stale() ) {
[239] Fix | Delete
return;
[240] Fix | Delete
}
[241] Fix | Delete
self::$_control |= self::BM_STALE;
[242] Fix | Delete
self::debug( 'X Cache_control -> stale' );
[243] Fix | Delete
}
[244] Fix | Delete
[245] Fix | Delete
/**
[246] Fix | Delete
* Get stale.
[247] Fix | Delete
*
[248] Fix | Delete
* @access public
[249] Fix | Delete
* @since 1.1.3
[250] Fix | Delete
* @return bool
[251] Fix | Delete
*/
[252] Fix | Delete
public static function is_stale() {
[253] Fix | Delete
return self::$_control & self::BM_STALE;
[254] Fix | Delete
}
[255] Fix | Delete
[256] Fix | Delete
/**
[257] Fix | Delete
* Set cache control to shared private.
[258] Fix | Delete
*
[259] Fix | Delete
* @access public
[260] Fix | Delete
* @since 1.1.3
[261] Fix | Delete
*
[262] Fix | Delete
* @param string|false $reason The reason to mark shared, or false.
[263] Fix | Delete
* @return void
[264] Fix | Delete
*/
[265] Fix | Delete
public static function set_shared( $reason = false ) {
[266] Fix | Delete
if ( self::is_shared() ) {
[267] Fix | Delete
return;
[268] Fix | Delete
}
[269] Fix | Delete
self::$_control |= self::BM_SHARED;
[270] Fix | Delete
self::set_private();
[271] Fix | Delete
[272] Fix | Delete
if ( ! is_string( $reason ) ) {
[273] Fix | Delete
$reason = false;
[274] Fix | Delete
}
[275] Fix | Delete
[276] Fix | Delete
if ( $reason ) {
[277] Fix | Delete
$reason = "( $reason )";
[278] Fix | Delete
}
[279] Fix | Delete
self::debug( 'X Cache_control -> shared ' . $reason );
[280] Fix | Delete
}
[281] Fix | Delete
[282] Fix | Delete
/**
[283] Fix | Delete
* Check if is shared private.
[284] Fix | Delete
*
[285] Fix | Delete
* @access public
[286] Fix | Delete
* @since 1.1.3
[287] Fix | Delete
* @return bool
[288] Fix | Delete
*/
[289] Fix | Delete
public static function is_shared() {
[290] Fix | Delete
return (bool) ( self::$_control & self::BM_SHARED ) && self::is_private();
[291] Fix | Delete
}
[292] Fix | Delete
[293] Fix | Delete
/**
[294] Fix | Delete
* Set cache control to forced public.
[295] Fix | Delete
*
[296] Fix | Delete
* @access public
[297] Fix | Delete
* @since 1.7.1
[298] Fix | Delete
*
[299] Fix | Delete
* @param string|false $reason Reason text or false.
[300] Fix | Delete
* @return void
[301] Fix | Delete
*/
[302] Fix | Delete
public static function set_public_forced( $reason = false ) {
[303] Fix | Delete
if ( self::is_public_forced() ) {
[304] Fix | Delete
return;
[305] Fix | Delete
}
[306] Fix | Delete
self::$_control |= self::BM_PUBLIC_FORCED;
[307] Fix | Delete
[308] Fix | Delete
if ( ! is_string( $reason ) ) {
[309] Fix | Delete
$reason = false;
[310] Fix | Delete
}
[311] Fix | Delete
[312] Fix | Delete
if ( $reason ) {
[313] Fix | Delete
$reason = "( $reason )";
[314] Fix | Delete
}
[315] Fix | Delete
self::debug( 'X Cache_control -> public forced ' . $reason );
[316] Fix | Delete
}
[317] Fix | Delete
[318] Fix | Delete
/**
[319] Fix | Delete
* Check if is public forced.
[320] Fix | Delete
*
[321] Fix | Delete
* @access public
[322] Fix | Delete
* @since 1.7.1
[323] Fix | Delete
* @return bool
[324] Fix | Delete
*/
[325] Fix | Delete
public static function is_public_forced() {
[326] Fix | Delete
return self::$_control & self::BM_PUBLIC_FORCED;
[327] Fix | Delete
}
[328] Fix | Delete
[329] Fix | Delete
/**
[330] Fix | Delete
* Set cache control to private.
[331] Fix | Delete
*
[332] Fix | Delete
* @access public
[333] Fix | Delete
* @since 1.1.3
[334] Fix | Delete
*
[335] Fix | Delete
* @param string|false $reason The reason to set private.
[336] Fix | Delete
* @return void
[337] Fix | Delete
*/
[338] Fix | Delete
public static function set_private( $reason = false ) {
[339] Fix | Delete
if ( self::is_private() ) {
[340] Fix | Delete
return;
[341] Fix | Delete
}
[342] Fix | Delete
self::$_control |= self::BM_PRIVATE;
[343] Fix | Delete
[344] Fix | Delete
if ( ! is_string( $reason ) ) {
[345] Fix | Delete
$reason = false;
[346] Fix | Delete
}
[347] Fix | Delete
[348] Fix | Delete
if ( $reason ) {
[349] Fix | Delete
$reason = "( $reason )";
[350] Fix | Delete
}
[351] Fix | Delete
self::debug( 'X Cache_control -> private ' . $reason );
[352] Fix | Delete
}
[353] Fix | Delete
[354] Fix | Delete
/**
[355] Fix | Delete
* Check if is private.
[356] Fix | Delete
*
[357] Fix | Delete
* @access public
[358] Fix | Delete
* @since 1.1.3
[359] Fix | Delete
* @return bool
[360] Fix | Delete
*/
[361] Fix | Delete
public static function is_private() {
[362] Fix | Delete
// if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
[363] Fix | Delete
// return false;
[364] Fix | Delete
// }
[365] Fix | Delete
[366] Fix | Delete
return (bool) ( self::$_control & self::BM_PRIVATE ) && ! self::is_public_forced();
[367] Fix | Delete
}
[368] Fix | Delete
[369] Fix | Delete
/**
[370] Fix | Delete
* Initialize cacheable status in `wp` hook, if not call this, by default it will be non-cacheable.
[371] Fix | Delete
*
[372] Fix | Delete
* @access public
[373] Fix | Delete
* @since 1.1.3
[374] Fix | Delete
*
[375] Fix | Delete
* @param string|false $reason Reason text or false.
[376] Fix | Delete
* @return void
[377] Fix | Delete
*/
[378] Fix | Delete
public function set_cacheable( $reason = false ) {
[379] Fix | Delete
self::$_control |= self::BM_CACHEABLE;
[380] Fix | Delete
[381] Fix | Delete
if ( ! is_string( $reason ) ) {
[382] Fix | Delete
$reason = false;
[383] Fix | Delete
}
[384] Fix | Delete
[385] Fix | Delete
if ( $reason ) {
[386] Fix | Delete
$reason = ' [reason] ' . $reason;
[387] Fix | Delete
}
[388] Fix | Delete
self::debug( 'Cache_control init on' . $reason );
[389] Fix | Delete
}
[390] Fix | Delete
[391] Fix | Delete
/**
[392] Fix | Delete
* This will disable non-cacheable BM.
[393] Fix | Delete
*
[394] Fix | Delete
* @access public
[395] Fix | Delete
* @since 2.2
[396] Fix | Delete
*
[397] Fix | Delete
* @param string|false $reason Reason text or false.
[398] Fix | Delete
* @return void
[399] Fix | Delete
*/
[400] Fix | Delete
public static function force_cacheable( $reason = false ) {
[401] Fix | Delete
self::$_control |= self::BM_FORCED_CACHEABLE;
[402] Fix | Delete
[403] Fix | Delete
if ( ! is_string( $reason ) ) {
[404] Fix | Delete
$reason = false;
[405] Fix | Delete
}
[406] Fix | Delete
[407] Fix | Delete
if ( $reason ) {
[408] Fix | Delete
$reason = ' [reason] ' . $reason;
[409] Fix | Delete
}
[410] Fix | Delete
self::debug( 'Forced cacheable' . $reason );
[411] Fix | Delete
}
[412] Fix | Delete
[413] Fix | Delete
/**
[414] Fix | Delete
* Switch to nocacheable status.
[415] Fix | Delete
*
[416] Fix | Delete
* @access public
[417] Fix | Delete
* @since 1.1.3
[418] Fix | Delete
*
[419] Fix | Delete
* @param string|false $reason The reason to no cache.
[420] Fix | Delete
* @return void
[421] Fix | Delete
*/
[422] Fix | Delete
public static function set_nocache( $reason = false ) {
[423] Fix | Delete
self::$_control |= self::BM_NOTCACHEABLE;
[424] Fix | Delete
[425] Fix | Delete
if ( ! is_string( $reason ) ) {
[426] Fix | Delete
$reason = false;
[427] Fix | Delete
}
[428] Fix | Delete
[429] Fix | Delete
if ( $reason ) {
[430] Fix | Delete
$reason = "( $reason )";
[431] Fix | Delete
}
[432] Fix | Delete
self::debug( 'X Cache_control -> no Cache ' . $reason, 5 );
[433] Fix | Delete
}
[434] Fix | Delete
[435] Fix | Delete
/**
[436] Fix | Delete
* Check current notcacheable bit set.
[437] Fix | Delete
*
[438] Fix | Delete
* @access public
[439] Fix | Delete
* @since 1.1.3
[440] Fix | Delete
* @return bool True if notcacheable bit is set, otherwise false.
[441] Fix | Delete
*/
[442] Fix | Delete
public static function isset_notcacheable() {
[443] Fix | Delete
return self::$_control & self::BM_NOTCACHEABLE;
[444] Fix | Delete
}
[445] Fix | Delete
[446] Fix | Delete
/**
[447] Fix | Delete
* Check current force cacheable bit set.
[448] Fix | Delete
*
[449] Fix | Delete
* @access public
[450] Fix | Delete
* @since 2.2
[451] Fix | Delete
* @return bool
[452] Fix | Delete
*/
[453] Fix | Delete
public static function is_forced_cacheable() {
[454] Fix | Delete
return self::$_control & self::BM_FORCED_CACHEABLE;
[455] Fix | Delete
}
[456] Fix | Delete
[457] Fix | Delete
/**
[458] Fix | Delete
* Check current cacheable status.
[459] Fix | Delete
*
[460] Fix | Delete
* @access public
[461] Fix | Delete
* @since 1.1.3
[462] Fix | Delete
* @return bool True if is still cacheable, otherwise false.
[463] Fix | Delete
*/
[464] Fix | Delete
public static function is_cacheable() {
[465] Fix | Delete
if ( defined( 'LSCACHE_NO_CACHE' ) && LSCACHE_NO_CACHE ) {
[466] Fix | Delete
self::debug( 'LSCACHE_NO_CACHE constant defined' );
[467] Fix | Delete
return false;
[468] Fix | Delete
}
[469] Fix | Delete
[470] Fix | Delete
// Guest mode always cacheable
[471] Fix | Delete
// if ( defined( 'LITESPEED_GUEST' ) && LITESPEED_GUEST ) {
[472] Fix | Delete
// return true;
[473] Fix | Delete
// }
[474] Fix | Delete
[475] Fix | Delete
// If it's forced public cacheable.
[476] Fix | Delete
if ( self::is_public_forced() ) {
[477] Fix | Delete
return true;
[478] Fix | Delete
}
[479] Fix | Delete
[480] Fix | Delete
// If it's forced cacheable.
[481] Fix | Delete
if ( self::is_forced_cacheable() ) {
[482] Fix | Delete
return true;
[483] Fix | Delete
}
[484] Fix | Delete
[485] Fix | Delete
return ! self::isset_notcacheable() && ( self::$_control & self::BM_CACHEABLE );
[486] Fix | Delete
}
[487] Fix | Delete
[488] Fix | Delete
/**
[489] Fix | Delete
* Set a custom TTL to use with the request if needed.
[490] Fix | Delete
*
[491] Fix | Delete
* @access public
[492] Fix | Delete
* @since 1.1.3
[493] Fix | Delete
*
[494] Fix | Delete
* @param int|string $ttl An integer or numeric string to use as the TTL.
[495] Fix | Delete
* @param string|false $reason Optional reason text.
[496] Fix | Delete
* @return void
[497] Fix | Delete
*/
[498] Fix | Delete
public static function set_custom_ttl( $ttl, $reason = false ) {
[499] Fix | Delete
12
It is recommended that you Edit text format, this type of Fix handles quite a lot in one request
Function