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 ); }