Failed to save the file to the "xx" directory.

Failed to save the file to the "ll" directory.

Failed to save the file to the "mm" directory.

Failed to save the file to the "wp" directory.

403WebShell
403Webshell
Server IP : 66.29.132.124  /  Your IP : 18.224.60.19
Web Server : LiteSpeed
System : Linux business141.web-hosting.com 4.18.0-553.lve.el8.x86_64 #1 SMP Mon May 27 15:27:34 UTC 2024 x86_64
User : wavevlvu ( 1524)
PHP Version : 7.4.33
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /usr/src/litespeed-wp-plugin/6.2.0.1/litespeed-cache/src/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /usr/src/litespeed-wp-plugin/6.2.0.1/litespeed-cache/src/purge.cls.php
<?php

/**
 * The plugin purge class for X-LiteSpeed-Purge
 *
 * @since      	1.1.3
 * @since  		2.2 Refactored. Changed access from public to private for most func and class variables.
 */

namespace LiteSpeed;

defined('WPINC') || exit();

class Purge extends Base
{
	const LOG_TAG = '🧹';

	protected $_pub_purge = array();
	protected $_pub_purge2 = array();
	protected $_priv_purge = array();
	protected $_purge_related = false;
	protected $_purge_single = false;

	const X_HEADER = 'X-LiteSpeed-Purge';
	const X_HEADER2 = 'X-LiteSpeed-Purge2';
	const DB_QUEUE = 'queue';
	const DB_QUEUE2 = 'queue2';

	const TYPE_PURGE_ALL = 'purge_all';
	const TYPE_PURGE_ALL_LSCACHE = 'purge_all_lscache';
	const TYPE_PURGE_ALL_CSSJS = 'purge_all_cssjs';
	const TYPE_PURGE_ALL_LOCALRES = 'purge_all_localres';
	const TYPE_PURGE_ALL_CCSS = 'purge_all_ccss';
	const TYPE_PURGE_ALL_UCSS = 'purge_all_ucss';
	const TYPE_PURGE_ALL_LQIP = 'purge_all_lqip';
	const TYPE_PURGE_ALL_AVATAR = 'purge_all_avatar';
	const TYPE_PURGE_ALL_OBJECT = 'purge_all_object';
	const TYPE_PURGE_ALL_OPCACHE = 'purge_all_opcache';

	const TYPE_PURGE_FRONT = 'purge_front';
	const TYPE_PURGE_UCSS = 'purge_ucss';
	const TYPE_PURGE_FRONTPAGE = 'purge_frontpage';
	const TYPE_PURGE_PAGES = 'purge_pages';
	const TYPE_PURGE_ERROR = 'purge_error';

	/**
	 * Init hooks
	 *
	 * @since  3.0
	 */
	public function init()
	{
		//register purge actions
		$purge_post_events = array(
			// 'edit_post',
			// 'save_post',
			'delete_post',
			'wp_trash_post',
			// 'clean_post_cache', // This will disable wc's not purge product when stock status not change setting
			'wp_update_comment_count', // TODO: check if needed for non ESI
		);
		foreach ($purge_post_events as $event) {
			// this will purge all related tags
			add_action($event, array($this, 'purge_post'));
		}

		// Purge post only when status is/was publish
		add_action('transition_post_status', array($this, 'purge_publish'), 10, 3);

		add_action('wp_update_comment_count', array($this, 'purge_feeds'));

		if ($this->conf(self::O_OPTM_UCSS)) {
			add_action('edit_post', __NAMESPACE__ . '\Purge::purge_ucss');
		}
	}

	/**
	 * Only purge publish related status post
	 *
	 * @since 3.0
	 * @access public
	 */
	public function purge_publish($new_status, $old_status, $post)
	{
		if ($new_status != 'publish' && $old_status != 'publish') {
			return;
		}

		$this->purge_post($post->ID);
	}

