true, 'cloudflare_enabled' => false, 'cloudflare_zone_id' => '', 'cloudflare_api_token' => '', 'sucuri_enabled' => false, 'sucuri_api_key' => '', 'sucuri_api_secret' => '', 'fastly_enabled' => false, 'fastly_service_id' => '', 'fastly_api_token' => '', 'akamai_enabled' => false, 'akamai_client_token' => '', 'akamai_access_token' => '', 'akamai_client_secret' => '', 'akamai_host' => '', 'sevalla_enabled' => false, 'sevalla_api_key' => '', 'sevalla_application_id' => '', 'cloudways_enabled' => false, 'flywheel_enabled' => false, ); } /** * Get all settings merged with defaults. * * @return array */ public static function get_settings() { return wp_parse_args( get_option(self::OPTION_KEY, array()), self::get_defaults() ); } /** * All setting keys that hold boolean toggles. * * @return array */ private static function get_bool_keys() { return array( 'cache_tags_enabled', 'cloudflare_enabled', 'sucuri_enabled', 'fastly_enabled', 'akamai_enabled', 'sevalla_enabled', 'cloudways_enabled', 'flywheel_enabled', ); } /** * Sanitize and save settings from $_POST. * * @param array $post POST data (defaults to $_POST). * @return bool True if saved. */ public static function save_from_post($post = null) { if ($post === null) { $post = $_POST; } // Only save if at least one edge-cache field is present in the payload. if (!isset($post['cache_tags_enabled'])) { return false; } $bool_keys = self::get_bool_keys(); $defaults = self::get_defaults(); $settings = array(); foreach ($defaults as $key => $default) { if (in_array($key, $bool_keys, true)) { $settings[$key] = !empty($post[$key]) && $post[$key] === '1'; } else { $settings[$key] = sanitize_text_field($post[$key] ?? ''); } } update_option(self::OPTION_KEY, $settings); return true; } /** * AJAX handler: save edge cache settings (standalone endpoint). */ public static function ajax_save() { if (!isset($_POST[self::NONCE_FIELD]) || !wp_verify_nonce($_POST[self::NONCE_FIELD], self::NONCE_ACTION)) { wp_send_json_error(array('message' => 'Security check failed')); return; } if (!Metasync::current_user_has_plugin_access()) { wp_send_json_error(array('message' => 'Insufficient permissions')); return; } self::save_from_post(); wp_send_json_success(array('message' => 'Edge cache settings saved')); } /** * Render the Edge Cache / CDN settings section. */ public static function render() { $settings = self::get_settings(); $show_sevalla = !class_exists('KinstaCache'); $show_cloudways = !empty($_SERVER['HTTP_X_VARNISH']) || !empty(get_option('metasync_cloudways_detected')); $show_flywheel = defined('FLYWHEEL_CONFIG_DIR'); ?>
Configure CDN credentials for cache-tag purging. When enabled, cache-tag headers are added to OTTO-processed pages so CDNs can purge by post ID.
How it works:
Adds Cache-Tag,
Surrogate-Key, and
Edge-Cache-Tag
headers to singular pages. These allow Cloudflare, Fastly, Akamai, and other CDNs to purge individual posts by tag instead of flushing the entire cache.
my.sevalla.com/applications/{UUID}'),
), !$has_more_after_sevalla, 'Uses v3 edge cache purge API with v2 fallback. If KinstaCache mu-plugin is available, native purge is used instead.');
}
if ($show_cloudways) {
self::render_provider('cloudways', 'Cloudways', 'purges Varnish cache per URL', $settings, array(), !$show_flywheel, 'Detected Cloudways Varnish. Enable to purge Varnish on each OTTO update.');
}
if ($show_flywheel) {
self::render_provider('flywheel', 'Flywheel', 'full cache flush on OTTO updates', $settings, array(), true, 'Detected Flywheel hosting. Enable to clear cache on each OTTO update.');
}
?>