cloudflare-cache-purger/cloudflare-cache-purger.php
lsemenenko a1ab59c34d
Adds cache purge on post update
Triggers cache purge when post moves from publish to publish.
Updates plugin info to reflect the cache purge on updates.
2025-08-17 00:58:13 -05:00

302 lines
13 KiB
PHP

<?php
/**
* Plugin Name: Cloudflare Cache Purger
* Plugin URI: https://git.optimull.com/lsemenenko/cloudflare-cache-purger
* Description: Automatically purges Cloudflare cache when specific WordPress hooks are fired.
* Version: 1.0.0
* Author: Leonid Semenenko
* Author URI: https://optimull.com
* License: GPL-2.0+
* License URI: http://www.gnu.org/licenses/gpl-2.0.txt
* Text Domain: cloudflare-cache-purger
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Cloudflare_Cache_Purger {
/**
* Cloudflare API credentials.
*/
private $api_token;
private $zone_id;
/**
* Debug mode flag.
*/
private $debug_mode;
/**
* Initialize the plugin.
*/
public function __construct() {
// Load settings.
$this->load_settings();
// Register hooks to purge cache.
$this->register_hooks();
// Add admin menu.
add_action( 'admin_menu', array( $this, 'add_admin_menu' ) );
add_action( 'admin_init', array( $this, 'register_settings' ) );
}
/**
* Load settings from WordPress options.
*/
private function load_settings() {
$this->api_token = get_option( 'cloudflare_cache_purger_api_token', '' );
$this->zone_id = get_option( 'cloudflare_cache_purger_zone_id', '' );
$this->debug_mode = get_option( 'cloudflare_cache_purger_debug', false );
}
/**
* Register hooks that will trigger cache purge.
*/
private function register_hooks() {
// Hooks specified in requirements.
add_action( 'publish_to_publish', array( $this, 'purge_cache' ) );
add_action( 'pending_to_publish', array( $this, 'purge_cache' ) );
add_action( 'publish_to_trash', array( $this, 'purge_cache' ) );
add_action( 'future_to_publish', array( $this, 'purge_cache' ) );
add_action( 'draft_to_publish', array( $this, 'purge_cache' ) );
add_action( 'delete_attachment', array( $this, 'purge_cache' ) );
add_action( 'autoptimize_action_cachepurged', array( $this, 'purge_cache' ) );
add_action( 'switch_theme', array( $this, 'purge_cache' ) );
add_action( 'customize_save_after', array( $this, 'purge_cache' ) );
}
/**
* Write debug information to a log file in wp-content.
*
* @param string $message The debug message.
*/
private function debug_log( $message ) {
$log_file = WP_CONTENT_DIR . '/cloudflare-cache-purger-debug.log';
$formatted_message = '[' . date( 'Y-m-d H:i:s' ) . '] ' . $message . "\n";
file_put_contents( $log_file, $formatted_message, FILE_APPEND );
}
/**
* Purge the Cloudflare cache.
*/
public function purge_cache() {
// Check if credentials are set.
if ( empty( $this->api_token ) || empty( $this->zone_id ) ) {
error_log( 'Cloudflare Cache Purger: API credentials not set.' );
if ( $this->debug_mode ) {
$this->debug_log( 'API credentials not set.' );
}
return;
}
// Prepare request to Cloudflare API.
$url = "https://api.cloudflare.com/client/v4/zones/{$this->zone_id}/purge_cache";
$headers = array(
'Authorization: Bearer ' . $this->api_token,
'Content-Type: application/json'
);
// Purge everything.
$data = json_encode( array( 'purge_everything' => true ) );
// Log the purge event if debug is enabled.
if ( $this->debug_mode ) {
$this->debug_log( "Initiating cache purge. URL: $url, Data: $data" );
}
// Initialize cURL.
$ch = curl_init();
curl_setopt( $ch, CURLOPT_URL, $url );
curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'POST' );
curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch, CURLOPT_POSTFIELDS, $data );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
// Execute request.
$result = curl_exec( $ch );
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
// Close cURL.
curl_close( $ch );
// Log API response if debug is enabled.
if ( $this->debug_mode ) {
$this->debug_log( "API response: HTTP Code: $http_code, Result: $result" );
}
// Log result to error_log and show admin notices.
if ( $http_code >= 200 && $http_code < 300 ) {
error_log( 'Cloudflare Cache Purger: Cache successfully purged.' );
if ( is_admin() ) {
add_action( 'admin_notices', function() {
echo '<div class="notice notice-success is-dismissible"><p>Cloudflare cache has been purged successfully.</p></div>';
} );
}
} else {
error_log( 'Cloudflare Cache Purger: Failed to purge cache. Error: ' . $result );
if ( is_admin() ) {
add_action( 'admin_notices', function() use ( $result ) {
$error_message = json_decode( $result, true );
$message = isset( $error_message['errors'][0]['message'] ) ? $error_message['errors'][0]['message'] : 'Unknown error';
echo '<div class="notice notice-error is-dismissible"><p>Failed to purge Cloudflare cache: ' . esc_html( $message ) . '</p></div>';
} );
}
}
}
/**
* Add admin menu.
*/
public function add_admin_menu() {
add_options_page(
'Cloudflare Cache Purger Settings',
'Cloudflare Cache',
'manage_options',
'cloudflare-cache-purger',
array( $this, 'settings_page' )
);
}
/**
* Register plugin settings.
*/
public function register_settings() {
register_setting( 'cloudflare_cache_purger', 'cloudflare_cache_purger_api_token' );
register_setting( 'cloudflare_cache_purger', 'cloudflare_cache_purger_zone_id' );
register_setting( 'cloudflare_cache_purger', 'cloudflare_cache_purger_debug' );
add_settings_section(
'cloudflare_cache_purger_section',
'Cloudflare API Settings',
array( $this, 'settings_section_callback' ),
'cloudflare-cache-purger'
);
add_settings_field(
'cloudflare_cache_purger_api_token',
'Cloudflare API Token',
array( $this, 'api_token_field_callback' ),
'cloudflare-cache-purger',
'cloudflare_cache_purger_section'
);
add_settings_field(
'cloudflare_cache_purger_zone_id',
'Cloudflare Zone ID',
array( $this, 'zone_id_field_callback' ),
'cloudflare-cache-purger',
'cloudflare_cache_purger_section'
);
add_settings_field(
'cloudflare_cache_purger_debug',
'Enable Debug Logging',
array( $this, 'debug_field_callback' ),
'cloudflare-cache-purger',
'cloudflare_cache_purger_section'
);
}
/**
* Settings section description.
*/
public function settings_section_callback() {
echo '<p>Enter your Cloudflare API credentials to enable automatic cache purging.</p>';
echo '<p>You can find your Zone ID in the Cloudflare dashboard under "Overview" > "API" section.</p>';
echo '<p>Create an API token with the "Zone.Cache Purge" permission in the Cloudflare dashboard under "My Profile" > "API Tokens".</p>';
}
/**
* API token field callback.
*/
public function api_token_field_callback() {
$api_token = get_option( 'cloudflare_cache_purger_api_token', '' );
echo '<input type="password" id="cloudflare_cache_purger_api_token" name="cloudflare_cache_purger_api_token" value="' . esc_attr( $api_token ) . '" class="regular-text" />';
echo '<p class="description">Your Cloudflare API token. Create one with "Zone.Cache Purge" permission.</p>';
}
/**
* Zone ID field callback.
*/
public function zone_id_field_callback() {
$zone_id = get_option( 'cloudflare_cache_purger_zone_id', '' );
echo '<input type="text" id="cloudflare_cache_purger_zone_id" name="cloudflare_cache_purger_zone_id" value="' . esc_attr( $zone_id ) . '" class="regular-text" />';
echo '<p class="description">Your Cloudflare Zone ID for the domain.</p>';
}
/**
* Debug field callback.
*/
public function debug_field_callback() {
$debug = get_option( 'cloudflare_cache_purger_debug', false );
?>
<input type="checkbox" id="cloudflare_cache_purger_debug" name="cloudflare_cache_purger_debug" value="1" <?php checked( 1, $debug ); ?> />
<p class="description">Enable debug logging. Debug messages will be saved to <code>wp-content/cloudflare-cache-purger-debug.log</code>.</p>
<?php
}
/**
* Settings page content.
*/
public function settings_page() {
// Check user capabilities.
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
?>
<div class="wrap">
<h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
<form action="options.php" method="post">
<?php
settings_fields( 'cloudflare_cache_purger' );
do_settings_sections( 'cloudflare-cache-purger' );
submit_button( 'Save Settings' );
?>
</form>
<div class="card">
<h2>Manual Cache Purge</h2>
<p>Click the button below to manually purge the Cloudflare cache.</p>
<form method="post" action="">
<?php wp_nonce_field( 'manual_purge_action', 'manual_purge_nonce' ); ?>
<input type="hidden" name="action" value="manual_purge">
<input type="submit" class="button button-primary" value="Purge Cache">
</form>
</div>
<div class="card">
<h2>Automatic Purge Events</h2>
<p>This plugin automatically purges the Cloudflare cache when any of these WordPress events occur:</p>
<ul style="list-style-type: disc; margin-left: 20px;">
<li>When a post is edited</li>
<li>When a post is updated</li>
<li>When a post is saved</li>
<li>When a post is deleted</li>
<li>When an attachment is deleted</li>
<li>When Autoptimize purges its cache</li>
<li>When a theme is switched</li>
<li>When customizer changes are saved</li>
</ul>
</div>
</div>
<?php
// Handle manual purge.
if (
isset( $_POST['action'] ) &&
$_POST['action'] === 'manual_purge' &&
isset( $_POST['manual_purge_nonce'] ) &&
wp_verify_nonce( $_POST['manual_purge_nonce'], 'manual_purge_action' )
) {
$this->purge_cache();
echo '<div class="notice notice-info is-dismissible"><p>Manual cache purge initiated.</p></div>';
}
}
}
// Initialize the plugin.
$cloudflare_cache_purger = new Cloudflare_Cache_Purger();