'; echo '

' . esc_html__( 'Cache settings updated.', 'pressable_cache_management' ) . '

'; echo ''; echo ''; } // ─── "Extending Batcache" notice — shows ONCE after first enable, then never again ─ // extend_batcache.php sets 'pcm_extend_batcache_notice_pending' only when it copies // the mu-plugin for the first time (fresh enable). We delete the flag here immediately // after rendering, so any subsequent page load or refresh will never see it again. add_action( 'admin_notices', 'pcm_extend_batcache_branded_notice' ); function pcm_extend_batcache_branded_notice() { if ( ! isset( $_GET['page'] ) || sanitize_key( $_GET['page'] ) !== 'pressable_cache_management' ) return; if ( ! current_user_can( 'manage_options' ) ) return; // Only show if freshly enabled if ( '1' !== get_option( 'pcm_extend_batcache_notice_pending' ) ) return; // Delete flag IMMEDIATELY — refresh / navigation will never trigger this again delete_option( 'pcm_extend_batcache_notice_pending' ); $wrap = 'display:flex;align-items:center;justify-content:space-between;gap:12px;' . 'border-left:4px solid #03fcc2;background:#fff;border-radius:0 8px 8px 0;' . 'padding:14px 18px;box-shadow:0 2px 8px rgba(4,0,36,.07);' . 'margin:10px 0;font-family:sans-serif;'; $btn = 'background:none;border:none;cursor:pointer;color:#94a3b8;font-size:18px;line-height:1;padding:0;'; echo '
'; echo '
'; echo '

' . esc_html__( 'Extending Batcache for 24 hours — see ', 'pressable_cache_management' ) . '' . esc_html__( 'Modifying Batcache Times.', 'pressable_cache_management' ) . '' . '

'; echo ''; echo '
'; echo '
'; } // ─── Helper: pcm_branded_notice (shared, safe) ─────────────────────────────── if ( ! function_exists( 'pcm_branded_notice' ) ) { function pcm_branded_notice( $message, $border_color = '#03fcc2', $is_html = false ) { $id = 'pcm-notice-' . substr( md5( $message . $border_color . microtime() ), 0, 8 ); $wrap = 'display:inline-flex;align-items:flex-start;justify-content:space-between;gap:16px;' . 'border-left:4px solid ' . esc_attr( $border_color ) . ';background:#fff;' . 'border-radius:0 8px 8px 0;padding:14px 18px;' . 'box-shadow:0 2px 8px rgba(4,0,36,.07);margin:10px 0 10px 8px;font-family:sans-serif;min-width:260px;max-width:480px;'; $btn = 'background:none;border:none;cursor:pointer;color:#94a3b8;font-size:18px;' . 'line-height:1;padding:0;flex-shrink:0;margin-top:2px;'; echo '
'; if ( $is_html ) { echo $message; } else { echo '

' . esc_html( $message ) . '

