Caching & Transients

CWP Snippets provides a set of helper functions for caching data using WordPress transients. All cache keys are automatically prefixed with cwpUF_ to avoid conflicts with other plugins.


Core Caching Functions

cwpCacheData($key, $data = null, $expire = 3600)

Set or get cached data using WordPress transients. All keys are automatically prefixed with cwpUF_.

Set cache:

cwpCacheData('my_key', $data, 3600); // Cache for 1 hour

Get cache:

$data = cwpCacheData('my_key'); // Returns cached value or false if expired/not found

Disable caching (development):

// Set cache duration to 0 to disable caching
$cache_duration = 0;
if ($cache_duration > 0) {
    cwpCacheData('my_key', $data, $cache_duration);
}

Parameters:

  • $key (string, required): Unique cache key (will be automatically prefixed with cwpUF_)
  • $data (mixed, optional): Data to cache. If null, function returns the cached value
  • $expire (int, optional): Expiry in seconds (default: 3600 = 1 hour)

Returns:

  • When getting (data is null): Returns cached value or false
  • When setting: Returns true on success, false on failure

cwpClearCache($key)

Clear a specific cached item by key.

Usage:

$result = cwpClearCache('my_key'); // Returns true if deleted, false otherwise

Parameters:

  • $key (string, required): Cache key to clear (will be automatically prefixed with cwpUF_)

Returns: Boolean - true if deleted, false otherwise


cwpClearCacheWildcard($prefix, $limit = 25)

Delete multiple transients by prefix wildcard. For example, prefix alex_ deletes all keys starting with alex_.

Usage:

$result = cwpClearCacheWildcard('user_', 50);
// Returns: ['matched' => 3, 'deleted' => 3, 'matched_keys' => [...], 'warning' => null]

Parameters:

  • $prefix (string, required): Logical prefix (without cwpUF_ prefix). Do NOT include trailing *
  • $limit (int, optional): Maximum number of matches to process (default: 25)

Returns: Array with keys:

  • matched (int): Total number of matching transients found
  • deleted (int): Number successfully deleted
  • matched_keys (array): List of matched cache keys
  • warning (string|null): Warning message if limits exceeded or errors occurred

Important notes:

  • Do NOT include the asterisk (*) in the prefix parameter
  • If more keys match than the limit, only the first N (alphabetically) are processed
  • A warning is returned if the match count exceeds the limit
  • Invalid prefixes (empty string, contains *) return a warning

cwpClearAllTransients($prefix = 'cwpUF_')

Clear ALL transients with the specified prefix. By default, clears all CWP Snippets cache.

Usage:

$deleted = cwpClearAllTransients(); // Clears all cwpUF_* transients
// Returns: 12 (number of transients deleted)

Parameters:

  • $prefix (string, optional): Prefix to match (default: 'cwpUF_')

Returns: Integer - number of transients deleted


REST API Endpoint

POST /wp-json/cwp/v1/clear-cache

Allows external applications (e.g., FileMaker) to clear cache via REST API.

Clear a Specific Key

Request:

curl -X POST https://example.com/wp-json/cwp/v1/clear-cache \
  -H "Content-Type: application/json" \
  -d '{"cache_key":"my_key"}'

Response:

{
  "success": true,
  "message": "Cache 'my_key' cleared."
}

Clear Multiple Keys

Request:

curl -X POST https://example.com/wp-json/cwp/v1/clear-cache \
  -H "Content-Type: application/json" \
  -d '{"cache_key":["key1","key2","key3"]}'

Response:

{
  "success": true,
  "results": {
    "exact": {
      "key1": true,
      "key2": true,
      "key3": false
    }
  },
  "message": "Processed multiple cache keys."
}

Clear by Wildcard Prefix

Request:

curl -X POST https://example.com/wp-json/cwp/v1/clear-cache \
  -H "Content-Type: application/json" \
  -d '{"cache_key":"user_*"}'

Response:

{
  "success": true,
  "result": {
    "matched": 3,
    "deleted": 3,
    "matched_keys": ["user_123", "user_456", "user_789"],
    "warning": null
  },
  "message": "Processed wildcard prefix."
}