	/**
	 * Handle all request actions from main cls
	 *
	 * @since  1.8
	 * @access public
	 */
	public function handler()
	{
		$type = Router::verify_type();

		switch ($type) {
			case self::TYPE_PURGE_ALL:
				$this->_purge_all();
				break;

			case self::TYPE_PURGE_ALL_LSCACHE:
				$this->_purge_all_lscache();
				break;

			case self::TYPE_PURGE_ALL_CSSJS:
				$this->_purge_all_cssjs();
				break;

			case self::TYPE_PURGE_ALL_LOCALRES:
				$this->_purge_all_localres();
				break;

			case self::TYPE_PURGE_ALL_CCSS:
				$this->_purge_all_ccss();
				break;

			case self::TYPE_PURGE_ALL_UCSS:
				$this->_purge_all_ucss();
				break;

			case self::TYPE_PURGE_ALL_LQIP:
				$this->_purge_all_lqip();
				break;

			case self::TYPE_PURGE_ALL_AVATAR:
				$this->_purge_all_avatar();
				break;

			case self::TYPE_PURGE_ALL_OBJECT:
				$this->_purge_all_object();
				break;

			case self::TYPE_PURGE_ALL_OPCACHE:
				$this->purge_all_opcache();
				break;

			case self::TYPE_PURGE_FRONT:
				$this->_purge_front();
				break;

			case self::TYPE_PURGE_UCSS:
				$this->_purge_ucss();
				break;

			case self::TYPE_PURGE_FRONTPAGE:
				$this->_purge_frontpage();
				break;

			case self::TYPE_PURGE_PAGES:
				$this->_purge_pages();
				break;

			case strpos($type, self::TYPE_PURGE_ERROR) === 0:
				$this->_purge_error(substr($type, strlen(self::TYPE_PURGE_ERROR)));
				break;

			default:
				break;
		}

		Admin::redirect();
	}

	/**
	 * Shortcut to purge all lscache
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public static function purge_all($reason = false)
	{
		self::cls()->_purge_all($reason);
	}

	/**
	 * Purge all caches (lscache/op/oc)
	 *
	 * @since 2.2
	 * @access private
	 */
	private function _purge_all($reason = false)
	{
		// if ( defined( 'LITESPEED_CLI' ) ) {
		// 	// Can't send, already has output, need to save and wait for next run
		// 	self::update_option( self::DB_QUEUE, $curr_built );
		// 	self::debug( 'CLI request, queue stored: ' . $curr_built );
		// }
		// else {
		$this->_purge_all_lscache(true);
		$this->_purge_all_cssjs(true);
		$this->_purge_all_localres(true);
		// $this->_purge_all_ccss( true );
		// $this->_purge_all_lqip( true );
		$this->_purge_all_object(true);
		$this->purge_all_opcache(true);
		// }

		if (!is_string($reason)) {
			$reason = false;
		}

		if ($reason) {
			$reason = "( $reason )";
		}

		self::debug('Purge all ' . $reason, 3);

		$msg = __('Purged all caches successfully.', 'litespeed-cache');
		!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);

