294 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 * Ajax Cache.
 | 
						|
 *
 | 
						|
 * @package Builder
 | 
						|
 */
 | 
						|
 | 
						|
if ( ! defined( 'ABSPATH' ) ) {
 | 
						|
	exit; // Exit if accessed directly.
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Class to cache commonly used AJAX requests.
 | 
						|
 */
 | 
						|
class ET_Builder_Ajax_Cache {
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Instance of this class.
 | 
						|
	 *
 | 
						|
	 * @var ET_Builder_Ajax_Cache
 | 
						|
	 */
 | 
						|
	private static $_instance;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Transient name.
 | 
						|
	 *
 | 
						|
	 * @var string
 | 
						|
	 */
 | 
						|
	protected $_transient = 'et_builder_ajax_cache';
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Flag to determine whether to save cache or not on `shutdown` hook.
 | 
						|
	 *
 | 
						|
	 * @var bool
 | 
						|
	 */
 | 
						|
	protected $_dirty = false;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * List of all ajax cache.
 | 
						|
	 *
 | 
						|
	 * @var Array
 | 
						|
	 */
 | 
						|
	protected $_cache;
 | 
						|
 | 
						|
	/**
 | 
						|
	 * ET_Builder_Ajax_Cache constructor.
 | 
						|
	 */
 | 
						|
	public function __construct() {
 | 
						|
		add_action( 'et_builder_ajax_cache_clear', array( $this, 'clear' ), 10, 1 );
 | 
						|
		add_action( 'shutdown', array( $this, 'save' ) );
 | 
						|
		add_filter( 'et_builder_dynamic_asset_deps', array( $this, 'add_cache_dep' ), 10, 2 );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns whether cache file exists or not.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	public function file_exists() {
 | 
						|
		$file = $this->get_file_name();
 | 
						|
		return $file && et_()->WPFS()->is_readable( $file );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Returns whether cache is empty or not.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	public function is_empty() {
 | 
						|
		$this->load();
 | 
						|
		return empty( $this->_cache );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Enqueue ajax cache as definitions dependency.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @param array  $deps Dependencies array.
 | 
						|
	 * @param string $key Script handle.
 | 
						|
	 *
 | 
						|
	 * @return array
 | 
						|
	 */
 | 
						|
	public function add_cache_dep( $deps, $key ) {
 | 
						|
		// Skip all static assets but definitions.
 | 
						|
		if ( 'et-dynamic-asset-definitions' !== $key ) {
 | 
						|
			return $deps;
 | 
						|
		}
 | 
						|
 | 
						|
		if ( ! $this->file_exists() && ! $this->write_file() ) {
 | 
						|
			// Bail out if cache is empty and cannot write the file.
 | 
						|
			return $deps;
 | 
						|
		}
 | 
						|
 | 
						|
		// Enqueue ajax cache as definitions dependency.
 | 
						|
		$handle = 'et-ajax-cache';
 | 
						|
		$deps[] = $handle;
 | 
						|
		wp_register_script( $handle, $this->get_url(), array(), ET_BUILDER_VERSION, false );
 | 
						|
 | 
						|
		return $deps;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Load cache.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function load() {
 | 
						|
		if ( is_array( $this->_cache ) ) {
 | 
						|
			// Cache was already loaded.
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		$this->_cache = get_transient( $this->_transient );
 | 
						|
 | 
						|
		if ( ! is_array( $this->_cache ) ) {
 | 
						|
			$this->_cache = array();
 | 
						|
			$this->delete_file();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Save cache.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function save() {
 | 
						|
		// Ensure cache is loaded.
 | 
						|
		$this->load();
 | 
						|
 | 
						|
		if ( $this->_dirty ) {
 | 
						|
			set_transient( $this->_transient, $this->_cache );
 | 
						|
			$this->delete_file();
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Write cache file.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return bool
 | 
						|
	 */
 | 
						|
	public function write_file() {
 | 
						|
		if ( $this->is_empty() ) {
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		$file  = $this->get_file_name();
 | 
						|
		$cache = '';
 | 
						|
		foreach ( $this->_cache as $key => $value ) {
 | 
						|
			$cache = sprintf( '"%s":%s,', $key, $value );
 | 
						|
		}
 | 
						|
		$cache = sprintf( '{"ajaxCache":{%s}}', rtrim( $cache, ',' ) );
 | 
						|
		$cache = sprintf( 'window.ETBuilderBackend=jQuery.extend(true,%s,window.ETBuilderBackend)', $cache );
 | 
						|
 | 
						|
		et_()->WPFS()->put_contents( $file, $cache );
 | 
						|
		return $this->file_exists();
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Delete cache file.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function delete_file() {
 | 
						|
		if ( $this->file_exists() ) {
 | 
						|
			et_()->WPFS()->delete( $this->get_file_name() );
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Set cache key.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @param string $key Cache key.
 | 
						|
	 * @param string $content Cache value.
 | 
						|
	 *
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function set( $key, $content ) {
 | 
						|
		$this->load();
 | 
						|
		$this->_cache[ $key ] = wp_json_encode( $content );
 | 
						|
		$this->_dirty         = true;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Unset cache key.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @param string $key Cache key.
 | 
						|
	 *
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function unset_( $key ) {
 | 
						|
		$this->load();
 | 
						|
		if ( isset( $this->_cache[ $key ] ) ) {
 | 
						|
			unset( $this->_cache[ $key ] );
 | 
						|
			$this->_dirty = true;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Clear cache.
 | 
						|
	 *
 | 
						|
	 * @return void
 | 
						|
	 */
 | 
						|
	public function clear() {
 | 
						|
		delete_transient( $this->_transient );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get cache file name.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return string.
 | 
						|
	 */
 | 
						|
	public function get_file_name() {
 | 
						|
		// Per language Cache due to some data being localized.
 | 
						|
		$lang   = is_admin() || et_fb_is_enabled() ? get_user_locale() : get_locale();
 | 
						|
		$lang   = trim( sanitize_file_name( $lang ), '.' );
 | 
						|
		$prefix = 'ajax';
 | 
						|
		$cache  = et_()->path( et_core_cache_dir()->path, $lang );
 | 
						|
		$files  = glob( "{$cache}/{$prefix}-*.js" );
 | 
						|
		$exists = is_array( $files ) && $files;
 | 
						|
 | 
						|
		if ( $exists ) {
 | 
						|
			return $files[0];
 | 
						|
		}
 | 
						|
 | 
						|
		wp_mkdir_p( $cache );
 | 
						|
 | 
						|
		// Create uniq filename.
 | 
						|
		$uniq = str_replace( '.', '', (string) microtime( true ) );
 | 
						|
		$file = "{$cache}/{$prefix}-{$uniq}.js";
 | 
						|
 | 
						|
		return et_()->WPFS()->is_writable( dirname( $file ) ) ? $file : false;
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get cache url.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return string
 | 
						|
	 */
 | 
						|
	public function get_url() {
 | 
						|
		$file = $this->get_file_name();
 | 
						|
		$lang = basename( dirname( $file ) );
 | 
						|
		$name = basename( $file );
 | 
						|
		return et_()->path( et_core_cache_dir()->url, $lang, $name );
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get the class instance.
 | 
						|
	 *
 | 
						|
	 * @since 4.0.10
 | 
						|
	 *
 | 
						|
	 * @return ET_Builder_Ajax_Cache
 | 
						|
	 */
 | 
						|
	public static function instance() {
 | 
						|
		if ( ! self::$_instance ) {
 | 
						|
			self::$_instance = new self();
 | 
						|
		}
 | 
						|
 | 
						|
		/**
 | 
						|
		 * Filters the cache class instance that for caches AJAX requests.
 | 
						|
		 *
 | 
						|
		 * @param ET_Builder_Ajax_Cache Cache Instance
 | 
						|
		 *
 | 
						|
		 * @see GlobalHistoryMigrationTest
 | 
						|
		 *
 | 
						|
		 * @since 4.14.0
 | 
						|
		 */
 | 
						|
		return apply_filters( 'et_builder_ajax_cache_instance', self::$_instance );
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
ET_Builder_Ajax_Cache::instance();
 |