Clear All Cache

Request (Method 1 - clear_all flag):

curl -X POST https://example.com/wp-json/cwp/v1/clear-cache \
  -H "Content-Type: application/json" \
  -d '{"clear_all":true}'

Request (Method 2 - special cache_key):

curl -X POST https://example.com/wp-json/cwp/v1/clear-cache \
  -H "Content-Type: application/json" \
  -d '{"cache_key":"clear_all"}'

Response:

{
  "success": true,
  "deleted": 12,
  "message": "Deleted 12 transients."
}

Delimiter-Separated Keys

You can send comma, semicolon, or newline-separated keys as a string:

Request:

curl -X POST https://example.com/wp-json/cwp/v1/clear-cache \
  -H "Content-Type: application/json" \
  -d '{"cache_key":"key1, key2, user_*"}'

FileMaker Integration

Insert from URL Examples

Clear Specific Key

FileMaker Script:

Set Variable [ $url ; Value: "https://your-site.com/wp-json/cwp/v1/clear-cache" ]
Set Variable [ $cacheKey ; Value: "my_cache_key" ]
Set Variable [ $curlOptions ; Value: "--request POST --header \"Content-Type: application/json\" --data \"{\\\"cache_key\\\":\\\"" & $cacheKey & "\\\"}\"" ]
Insert from URL [ Select ; With dialog: Off ; Target: $$result ; $url ; cURL options: $curlOptions ]

Clear All Cache

FileMaker Script:

Set Variable [ $url ; Value: "https://your-site.com/wp-json/cwp/v1/clear-cache" ]
Set Variable [ $curlOptions ; Value: "--request POST --header \"Content-Type: application/json\" --data \"{\\\"clear_all\\\":true}\"" ]
Insert from URL [ Select ; With dialog: Off ; Target: $$result ; $url ; cURL options: $curlOptions ]

Using Let Calculation (No Manual Escaping)

Let(
  [
    json = JSONSetElement("{}"; "cache_key"; "my_key"; JSONString);
    curl = "--request POST " &
           "--header " & Quote("Content-Type: application/json") & " " &
           "--data " & Quote(json) & " " &
           "--max-time 30"
  ];
  curl
)

Security Considerations

Important: The REST endpoint is intentionally permissive by default for ease of testing and development. For production use, you should add authentication:

  1. Token-based authentication:

    // Add to the REST endpoint permission_callback
    if ($request->get_param('token') !== 'your_secret_token') {
     return false;
    }
  2. IP allowlist:

    // Restrict to specific IP addresses
    if (!in_array($_SERVER['REMOTE_ADDR'], ['1.2.3.4', '5.6.7.8'])) {
     return false;
    }
  3. WordPress capability check:

    // Require admin user
    if (!current_user_can('manage_options')) {
     return false;
    }

Clear-all operations explicitly check for manage_options capability before executing, providing an additional security layer for destructive operations.


Additional Helper Functions

cwp_cache_bust($url, $version = null)

Append a cache-busting query string to asset URLs to force browsers to reload updated files.

Usage:

// Using file modification time (recommended)
$url = cwp_cache_bust(get_stylesheet_directory_uri() . '/style.css');
// Returns: https://site.com/style.css?v=1704844800

// Using custom version
$url = cwp_cache_bust(get_stylesheet_directory_uri() . '/script.js', '1.2.3');
// Returns: https://site.com/script.js?v=1.2.3

Parameters:

  • $url (string, required): The asset URL to modify
  • $version (string|int, optional): Version or timestamp. If null, uses file modification time or current timestamp

Returns: Cache-busted URL string, or false if URL is invalid


cwpIsURLValid($data, $logging = false, $checkCount = 1, $random = false)

Quickly check whether cached FileMaker responses contain expired Streaming_SSL image URLs.

Purpose: Validates FileMaker container image URLs before serving cached data to ensure images are still accessible.

Usage:

$cached = cwpCacheData('fm_records');
if ($cached && cwpIsURLValid($cached, true)) {
    // Cache is valid, use it
} else {
    // Refresh cache from FileMaker
}