		do_action('litespeed_purged_all');
	}

	/**
	 * Alerts LiteSpeed Web Server to purge all pages.
	 *
	 * For multisite installs, if this is called by a site admin (not network admin),
	 * it will only purge all posts associated with that site.
	 *
	 * @since 2.2
	 * @access public
	 */
	private function _purge_all_lscache($silence = false)
	{
		$this->_add('*');

		if (!$silence) {
			$msg = __('Notified LiteSpeed Web Server to purge all LSCache entries.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Delete all critical css
	 *
	 * @since    2.3
	 * @access   private
	 */
	private function _purge_all_ccss($silence = false)
	{
		do_action('litespeed_purged_all_ccss');

		$this->cls('CSS')->rm_cache_folder('ccss');

		$this->cls('Data')->url_file_clean('ccss');

		if (!$silence) {
			$msg = __('Cleaned all Critical CSS files.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Delete all unique css
	 *
	 * @since    2.3
	 * @access   private
	 */
	private function _purge_all_ucss($silence = false)
	{
		do_action('litespeed_purged_all_ucss');

		$this->cls('CSS')->rm_cache_folder('ucss');

		$this->cls('Data')->url_file_clean('ucss');

		if (!$silence) {
			$msg = __('Cleaned all Unique CSS files.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Purge one UCSS by URL
	 *
	 * @since 4.5
	 * @access public
	 */
	public static function purge_ucss($post_id_or_url)
	{
		self::debug('Purge a single UCSS: ' . $post_id_or_url);
		// If is post_id, generate URL
		if (!preg_match('/\D/', $post_id_or_url)) {
			$post_id_or_url = get_permalink($post_id_or_url);
		}
		$post_id_or_url = untrailingslashit($post_id_or_url);

		$existing_url_files = Data::cls()->mark_as_expired($post_id_or_url, true);
		if ($existing_url_files) {
			// Add to UCSS Q
			self::cls('UCSS')->add_to_q($existing_url_files);
		}
	}

	/**
	 * Delete all LQIP images
	 *
	 * @since    3.0
	 * @access   private
	 */
	private function _purge_all_lqip($silence = false)
	{
		do_action('litespeed_purged_all_lqip');

		$this->cls('Placeholder')->rm_cache_folder('lqip');

		if (!$silence) {
			$msg = __('Cleaned all LQIP files.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Delete all avatar images
	 *
	 * @since    3.0
	 * @access   private
	 */
	private function _purge_all_avatar($silence = false)
	{
		do_action('litespeed_purged_all_avatar');

		$this->cls('Avatar')->rm_cache_folder('avatar');

		if (!$silence) {
			$msg = __('Cleaned all Gravatar files.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Delete all localized JS
	 *
	 * @since    3.3
	 * @access   private
	 */
	private function _purge_all_localres($silence = false)
	{
		do_action('litespeed_purged_all_localres');

		$this->_add(Tag::TYPE_LOCALRES);

		if (!$silence) {
			$msg = __('Cleaned all localized resource entries.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Alerts LiteSpeed Web Server to purge pages.
	 *
	 * @since    1.2.2
	 * @access   private
	 */
	private function _purge_all_cssjs($silence = false)
	{
		if (defined('DOING_CRON') || defined('LITESPEED_DID_send_headers')) {
			self::debug('❌ Bypassed cssjs delete as header sent (lscache purge after this point will fail) or doing cron');
			return;
		}
		$this->_purge_all_lscache($silence); // Purge CSSJS must purge lscache too to avoid 404

		do_action('litespeed_purged_all_cssjs');

		Optimize::update_option(Optimize::ITEM_TIMESTAMP_PURGE_CSS, time());

		$this->_add(Tag::TYPE_MIN);

		$this->cls('CSS')->rm_cache_folder('css');
		$this->cls('CSS')->rm_cache_folder('js');

		$this->cls('Data')->url_file_clean('css');
		$this->cls('Data')->url_file_clean('js');

		// Clear UCSS queue as it used combined CSS to generate
		$this->clear_q('ucss', true);

		if (!$silence) {
			$msg = __('Notified LiteSpeed Web Server to purge CSS/JS entries.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}
	}

	/**
	 * Purge opcode cache
	 *
	 * @since  1.8.2
	 * @access public
	 */
	public function purge_all_opcache($silence = false)
	{
		if (!Router::opcache_enabled()) {
			self::debug('Failed to reset opcode cache due to opcache not enabled');

			if (!$silence) {
				$msg = __('Opcode cache is not enabled.', 'litespeed-cache');
				Admin_Display::error($msg);
			}

			return false;
		}

		// Purge opcode cache
		opcache_reset();
		self::debug('Reset opcode cache');

		if (!$silence) {
			$msg = __('Reset the entire opcode cache successfully.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}

		return true;
	}

	/**
	 * Purge object cache
	 *
	 * @since  3.4
	 * @access public
	 */
	public static function purge_all_object($silence = true)
	{
		self::cls()->_purge_all_object($silence);
	}

	/**
	 * Purge object cache
	 *
	 * @since  1.8
	 * @access private
	 */
	private function _purge_all_object($silence = false)
	{
		if (!defined('LSCWP_OBJECT_CACHE')) {
			self::debug('Failed to flush object cache due to object cache not enabled');

			if (!$silence) {
				$msg = __('Object cache is not enabled.', 'litespeed-cache');
				Admin_Display::error($msg);
			}

			return false;
		}

		do_action('litespeed_purged_all_object');

		$this->cls('Object_Cache')->flush();
		self::debug('Flushed object cache');

		if (!$silence) {
			$msg = __('Purge all object caches successfully.', 'litespeed-cache');
			!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
		}

		return true;
	}

	/**
	 * Adds new public purge tags to the array of purge tags for the request.
	 *
	 * @since 1.1.3
	 * @access public
	 * @param mixed $tags Tags to add to the list.
	 */
	public static function add($tags, $purge2 = false)
	{
		self::cls()->_add($tags, $purge2);
	}

	/**
	 * Add tags to purge
	 *
	 * @since 2.2
	 * @access private
	 */
	private function _add($tags, $purge2 = false)
	{
		if (!is_array($tags)) {
			$tags = array($tags);
		}

		$tags = $this->_prepend_bid($tags);

		if (!array_diff($tags, $purge2 ? $this->_pub_purge2 : $this->_pub_purge)) {
			return;
		}

		if ($purge2) {
			$this->_pub_purge2 = array_merge($this->_pub_purge2, $tags);
			$this->_pub_purge2 = array_unique($this->_pub_purge2);
		} else {
			$this->_pub_purge = array_merge($this->_pub_purge, $tags);
			$this->_pub_purge = array_unique($this->_pub_purge);
		}
		self::debug('added ' . implode(',', $tags) . ($purge2 ? ' [Purge2]' : ''), 8);

		// Send purge header immediately
		$curr_built = $this->_build($purge2);
		if (defined('LITESPEED_CLI')) {
			// Can't send, already has output, need to save and wait for next run
			self::update_option($purge2 ? self::DB_QUEUE2 : self::DB_QUEUE, $curr_built);
			self::debug('CLI request, queue stored: ' . $curr_built);
		} else {
			@header($curr_built);
			if (defined('DOING_CRON') || defined('LITESPEED_DID_send_headers') || apply_filters('litespeed_delay_purge', false)) {
				self::update_option($purge2 ? self::DB_QUEUE2 : self::DB_QUEUE, $curr_built);
				self::debug('Output existed, queue stored: ' . $curr_built);
			}
			self::debug($curr_built);
		}
	}

	/**
	 * Adds new private purge tags to the array of purge tags for the request.
	 *
	 * @since 1.1.3
	 * @access public
	 * @param mixed $tags Tags to add to the list.
	 */
	public static function add_private($tags)
	{
		self::cls()->_add_private($tags);
	}

	/**
	 * Add private ESI tag to purge list
	 *
	 * @since 3.0
	 * @access public
	 */
	public static function add_private_esi($tag)
	{
		self::add_private(Tag::TYPE_ESI . $tag);
	}

	/**
	 * Add private all tag to purge list
	 *
	 * @since 3.0
	 * @access public
	 */
	public static function add_private_all()
	{
		self::add_private('*');
	}

	/**
	 * Add tags to private purge
	 *
	 * @since 2.2
	 * @access private
	 */
	private function _add_private($tags)
	{
		if (!is_array($tags)) {
			$tags = array($tags);
		}

		$tags = $this->_prepend_bid($tags);

		if (!array_diff($tags, $this->_priv_purge)) {
			return;
		}

		self::debug('added [private] ' . implode(',', $tags), 3);

		$this->_priv_purge = array_merge($this->_priv_purge, $tags);
		$this->_priv_purge = array_unique($this->_priv_purge);

		// Send purge header immediately
		@header($this->_build());
	}

	/**
	 * Incorporate blog_id into purge tags for multisite
	 *
	 * @since 4.0
	 * @access private
	 * @param mixed $tags Tags to add to the list.
	 */
	private function _prepend_bid($tags)
	{
		if (in_array('*', $tags)) {
			return array('*');
		}

		$curr_bid = is_multisite() ? get_current_blog_id() : '';

		foreach ($tags as $k => $v) {
			$tags[$k] = $curr_bid . '_' . $v;
		}
		return $tags;
	}

	/**
	 * Activate `purge related tags` for Admin QS.
	 *
	 * @since    1.1.3
	 * @access   public
	 */
	public static function set_purge_related()
	{
		self::cls()->_purge_related = true;
	}

	/**
	 * Activate `purge single url tag` for Admin QS.
	 *
	 * @since    1.1.3
	 * @access   public
	 */
	public static function set_purge_single()
	{
		self::cls()->_purge_single = true;
	}

	/**
	 * Purge frontend url
	 *
	 * @since 1.3
	 * @since 2.2 Renamed from `frontend_purge`; Access changed from public
	 * @access private
	 */
	private function _purge_front()
	{
		if (empty($_SERVER['HTTP_REFERER'])) {
			exit('no referer');
		}

		$this->purge_url($_SERVER['HTTP_REFERER']);

		do_action('litespeed_purged_front', $_SERVER['HTTP_REFERER']);
		wp_redirect($_SERVER['HTTP_REFERER']);
		exit();
	}

	/**
	 * Purge single UCSS
	 * @since 4.7
	 */
	private function _purge_ucss()
	{
		if (empty($_SERVER['HTTP_REFERER'])) {
			exit('no referer');
		}

		$url_tag = empty($_GET['url_tag']) ? $_SERVER['HTTP_REFERER'] : $_GET['url_tag'];

		self::debug('Purge ucss [url_tag] ' . $url_tag);

		do_action('litespeed_purge_ucss', $url_tag);
		$this->purge_url($_SERVER['HTTP_REFERER']);

		wp_redirect($_SERVER['HTTP_REFERER']);
		exit();
	}

	/**
	 * Alerts LiteSpeed Web Server to purge the front page.
	 *
	 * @since    1.0.3
	 * @since  	 2.2 	Access changed from public to private, renamed from `_purge_front`
	 * @access   private
	 */
	private function _purge_frontpage()
	{
		$this->_add(Tag::TYPE_FRONTPAGE);
		if (LITESPEED_SERVER_TYPE !== 'LITESPEED_SERVER_OLS') {
			$this->_add_private(Tag::TYPE_FRONTPAGE);
		}

		$msg = __('Notified LiteSpeed Web Server to purge the front page.', 'litespeed-cache');
		!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
	}

	/**
	 * Alerts LiteSpeed Web Server to purge pages.
	 *
	 * @since    1.0.15
	 * @access   private
	 */
	private function _purge_pages()
	{
		$this->_add(Tag::TYPE_PAGES);

		$msg = __('Notified LiteSpeed Web Server to purge all pages.', 'litespeed-cache');
		!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
	}

	/**
	 * Alerts LiteSpeed Web Server to purge error pages.
	 *
	 * @since    1.0.14
	 * @access   private
	 */
	private function _purge_error($type = false)
	{
		$this->_add(Tag::TYPE_HTTP);

		if (!$type || !in_array($type, array('403', '404', '500'))) {
			return;
		}

		$this->_add(Tag::TYPE_HTTP . $type);

		$msg = __('Notified LiteSpeed Web Server to purge error pages.', 'litespeed-cache');
		!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed($msg);
	}

	/**
	 * Callback to add purge tags if admin selects to purge selected category pages.
	 *
	 * @since 1.0.7
	 * @access public
	 */
	public function purge_cat($value)
	{
		$val = trim($value);
		if (empty($val)) {
			return;
		}
		if (preg_match('/^[a-zA-Z0-9-]+$/', $val) == 0) {
			self::debug("$val cat invalid");
			return;
		}
		$cat = get_category_by_slug($val);
		if ($cat == false) {
			self::debug("$val cat not existed/published");
			return;
		}

		self::add(Tag::TYPE_ARCHIVE_TERM . $cat->term_id);

		!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed(sprintf(__('Purge category %s', 'litespeed-cache'), $val));
	}

	/**
	 * Callback to add purge tags if admin selects to purge selected tag pages.
	 *
	 * @since 1.0.7
	 * @access public
	 */
	public function purge_tag($val)
	{
		$val = trim($val);
		if (empty($val)) {
			return;
		}
		if (preg_match('/^[a-zA-Z0-9-]+$/', $val) == 0) {
			self::debug("$val tag invalid");
			return;
		}
		$term = get_term_by('slug', $val, 'post_tag');
		if ($term == 0) {
			self::debug("$val tag not exist");
			return;
		}

		self::add(Tag::TYPE_ARCHIVE_TERM . $term->term_id);

		!defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed(sprintf(__('Purge tag %s', 'litespeed-cache'), $val));
	}

	/**
	 * Callback to add purge tags if admin selects to purge selected urls.
	 *
	 * @since 1.0.7
	 * @access public
	 */
	public function purge_url($url, $purge2 = false, $quite = false)
	{
		$val = trim($url);
		if (empty($val)) {
			return;
		}

		if (strpos($val, '<') !== false) {
			self::debug("$val url contains <");
			return;
		}

		$val = Utility::make_relative($val);

		$hash = Tag::get_uri_tag($val);

		if ($hash === false) {
			self::debug("$val url invalid");
			return;
		}

		self::add($hash, $purge2);

		!$quite && !defined('LITESPEED_PURGE_SILENT') && Admin_Display::succeed(sprintf(__('Purge url %s', 'litespeed-cache'), $val));
	}

	/**
	 * Purge a list of pages when selected by admin. This method will look at the post arguments to determine how and what to purge.
	 *
	 * @since 1.0.7
	 * @access public
	 */
	public function purge_list()
	{
		if (!isset($_REQUEST[Admin_Display::PURGEBYOPT_SELECT]) || !isset($_REQUEST[Admin_Display::PURGEBYOPT_LIST])) {
			return;
		}
		$sel = $_REQUEST[Admin_Display::PURGEBYOPT_SELECT];
		$list_buf = $_REQUEST[Admin_Display::PURGEBYOPT_LIST];
		if (empty($list_buf)) {
			return;
		}
		$list_buf = str_replace(',', "\n", $list_buf); // for cli
		$list = explode("\n", $list_buf);
		switch ($sel) {
			case Admin_Display::PURGEBY_CAT:
				$cb = 'purge_cat';
				break;
			case Admin_Display::PURGEBY_PID:
				$cb = 'purge_post';
				break;
			case Admin_Display::PURGEBY_TAG:
				$cb = 'purge_tag';
				break;
			case Admin_Display::PURGEBY_URL:
				$cb = 'purge_url';
				break;

			default:
				return;
		}
		array_map(array($this, $cb), $list);

		// for redirection
		$_GET[Admin_Display::PURGEBYOPT_SELECT] = $sel;
	}

	/**
	 * Purge ESI
	 *
	 * @since 3.0
	 * @access public
	 */
	public static function purge_esi($tag)
	{
		self::add(Tag::TYPE_ESI . $tag);
	}

	/**
	 * Purge a certain post type
	 *
	 * @since 3.0
	 * @access public
	 */
	public static function purge_posttype($post_type)
	{
		self::add(Tag::TYPE_ARCHIVE_POSTTYPE . $post_type);
		self::add($post_type);
	}

	/**
	 * Purge all related tags to a post.
	 *
	 * @since 1.0.0
	 * @access public
	 */
	public function purge_post($pid)
	{
		$pid = intval($pid);
		// ignore the status we don't care
		if (!$pid || !in_array(get_post_status($pid), array('publish', 'trash', 'private', 'draft'))) {
			return;
		}

		$purge_tags = $this->_get_purge_tags_by_post($pid);
		if (!$purge_tags) {
			return;
		}

		self::add($purge_tags);
		if ($this->conf(self::O_CACHE_REST)) {
			self::add(Tag::TYPE_REST);
		}

		// $this->cls( 'Control' )->set_stale();
	}

	/**
	 * Hooked to the load-widgets.php action.
	 * Attempts to purge a single widget from cache.
	 * If no widget id is passed in, the method will attempt to find the widget id.
	 *
	 * @since 1.1.3
	 * @access public
	 */
	public static function purge_widget($widget_id = null)
	{
		if (is_null($widget_id)) {
			$widget_id = $_POST['widget-id'];
			if (is_null($widget_id)) {
				return;
			}
		}
		self::add(Tag::TYPE_WIDGET . $widget_id);
		self::add_private(Tag::TYPE_WIDGET . $widget_id);
	}

	/**
	 * Hooked to the wp_update_comment_count action.
	 * Purges the comment widget when the count is updated.
	 *
	 * @access public
	 * @since 1.1.3
	 * @global type $wp_widget_factory
	 */
	public static function purge_comment_widget()
	{
		global $wp_widget_factory;
		if (!isset($wp_widget_factory->widgets['WP_Widget_Recent_Comments'])) {
			return;
		}
		$recent_comments = $wp_widget_factory->widgets['WP_Widget_Recent_Comments'];
		if (!is_null($recent_comments)) {
			self::add(Tag::TYPE_WIDGET . $recent_comments->id);
			self::add_private(Tag::TYPE_WIDGET . $recent_comments->id);
		}
	}

	/**
	 * Purges feeds on comment count update.
	 *
	 * @since 1.0.9
	 * @access public
	 */
	public function purge_feeds()
	{
		if ($this->conf(self::O_CACHE_TTL_FEED) > 0) {
			self::add(Tag::TYPE_FEED);
		}
	}

	/**
	 * Purges all private cache entries when the user logs out.
	 *
	 * @access public
	 * @since 1.1.3
	 */
	public static function purge_on_logout()
	{
		self::add_private('*');
	}

	/**
	 * Generate all purge tags before output
	 *
	 * @access private
	 * @since 1.1.3
	 */
	private function _finalize()
	{
		// Make sure header output only run once
		if (!defined('LITESPEED_DID_' . __FUNCTION__)) {
			define('LITESPEED_DID_' . __FUNCTION__, true);
		} else {
			return;
		}

		do_action('litespeed_purge_finalize');

		// Append unique uri purge tags if Admin QS is `PURGESINGLE`
		if ($this->_purge_single) {
			$this->_pub_purge[] = Tag::build_uri_tag(); // TODO: add private tag too
		}
		// Append related purge tags if Admin QS is `PURGE`
		if ($this->_purge_related) {
			// Before this, tags need to be finalized
			$tags_related = Tag::output_tags();
			// NOTE: need to remove the empty item `B1_` to avoid purging all
			$tags_related = array_filter($tags_related);
			if ($tags_related) {
				$this->_pub_purge = array_merge($this->_pub_purge, $tags_related);
			}
		}

		if (!empty($this->_pub_purge)) {
			$this->_pub_purge = array_unique($this->_pub_purge);
		}

		if (!empty($this->_priv_purge)) {
			$this->_priv_purge = array_unique($this->_priv_purge);
		}
	}

	/**
	 * Gathers all the purge headers.
	 *
	 * This will collect all site wide purge tags as well as third party plugin defined purge tags.
	 *
	 * @since 1.1.0
	 * @access public
	 * @return string the built purge header
	 */
	public static function output()
	{
		$instance = self::cls();

		$instance->_finalize();

		return $instance->_build();
	}

	/**
	 * Build the current purge headers.
	 *
	 * @since 1.1.5
	 * @access private
	 * @return string the built purge header
	 */
	private function _build($purge2 = false)
	{
		if ($purge2) {
			if (empty($this->_pub_purge2)) {
				return;
			}
		} else {
			if (empty($this->_pub_purge) && empty($this->_priv_purge)) {
				return;
			}
		}

		$purge_header = '';

		// Handle purge2 @since 4.4.1
		if ($purge2) {
			$public_tags = $this->_append_prefix($this->_pub_purge2);
			if (empty($public_tags)) {
				return;
			}
			$purge_header = self::X_HEADER2 . ': public,';
			if (Control::is_stale()) {
				$purge_header .= 'stale,';
			}
			$purge_header .= implode(',', $public_tags);
			return $purge_header;
		}

		$private_prefix = self::X_HEADER . ': private,';

		if (!empty($this->_pub_purge)) {
			$public_tags = $this->_append_prefix($this->_pub_purge);
			if (empty($public_tags)) {
				// If this ends up empty, private will also end up empty
				return;
			}
			$purge_header = self::X_HEADER . ': public,';
			if (Control::is_stale()) {
				$purge_header .= 'stale,';
			}
			$purge_header .= implode(',', $public_tags);
			$private_prefix = ';private,';
		}

		// Handle priv purge tags
		if (!empty($this->_priv_purge)) {
			$private_tags = $this->_append_prefix($this->_priv_purge, true);
			$purge_header .= $private_prefix . implode(',', $private_tags);
		}

		return $purge_header;
	}

	/**
	 * Append prefix to an array of purge headers
	 *
	 * @since 1.1.0
	 * @access private
	 */
	private function _append_prefix($purge_tags, $is_private = false)
	{
		$curr_bid = is_multisite() ? get_current_blog_id() : '';

		if (!in_array('*', $purge_tags)) {
			$tags = array();
			foreach ($purge_tags as $val) {
				$tags[] = LSWCP_TAG_PREFIX . $val;
			}
			return $tags;
		}

		// Purge All need to check if need to reset crawler or not
		if (!$is_private && $this->conf(self::O_CRAWLER)) {
			Crawler::cls()->reset_pos();
		}

		if (defined('LSWCP_EMPTYCACHE') || $is_private) {
			return array('*');
		}

		if (is_multisite() && !$this->_is_subsite_purge()) {
			$blogs = Activation::get_network_ids();
			if (empty($blogs)) {
				self::debug('build_purge_headers: blog list is empty');
				return '';
			}
			$tags = array();
			foreach ($blogs as $blog_id) {
				$tags[] = LSWCP_TAG_PREFIX . $blog_id . '_';
			}
			return $tags;
		} else {
			return array(LSWCP_TAG_PREFIX . $curr_bid . '_');
		}
	}

	/**
	 * Check if this purge blongs to a subsite purge
	 *
	 * @since  4.0
	 */
	private function _is_subsite_purge()
	{
		if (!is_multisite()) {
			return false;
		}

		if (is_network_admin()) {
			return false;
		}

		if (defined('LSWCP_EMPTYCACHE')) {
			return false;
		}

		// Would only use multisite and network admin except is_network_admin is false for ajax calls, which is used by wordpress updates v4.6+
		if (Router::is_ajax() && (check_ajax_referer('updates', false, false) || check_ajax_referer('litespeed-purgeall-network', false, false))) {
			return false;
		}

		return true;
	}

	/**
	 * Gets all the purge tags correlated with the post about to be purged.
	 *
	 * If the purge all pages configuration is set, all pages will be purged.
	 *
	 * This includes site wide post types (e.g. front page) as well as any third party plugin specific post tags.
	 *
	 * @since 1.0.0
	 * @access private
	 */
	private function _get_purge_tags_by_post($post_id)
	{
		// If this is a valid post we want to purge the post, the home page and any associated tags & cats
		// If not, purge everything on the site.

		$purge_tags = array();

		if ($this->conf(self::O_PURGE_POST_ALL)) {
			// ignore the rest if purge all
			return array('*');
		}

		// now do API hook action for post purge
		do_action('litespeed_api_purge_post', $post_id);

		// post
		$purge_tags[] = Tag::TYPE_POST . $post_id;
		$post_status = get_post_status($post_id);
		if (function_exists('is_post_status_viewable')) {
			$viewable = is_post_status_viewable($post_status);
			if ($viewable) {
				$purge_tags[] = Tag::get_uri_tag(wp_make_link_relative(get_permalink($post_id)));
			}
		}

		// for archive of categories|tags|custom tax
		global $post;
		$original_post = $post;
		$post = get_post($post_id);
		$post_type = $post->post_type;

		global $wp_widget_factory;
		// recent_posts
		$recent_posts = isset($wp_widget_factory->widgets['WP_Widget_Recent_Posts']) ? $wp_widget_factory->widgets['WP_Widget_Recent_Posts'] : null;
		if (!is_null($recent_posts)) {
			$purge_tags[] = Tag::TYPE_WIDGET . $recent_posts->id;
		}

		// get adjacent posts id as related post tag
		if ($post_type == 'post') {
			$prev_post = get_previous_post();
			$next_post = get_next_post();
			if (!empty($prev_post->ID)) {
				$purge_tags[] = Tag::TYPE_POST . $prev_post->ID;
				self::debug('--------purge_tags prev is: ' . $prev_post->ID);
			}
			if (!empty($next_post->ID)) {
				$purge_tags[] = Tag::TYPE_POST . $next_post->ID;
				self::debug('--------purge_tags next is: ' . $next_post->ID);
			}
		}

		if ($this->conf(self::O_PURGE_POST_TERM)) {
			$taxonomies = get_object_taxonomies($post_type);
			//self::debug('purge by post, check tax = ' . var_export($taxonomies, true));
			foreach ($taxonomies as $tax) {
				$terms = get_the_terms($post_id, $tax);
				if (!empty($terms)) {
					foreach ($terms as $term) {
						$purge_tags[] = Tag::TYPE_ARCHIVE_TERM . $term->term_id;
					}
				}
			}
		}

		if ($this->conf(self::O_CACHE_TTL_FEED)) {
			$purge_tags[] = Tag::TYPE_FEED;
		}

		// author, for author posts and feed list
		if ($this->conf(self::O_PURGE_POST_AUTHOR)) {
			$purge_tags[] = Tag::TYPE_AUTHOR . get_post_field('post_author', $post_id);
		}

		// archive and feed of post type
		// todo: check if type contains space
		if ($this->conf(self::O_PURGE_POST_POSTTYPE)) {
			if (get_post_type_archive_link($post_type)) {
				$purge_tags[] = Tag::TYPE_ARCHIVE_POSTTYPE . $post_type;
				$purge_tags[] = $post_type;
			}
		}

		if ($this->conf(self::O_PURGE_POST_FRONTPAGE)) {
			$purge_tags[] = Tag::TYPE_FRONTPAGE;
		}

		if ($this->conf(self::O_PURGE_POST_HOMEPAGE)) {
			$purge_tags[] = Tag::TYPE_HOME;
		}

		if ($this->conf(self::O_PURGE_POST_PAGES)) {
			$purge_tags[] = Tag::TYPE_PAGES;
		}

		if ($this->conf(self::O_PURGE_POST_PAGES_WITH_RECENT_POSTS)) {
			$purge_tags[] = Tag::TYPE_PAGES_WITH_RECENT_POSTS;
		}

		// if configured to have archived by date
		$date = $post->post_date;
		$date = strtotime($date);

		if ($this->conf(self::O_PURGE_POST_DATE)) {
			$purge_tags[] = Tag::TYPE_ARCHIVE_DATE . date('Ymd', $date);
		}

		if ($this->conf(self::O_PURGE_POST_MONTH)) {
			$purge_tags[] = Tag::TYPE_ARCHIVE_DATE . date('Ym', $date);
		}

		if ($this->conf(self::O_PURGE_POST_YEAR)) {
			$purge_tags[] = Tag::TYPE_ARCHIVE_DATE . date('Y', $date);
		}

		// Set back to original post as $post_id might affecting the global $post value
		$post = $original_post;

		return array_unique($purge_tags);
	}

	/**
	 * The dummy filter for purge all
	 *
	 * @since 1.1.5
	 * @access public
	 * @param string $val The filter value
	 * @return string     The filter value
	 */
	public static function filter_with_purge_all($val)
	{
		self::purge_all();
		return $val;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit