setup();
}
return self::$instance;
}
protected function __construct() {
/** Don't do anything **/
}
/**
* Setup the actions and filters we need to hook into, and initialize any properties we need.
*
* @return void
*/
protected function setup() {
$this->options = get_option( self::SLUG, array() );
$this->default_options = array(
'default_ttl' => 600,
'maintenance_mode' => 'disabled',
);
$this->options = wp_parse_args( $this->options, $this->default_options );
add_action( 'init', array( $this, 'action_init_do_maintenance_mode' ) );
add_action( 'admin_init', array( $this, 'action_admin_init' ) );
add_action( 'admin_menu', array( $this, 'action_admin_menu' ) );
add_action( 'load-plugin-install.php', array( $this, 'action_load_plugin_install' ) );
add_action( 'admin_post_pantheon_cache_flush_site', array( $this, 'flush_site' ) );
add_action( 'send_headers', array( $this, 'cache_add_headers' ) );
add_filter( 'rest_post_dispatch', array( $this, 'filter_rest_post_dispatch_send_cache_control' ), 10, 2 );
add_action( 'admin_notices', function(){
global $wp_object_cache;
if ( empty( $wp_object_cache->missing_redis_message ) ) {
return;
}
$wp_object_cache->missing_redis_message = 'Alert! The Pantheon Redis service needs to be enabled before the WP Redis object cache will function properly.';
}, 9 ); // Before the message is displayed in the plugin notice.
add_action( 'shutdown', array( $this, 'cache_clean_urls' ), 999 );
}
/**
* Displays maintenance mode when enabled.
*/
public function action_init_do_maintenance_mode() {
$do_maintenance_mode = false;
if ( in_array( $this->options['maintenance_mode'], [ 'anonymous', 'everyone' ], true )
&& ! is_user_logged_in() ) {
$do_maintenance_mode = true;
}
if ( 'everyone' === $this->options['maintenance_mode']
&& is_user_logged_in()
&& ! current_user_can( 'manage_options' ) ) {
$do_maintenance_mode = true;
}
if ( defined( 'WP_CLI' ) && WP_CLI ) {
$do_maintenance_mode = false;
}
if ( 'wp-login.php' === $GLOBALS['pagenow'] ) {
$do_maintenance_mode = false;
}
/**
* Modify maintenance mode behavior with more advanced conditionals.
*
* @var boolean $do_maintenance_mode Whether or not to do maintenance mode.
*/
$do_maintenance_mode = apply_filters( 'pantheon_cache_do_maintenance_mode', $do_maintenance_mode );
if ( ! $do_maintenance_mode ) {
return;
}
wp_die(
__( 'Briefly unavailable for scheduled maintenance. Check back in a minute.' ),
__( 'Maintenance' ),
503
);
}
/**
* Prep the Settings API.
*
* @return void
*/
public function action_admin_init() {
register_setting( self::SLUG, self::SLUG, array( self::$instance, 'sanitize_options' ) );
add_settings_section( 'general', false, '__return_false', self::SLUG );
add_settings_field( 'default_ttl', null, array( self::$instance, 'default_ttl_field' ), self::SLUG, 'general' );
add_settings_field( 'maintenance_mode', null, array( self::$instance, 'maintenance_mode_field' ), self::SLUG, 'general' );
}
/**
* Add the settings page to the menu.
*
* @return void
*/
public function action_admin_menu() {
add_options_page( __( 'Pantheon Page Cache', 'pantheon-cache' ), __( 'Pantheon Page Cache', 'pantheon-cache' ), $this->options_capability, self::SLUG, array( self::$instance, 'view_settings_page' ) );
}
/**
* Check to see if JavaScript should trigger the opening of the plugin install box
*/
public function action_load_plugin_install() {
if ( empty( $_GET['action'] ) || 'pantheon-load-infobox' !== $_GET['action'] ) {
return;
}
add_action( 'admin_footer', array( $this, 'action_admin_footer_trigger_plugin_open' ) );
}
/**
* Trigger the opening of the Pantheon Advanced Page Cache infobox
*/
public function action_admin_footer_trigger_plugin_open() {
?>
' . __( 'Default Time to Live (TTL)', 'pantheon-cache' ) . '';
echo '
' . __( 'Maximum time a cached page will be served. A higher TTL typically improves site performance.', 'pantheon-cache' ) . '
';
echo ' ' . __( 'seconds', 'pantheon-cache' );
}
/**
* Add the HTML for the maintenance mode field.
*
* @return void
*/
public function maintenance_mode_field() {
echo '' . __( 'Maintenance Mode', 'pantheon-cache' ) . '
';
echo '' . __( 'Enable maintenance mode to work on your site while serving cached pages to:', 'pantheon-cache' ) . '
';
echo '';
echo '';
echo '';
}
/**
* Sanitize our options.
*
* @param array $in The POST values.
* @return array The sanitized POST values.
*/
public function sanitize_options( $in ) {
$out = $this->default_options;
// Validate default_ttl
$out['default_ttl'] = absint( $in['default_ttl'] );
if ( $out['default_ttl'] < 60 && isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && 'live' === $_ENV['PANTHEON_ENVIRONMENT'] ) {
$out['default_ttl'] = 60;
}
if ( ! empty( $in['maintenance_mode'] )
&& in_array( $in['maintenance_mode'], [ 'anonymous', 'everyone' ], true ) ) {
$out['maintenance_mode'] = $in['maintenance_mode'];
} else {
$out['maintenance_mode'] = 'disabled';
}
return $out;
}
/**
* Output the settings page.
*
* @return void
*/
public function view_settings_page() {
?>
Learn more', 'pantheon-cache' ), 'https://docs.pantheon.io/guides/wordpress-configurations/wordpress-cache-plugin' ) ); ?>
Pantheon Advanced Page Cache.', 'pantheon-cache' ), 'https://docs.pantheon.io/guides/wordpress-configurations/wordpress-cache-plugin' ) ); ?>
options['default_ttl'] );
if ( $ttl < 60 && isset( $_ENV['PANTHEON_ENVIRONMENT'] ) && 'live' === $_ENV['PANTHEON_ENVIRONMENT'] ) {
$ttl = 60;
}
return sprintf( 'public, max-age=%d', $ttl );
} else {
return 'no-cache, no-store, must-revalidate';
}
}
/**
* Add the cache-control header.
*
* @return void
*/
public function cache_add_headers() {
header( sprintf( 'cache-control: %s', $this->get_cache_control_header_value() ) );
}
/**
* Send the cache control header for REST API requests
*
* @param WP_REST_Response $response Response.
* @return WP_REST_Response Response.
*/
public function filter_rest_post_dispatch_send_cache_control( $response ) {
$response->header( 'Cache-Control', $this->get_cache_control_header_value() );
return $response;
}
/**
* Clear the cache for the entire site.
*
* @return void
*/
public function flush_site() {
if ( ! function_exists( 'current_user_can' ) || false == current_user_can( 'manage_options' ) )
return false;
if ( ! empty( $_POST['pantheon-cache-nonce'] ) && wp_verify_nonce( $_POST['pantheon-cache-nonce'], 'pantheon-cache-clear-all' ) ) {
if ( function_exists( 'pantheon_clear_edge_all' ) ) {
pantheon_clear_edge_all();
}
wp_cache_flush();
wp_redirect( admin_url( 'options-general.php?page=pantheon-cache&cache-cleared=true' ) );
exit();
}
}
/**
* Clear the cache for a post.
*
* @deprecated
*
* @param int $post_id A post ID to clean.
* @return void
*/
public function clean_post_cache( $post_id, $include_homepage = true ) {
if ( method_exists( 'Pantheon_Advanced_Page_Cache\Purger', 'action_clean_post_cache' ) ) {
Pantheon_Advanced_Page_Cache\Purger::action_clean_post_cache( $post_id );
}
}
/**
* Clear the cache for a given term or terms and taxonomy.
*
* @deprecated
*
* @param int|array $ids Single or list of Term IDs.
* @param string $taxonomy Can be empty and will assume tt_ids, else will use for context.
* @return void
*/
public function clean_term_cache( $term_ids, $taxonomy ) {
if ( method_exists( 'Pantheon_Advanced_Page_Cache\Purger', 'action_clean_term_cache' ) ) {
Pantheon_Advanced_Page_Cache\Purger::action_clean_term_cache( $term_ids );
}
}
/**
* Clear the cache for a given term or terms and taxonomy.
*
* @deprecated
*
* @param int|array $object_ids Single or list of term object ID(s).
* @param array|string $object_type The taxonomy object type.
* @return void
*/
public function clean_object_term_cache( $object_ids, $object_type ) {
// Handled by Pantheon Integrated CDN
}
/**
* Enqueue Fully-qualified urls to be cleared on shutdown.
*
* @param array|string $urls List of full urls to clear.
* @return void
*/
public function enqueue_urls( $urls ) {
$paths = array();
$urls = array_filter( (array) $urls, 'is_string' );
foreach ( $urls as $full_url ) {
# Parse down to the path+query, escape regex.
$parsed = parse_url( $full_url );
# Sometimes parse_url can return false, on malformed urls
if (FALSE == $parsed) {
continue;
}
# Build up the path, checking if the array key exists first
if (array_key_exists('path', $parsed)) {
$path = $parsed['path'];
if (array_key_exists('query', $parsed)) {
$path = $path . $parsed['query'];
}
}
# If the path doesn't exist, set it to the null string
else {
$path = '';
}
if ( '' == $path ) {
continue;
}
$path = '^' . preg_quote( $path ) . '$';
$paths[] = $path;
}
$this->paths = array_merge( $this->paths, $paths );
}
/**
* Enqueue a regex to be cleared.
*
* You must understand regular expressions to use this, and be careful.
*
* @param string $regex path regex to clear.
* @return void
*/
public function enqueue_regex( $regex ) {
$this->paths[] = $regex;
}
public function cache_clean_urls() {
if ( empty( $this->paths ) )
return;
$this->paths = apply_filters( 'pantheon_clean_urls', array_unique( $this->paths ) );
# Call the big daddy here
$url = home_url();
$host = parse_url( $url, PHP_URL_HOST );
$this->paths = apply_filters( 'pantheon_final_clean_urls', $this->paths );
if ( function_exists( 'pantheon_clear_edge_paths' ) ) {
pantheon_clear_edge_paths( $this->paths );
}
}
}
/**
* Get a reference to the singleton.
*
* This can be used to reference public methods, e.g. `Pantheon_Cache()->clean_post_cache( 123 )`
*
* @return void
*/
function Pantheon_Cache() {
return Pantheon_Cache::instance();
}
add_action( 'plugins_loaded', 'Pantheon_Cache' );
/**
* @see Pantheon_Cache::clean_post_cache
*
* @deprecated Please call Pantheon Integrated CDN instead.
*/
function pantheon_clean_post_cache( $post_id, $include_homepage = true ) {
Pantheon_Cache()->clean_post_cache( $post_id, $include_homepage );
}
/**
* @see Pantheon_Cache::clean_term_cache
*
* @deprecated Please call Pantheon Integrated CDN instead.
*/
function pantheon_clean_term_cache( $term_ids, $taxonomy ) {
Pantheon_Cache()->clean_term_cache( $term_ids, $taxonomy );
}
/**
* @see Pantheon_Cache::enqueue_urls
*
* @deprecated Please call Pantheon Integrated CDN instead.
*/
function pantheon_enqueue_urls( $urls ) {
Pantheon_Cache()->enqueue_urls( $urls );
}