Parameters:

  • $data (string|array, required): A URL string or FileMaker response array to validate
  • $logging (bool, optional): Log failures to CWP error log (default: false)
  • $checkCount (int, optional): Number of URLs to validate (default: 1)
  • $random (bool, optional): Sample URLs randomly if true, or use first N if false (default: false)

Returns: Boolean

  • true if all sampled URLs return 2xx HTTP status
  • false if any URL fails validation

Behavior:

  • Recursively scans arrays for values containing Streaming_SSL (case-insensitive)
  • Performs HTTP HEAD requests with short timeouts
  • Falls back to GET request if HEAD fails
  • Returns true immediately if no Streaming_SSL URLs found

Examples:

// Check single cached response with logging
if (!cwpIsURLValid($cached, true)) {
    // Refresh cache
}

// Check 3 random images
if (!cwpIsURLValid($response, true, 3, true)) {
    // One or more URLs failed
}

cwpShowTransients()

Display all current CWP transients and their expiry times for debugging.

Usage:

cwpShowTransients(); // Only visible to users with 'manage_options' capability

Security: Automatically restricted to admin users only.


Best Practices

  1. Use descriptive cache keys:

    // Good
    cwpCacheData('user_profile_123', $data);
    
    // Bad
    cwpCacheData('data', $data);
  2. Set appropriate expiry times:

    // Frequently changing data - 5 minutes
    cwpCacheData('stock_prices', $data, 300);
    
    // Rarely changing data - 7 days
    cwpCacheData('company_info', $data, 604800);
  3. Clear cache when data changes:

    // After updating a record
    cwpClearCache('user_profile_' . $user_id);
    
    // Or clear related wildcards
    cwpClearCacheWildcard('user_profile_', 50);
  4. Use wildcards for grouped data:

    // Cache with consistent prefix
    cwpCacheData('invoice_' . $invoice_id, $data);
    cwpCacheData('invoice_meta_' . $invoice_id, $meta);
    
    // Clear all invoice-related cache
    cwpClearCacheWildcard('invoice_', 100);
  5. Disable caching during development:

    $cache_duration = 0; // Set to 0 to disable
    if ($cache_duration > 0) {
        cwpCacheData($key, $data, $cache_duration);
    }
  6. Add logging for external clears:

    // In your REST endpoint permission_callback or handler
    cwpLog('cache_cleared', 'External API cleared cache: ' . $cache_key);
        "--max-time 30"

    ]; curl )

  • To include a token in the JSON body: add JSONSetElement() entries for token or append --header "Authorization: Bearer <token>" using Quote().

  • Admin-AJAX (simple backdoor / quick test):

    • URL (GET): https://your-site/wp-admin/admin-ajax.php?action=cwp_clear_cache&clear_all=1
    • Or POST (form-encoded):
--request POST --header "Content-Type: application/x-www-form-urlencoded" --data "clear_all=1" --max-time 30
  • From FileMaker you can either place the query string in the URL field (no cURL options needed) or send the POST body via the cURL options box.

Notes about escaping in FileMaker

  • If you paste raw cURL options into the cURL box, JSON double-quotes must be escaped (e.g., \"clear_all\":true).
  • Use Quote() and JSONSetElement() in a calculation to avoid manual escaping and to produce valid JSON automatically.

Why JSON vs form-encoded

  • The REST endpoint expects JSON and will parse the body automatically when Content-Type is application/json. Admin-AJAX can accept form-encoded parameters and is convenient for quick tests.

Safety & recommendations

  • The REST route and the simple AJAX handler are intentionally permissive in this codebase for convenience and testing. In production, prefer:
    • A long unguessable token validated in permission_callback or inside the handler; or
    • Restrict access by IP/network; or
    • Require an authenticated admin request (remove nopriv registration).
  • Add logging (cwpLog) for any external clears so you can audit who/when cleared caches.

Transient Expiry Viewer

cwpShowTransients()

Purpose:

  • Displays all current CWP transients (cache items) and their expiry times.
  • Only visible to users with manage_options capability (admins/webmasters).

Usage:

cwpShowTransients();

Security Note:

  • This function is for debugging and admin use only. It is not visible to regular users.
  • The code does not reveal or hint at any sensitive or private transients.