'; } echo '
'; } } // ─── Batcache status check ─────────────────────────────────────────────────── // WHY BROWSER-SIDE: wp_remote_get() is a server-side loopback request. Pressable's // infrastructure routes loopback requests directly to PHP, bypassing the Batcache/CDN // layer entirely — so x-nananana is never present regardless of real cache state. // The browser is the only client that sees the actual CDN response headers. // SOLUTION: JS fetches the homepage with cache:reload (forces a fresh CDN response) // and reads x-nananana directly, then reports the result back to PHP via AJAX. // PHP only stores/returns the transient — it never probes the URL itself. function pcm_get_batcache_status() { $cached = get_transient( 'pcm_batcache_status' ); return ( $cached !== false ) ? $cached : 'unknown'; } // ── AJAX: browser reports the header value it observed ─────────────────────── function pcm_ajax_report_batcache_header() { check_ajax_referer( 'pcm_batcache_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'Unauthorized', 403 ); } $raw = isset( $_POST['x_nananana'] ) ? sanitize_text_field( wp_unslash( $_POST['x_nananana'] ) ) : ''; $val = strtolower( trim( $raw ) ); if ( strpos( $val, 'batcache' ) !== false ) { $status = 'active'; } elseif ( isset( $_POST['is_cloudflare'] ) && $_POST['is_cloudflare'] === '1' ) { $status = 'cloudflare'; } else { $status = 'broken'; } // Active: 24 hrs — prevents the badge falsely flipping to broken after 5 min. // Broken: 2 min — re-probe frequently until resolved. $ttl = ( $status === 'active' ) ? 86400 : 120; set_transient( 'pcm_batcache_status', $status, $ttl ); $labels = array( 'active' => __( 'Batcache Active', 'pressable_cache_management' ), 'cloudflare' => __( 'Cloudflare Detected', 'pressable_cache_management' ), 'broken' => __( 'Batcache Broken', 'pressable_cache_management' ), ); wp_send_json_success( array( 'status' => $status, 'label' => $labels[ $status ], ) ); } add_action( 'wp_ajax_pcm_report_batcache_header', 'pcm_ajax_report_batcache_header' ); // ── AJAX: return current stored status (for badge refresh without re-fetching) ─ function pcm_ajax_get_batcache_status() { check_ajax_referer( 'pcm_batcache_nonce', 'nonce' ); if ( ! current_user_can( 'manage_options' ) ) { wp_send_json_error( 'Unauthorized', 403 ); } $status = pcm_get_batcache_status(); $labels = array( 'active' => __( 'Batcache Active', 'pressable_cache_management' ), 'cloudflare' => __( 'Cloudflare Detected', 'pressable_cache_management' ), 'broken' => __( 'Batcache Broken', 'pressable_cache_management' ), 'unknown' => __( 'Batcache Broken', 'pressable_cache_management' ), ); wp_send_json_success( array( 'status' => $status, 'label' => isset( $labels[ $status ] ) ? $labels[ $status ] : $labels['broken'], ) ); } add_action( 'wp_ajax_pcm_get_batcache_status', 'pcm_ajax_get_batcache_status' ); // Keep the old action name as an alias so any cached JS still works add_action( 'wp_ajax_pcm_refresh_batcache_status', 'pcm_ajax_get_batcache_status' ); /** * Clear the cached status immediately after any cache flush * so the badge re-checks on next page load. */ function pcm_clear_batcache_status_transient() { delete_transient( 'pcm_batcache_status' ); } add_action( 'pcm_after_object_cache_flush', 'pcm_clear_batcache_status_transient' ); add_action( 'pcm_after_batcache_flush', 'pcm_clear_batcache_status_transient' ); // Also clear when edge cache is fully purged — Batcache is implicitly invalidated too, // so the next probe will correctly detect the transitional 'broken' state. add_action( 'pcm_after_edge_cache_purge', 'pcm_clear_batcache_status_transient' ); // ─── Main page ─────────────────────────────────────────────────────────────── function pressable_cache_management_display_settings_page() { if ( ! current_user_can('manage_options') ) return; $tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : null; $branding_opts = get_option('remove_pressable_branding_tab_options'); $show_branding = ! ( $branding_opts && 'disable' == $branding_opts['branding_on_off_radio_button'] ); wp_enqueue_style( 'pressable_cache_management', plugin_dir_url( dirname( __FILE__ ) ) . 'public/css/style.css', array(), '3.0.0', 'screen' ); wp_enqueue_style( 'pcm-google-fonts', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap', array(), null ); ?>

?



array( 'title' => '🔌 ' . __( 'Flush Cache on Plugin/Theme Update', 'pressable_cache_management' ), 'desc' => __( 'Flush cache automatically on plugin & theme update.', 'pressable_cache_management' ), 'ts' => get_option('flush-cache-theme-plugin-time-stamp'), ), 'flush_cache_page_edit_checkbox' => array( 'title' => '📝 ' . __( 'Flush Cache on Post/Page Edit', 'pressable_cache_management' ), 'desc' => __( 'Flush cache automatically when page/post/post_types are updated.', 'pressable_cache_management' ), 'ts' => get_option('flush-cache-page-edit-time-stamp'), ), 'flush_cache_on_comment_delete_checkbox' => array( 'title' => '💬 ' . __( 'Flush Cache on Comment Delete', 'pressable_cache_management' ), 'desc' => __( 'Flush cache automatically when comments are deleted.', 'pressable_cache_management' ), 'ts' => get_option('flush-cache-on-comment-delete-time-stamp'), ), ); foreach ( $rules as $id => $rule ) : $checked = isset($options[$id]) ? checked($options[$id], 1, false) : ''; ?>

/page/ /your-site.com/, /about-us/, /info/

'pcm-main-settings-form') ); ?>

'enable')); } add_filter('admin_footer_text','pcm_replace_default_footer'); } function pcm_replace_default_footer($footer_text) { if ( is_admin() && isset($_GET['page']) && sanitize_key( $_GET['page'] ) === 'pressable_cache_management' ) { $opts = get_option('remove_pressable_branding_tab_options'); $branding_disabled = $opts && 'disable' === $opts['branding_on_off_radio_button']; if ( $branding_disabled ) { // Branding hidden: "Built with ♥" — heart links to branding settings page return 'Built with '; } else { // Branding shown: full credit — heart links to branding settings page return 'Built with by The Pressable CS Team.'; } } return $footer_text; } add_action('admin_init','pcm_footer_msg');