Changeset 3383047
- Timestamp:
- 10/23/2025 04:46:42 AM (4 months ago)
- Location:
- quant/trunk
- Files:
-
- 6 edited
-
quant.php (modified) (2 diffs)
-
readme.txt (modified) (2 diffs)
-
src/Client.php (modified) (1 diff)
-
src/Settings.php (modified) (2 diffs)
-
src/SettingsScreen.php (modified) (2 diffs)
-
src/functions.php (modified) (4 diffs)
Legend:
- Unmodified
- Added
- Removed
-
quant/trunk/quant.php
r3343846 r3383047 6 6 * Author: www.quantcdn.io 7 7 * Plugin URI: https://www.quantcdn.io 8 * Version: 1. 5.28 * Version: 1.6.0 9 9 * License: GPL-2.0+ 10 10 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt … … 39 39 add_option(QUANT_SETTINGS_KEY, [ 40 40 'enabled' => 0, 41 'purge_on_save' => 1, 41 42 'api_endpoint' => 'https://api.quantcdn.io', 42 43 'webserver_url' => '', -
quant/trunk/readme.txt
r3343846 r3383047 5 5 Requires at least: 4.6 6 6 Tested up to: 6.8.2 7 Requires PHP: 8.18 Stable tag: 1. 5.27 Requires PHP: 7.4 8 Stable tag: 1.6.0 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 66 66 == Changelog == 67 67 68 = 1.6.0 = 69 * Feature: Added new Cache tab for manual CDN cache purging (purge all or selective paths). 70 * Feature: Added "Cache purge on save" option to automatically purge CDN cache when content changes. 71 * Feature: Renamed "Quant Enabled" to "Automatic static push" for clarity. 72 * Feature: Automatic trailing slash handling - purges both /path and /path/ variants. 73 * Improvement: Enhanced error handling and validation for cache purge operations. 74 * Improvement: Cache purge now works independently of automatic static push. 75 * Tested with WordPress 6.8.2. 76 * Updated minimum PHP requirement to 7.4 (previously stated 8.1). 77 68 78 = 1.5.2 = 69 79 * Tested with WordPress 6.8.2. 80 * Updated minimum PHP requirement to 7.4 (previously stated 8.1). 70 81 71 82 = 1.5.1 = -
quant/trunk/src/Client.php
r2888755 r3383047 172 172 /** 173 173 * Purge the cache for a route in Quant. 174 * Automatically purges both with and without trailing slash (except homepage). 174 175 * 175 176 * @param string $route 177 * @return array Array with 'success' (bool), 'message' (string), and optional 'body' (string) 176 178 */ 177 179 public function purge($route) { 178 180 179 $args = [ 180 'headers' => $this->headers, 181 'timeout' => $this->httpRequestTimeout, 182 ]; 183 184 $args['headers']['Quant-Url'] = $route; 185 186 if ($this->disableTlsVerify) { 187 $args['sslverify'] = FALSE; 188 } 189 190 $response = wp_remote_post($this->endpoint . '/purge', $args); 191 $body = wp_remote_retrieve_body($response); 192 193 return $body; 181 $routes_to_purge = [$route]; 182 183 // For non-homepage routes, also purge the alternate trailing slash variant 184 if (strlen($route) > 1) { 185 if (substr($route, -1) === '/') { 186 // Has trailing slash, also purge without 187 $routes_to_purge[] = rtrim($route, '/'); 188 } else { 189 // No trailing slash, also purge with 190 $routes_to_purge[] = $route . '/'; 191 } 192 } 193 194 $last_result = null; 195 196 foreach ($routes_to_purge as $purge_route) { 197 $args = [ 198 'headers' => $this->headers, 199 'timeout' => $this->httpRequestTimeout, 200 ]; 201 202 $args['headers']['Quant-Url'] = $purge_route; 203 204 if ($this->disableTlsVerify) { 205 $args['sslverify'] = FALSE; 206 } 207 208 $response = wp_remote_post($this->endpoint . '/purge', $args); 209 210 // Check for WordPress HTTP errors 211 if (is_wp_error($response)) { 212 $error_message = $response->get_error_message(); 213 return [ 214 'success' => false, 215 'message' => "HTTP Error: {$error_message}", 216 ]; 217 } 218 219 $status_code = wp_remote_retrieve_response_code($response); 220 $body = wp_remote_retrieve_body($response); 221 222 // Check for non-200 status codes 223 if ($status_code < 200 || $status_code >= 300) { 224 $error_msg = "API returned status {$status_code}"; 225 if (!empty($body)) { 226 $decoded = json_decode($body, true); 227 if (isset($decoded['error'])) { 228 $error_msg .= ": " . $decoded['error']; 229 } else if (isset($decoded['message'])) { 230 $error_msg .= ": " . $decoded['message']; 231 } 232 } 233 return [ 234 'success' => false, 235 'message' => $error_msg, 236 ]; 237 } 238 239 $last_result = [ 240 'success' => true, 241 'message' => 'Cache purged successfully', 242 'body' => $body, 243 ]; 244 } 245 246 return $last_result; 194 247 } 195 248 -
quant/trunk/src/Settings.php
r2993628 r3383047 39 39 * General settings form fields. 40 40 */ 41 add_settings_field('quant_enabled', ' Quant Enabled', ['Quant\Field', 'checkbox'], $key, 'general', [41 add_settings_field('quant_enabled', 'Automatic static push', ['Quant\Field', 'checkbox'], $key, 'general', [ 42 42 'name' => "{$key}[enabled]", 43 'description' => ' Enable QuantCDN integration',43 'description' => 'Automatically push static content to Quant when content changes', 44 44 'value' => $options['enabled'] ?? 0, 45 ]); 46 47 add_settings_field('quant_purge_on_save', 'Cache purge on save', ['Quant\Field', 'checkbox'], $key, 'general', [ 48 'name' => "{$key}[purge_on_save]", 49 'description' => 'Automatically purge CDN cache when content changes<br><small><em>Note: This is automatically enabled when "Automatic static push" is checked.</em></small>', 50 'value' => $options['purge_on_save'] ?? 1, 45 51 ]); 46 52 … … 195 201 public static function sanitize($input) 196 202 { 197 // @todo: Sanitization 203 // If automatic static push is enabled, ensure cache purge is also enabled 204 // since pushing content inherently purges the cache 205 if (!empty($input['enabled'])) { 206 $input['purge_on_save'] = 1; 207 } 208 198 209 return $input; 199 210 } -
quant/trunk/src/SettingsScreen.php
r2993628 r3383047 95 95 <a href="?page=quant&tab=settings" class="nav-tab <?php echo $active_tab == 'settings' ? 'nav-tab-active' : ''; ?>">Settings</a> 96 96 <a href="?page=quant&tab=cron" class="nav-tab <?php echo $active_tab == 'cron' ? 'nav-tab-active' : ''; ?>">Cron</a> 97 <a href="?page=quant&tab=cache" class="nav-tab <?php echo $active_tab == 'cache' ? 'nav-tab-active' : ''; ?>">Cache</a> 97 98 </h2> 98 99 100 <?php if( $active_tab == 'cache' ) { ?> 101 <!-- Cache tab doesn't use a form, it has custom actions --> 102 <?php self::renderCacheTab(); ?> 103 <?php } else { ?> 99 104 <form method="post" action="<?php echo esc_url( add_query_arg('tab', $active_tab, admin_url( 'options.php' )) ); ?>"> 100 105 … … 119 124 ?> 120 125 </form> 126 <?php } ?> 121 127 122 128 </div><?php 123 129 } 130 131 /** 132 * Render the Cache management tab 133 * 134 * @return void 135 */ 136 public static function renderCacheTab() 137 { 138 ?> 139 <div class="quant-cache-management"> 140 <style> 141 .quant-cache-card { 142 background: #fff; 143 border: 1px solid #ccd0d4; 144 box-shadow: 0 1px 1px rgba(0,0,0,.04); 145 margin: 20px 0; 146 padding: 20px; 147 max-width: 800px; 148 } 149 .quant-cache-card h3 { 150 margin-top: 0; 151 } 152 .quant-cache-card p { 153 color: #646970; 154 } 155 .quant-purge-paths { 156 width: 100%; 157 min-height: 150px; 158 font-family: monospace; 159 } 160 .quant-cache-response { 161 margin-top: 15px; 162 padding: 10px; 163 display: none; 164 } 165 .quant-cache-response.success { 166 display: block; 167 background: #d7f0d7; 168 border-left: 4px solid #46b450; 169 color: #000; 170 } 171 .quant-cache-response.error { 172 display: block; 173 background: #f8d7da; 174 border-left: 4px solid #dc3545; 175 color: #721c24; 176 } 177 .quant-button-large { 178 height: 40px; 179 font-size: 14px; 180 } 181 </style> 182 183 <div class="quant-cache-card"> 184 <h3>Purge All Cache</h3> 185 <p>This will purge the entire CDN cache for your site by purging "/*".</p> 186 <button type="button" id="quant-purge-all" class="button button-primary button-hero quant-button-large"> 187 Purge All Cache 188 </button> 189 <div id="quant-purge-all-response" class="quant-cache-response"></div> 190 </div> 191 192 <div class="quant-cache-card"> 193 <h3>Purge Selective Paths</h3> 194 <p>Enter specific paths to purge from the CDN cache (one per line):</p> 195 <textarea id="quant-purge-paths" class="quant-purge-paths" placeholder="/path/to/page /another/path /blog/*"></textarea> 196 <p><em>Examples: /about, /blog/*, /wp-content/themes/mytheme/style.css</em></p> 197 <button type="button" id="quant-purge-selective" class="button button-primary button-large quant-button-large"> 198 Purge Selected Paths 199 </button> 200 <div id="quant-purge-selective-response" class="quant-cache-response"></div> 201 </div> 202 203 <script> 204 jQuery(document).ready(function($) { 205 // Purge all cache 206 $('#quant-purge-all').on('click', function() { 207 var button = $(this); 208 var responseDiv = $('#quant-purge-all-response'); 209 210 button.prop('disabled', true).text('Purging...'); 211 responseDiv.removeClass('success error').hide(); 212 213 $.ajax({ 214 url: ajaxurl, 215 type: 'POST', 216 data: { 217 action: 'quant_purge_cache', 218 nonce: '<?php echo wp_create_nonce('quant_purge_cache'); ?>', 219 paths: ['/*'] 220 }, 221 success: function(response) { 222 if (response.success) { 223 responseDiv.addClass('success').text('✓ Successfully purged all cache').show(); 224 } else { 225 responseDiv.addClass('error').text('✗ Error: ' + (response.data || 'Unknown error')).show(); 226 } 227 button.prop('disabled', false).text('Purge All Cache'); 228 }, 229 error: function(xhr, status, error) { 230 responseDiv.addClass('error').text('✗ Request failed: ' + error).show(); 231 button.prop('disabled', false).text('Purge All Cache'); 232 } 233 }); 234 }); 235 236 // Purge selective paths 237 $('#quant-purge-selective').on('click', function() { 238 var button = $(this); 239 var responseDiv = $('#quant-purge-selective-response'); 240 var pathsTextarea = $('#quant-purge-paths'); 241 var paths = pathsTextarea.val().split('\n').map(function(p) { 242 return p.trim(); 243 }).filter(function(p) { 244 return p.length > 0; 245 }); 246 247 if (paths.length === 0) { 248 responseDiv.addClass('error').text('✗ Please enter at least one path').show(); 249 return; 250 } 251 252 button.prop('disabled', true).text('Purging...'); 253 responseDiv.removeClass('success error').hide(); 254 255 $.ajax({ 256 url: ajaxurl, 257 type: 'POST', 258 data: { 259 action: 'quant_purge_cache', 260 nonce: '<?php echo wp_create_nonce('quant_purge_cache'); ?>', 261 paths: paths 262 }, 263 success: function(response) { 264 if (response.success) { 265 responseDiv.addClass('success').text('✓ Successfully purged ' + paths.length + ' path(s)').show(); 266 } else { 267 responseDiv.addClass('error').text('✗ Error: ' + (response.data || 'Unknown error')).show(); 268 } 269 button.prop('disabled', false).text('Purge Selected Paths'); 270 }, 271 error: function(xhr, status, error) { 272 responseDiv.addClass('error').text('✗ Request failed: ' + error).show(); 273 button.prop('disabled', false).text('Purge Selected Paths'); 274 } 275 }); 276 }); 277 }); 278 </script> 279 </div> 280 <?php 281 } 124 282 } -
quant/trunk/src/functions.php
r2888755 r3383047 85 85 function quant_save_post($id) 86 86 { 87 if (!quant_is_enabled()) { 88 return; 89 } 90 91 // @todo: Support draft/scheduled posts 92 if (get_post_status($id) !== 'publish') { 93 quant_unpublish_post($id); 94 return; 95 } 96 97 $client = new Client(); 98 $client->sendPost($id); 87 $options = quant_get_options(); 88 89 // If automatic push is enabled, send the full content 90 if (quant_is_enabled()) { 91 // @todo: Support draft/scheduled posts 92 if (get_post_status($id) !== 'publish') { 93 quant_unpublish_post($id); 94 return; 95 } 96 97 $client = new Client(); 98 $client->sendPost($id); 99 return; 100 } 101 102 // If automatic push is disabled but cache purge is enabled, just purge 103 if (!empty($options['purge_on_save'])) { 104 $client = new Client(); 105 $permalink = wp_make_link_relative(get_permalink($id)); 106 // Client::purge() automatically handles both with/without trailing slash 107 $client->purge($permalink); 108 } 99 109 } 100 110 } … … 135 145 function quant_save_category($id) 136 146 { 147 $options = quant_get_options(); 137 148 $client = new Client(); 138 $client->sendCategory($id); 149 150 // If automatic push is enabled, send the full content 151 if (quant_is_enabled()) { 152 $client->sendCategory($id); 153 return; 154 } 155 156 // If automatic push is disabled but cache purge is enabled, just purge 157 if (!empty($options['purge_on_save'])) { 158 $permalink = wp_make_link_relative(get_term_link($id)); 159 // Client::purge() automatically handles both with/without trailing slash 160 $client->purge($permalink); 161 } 139 162 } 140 163 } … … 284 307 function quant_init_hooks() 285 308 { 286 if (!quant_is_enabled()) { 309 $options = quant_get_options(); 310 311 // Only register hooks if either automatic push or cache purge is enabled 312 if (!quant_is_enabled() && empty($options['purge_on_save'])) { 287 313 return; 288 314 } … … 321 347 322 348 } 349 350 if (!function_exists('quant_purge_cache_ajax')) { 351 /** 352 * AJAX handler for cache purging 353 * 354 * @return void 355 */ 356 function quant_purge_cache_ajax() 357 { 358 // Verify nonce 359 if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'quant_purge_cache')) { 360 wp_send_json_error('Invalid security token'); 361 return; 362 } 363 364 // Check user permissions 365 if (!current_user_can('manage_options')) { 366 wp_send_json_error('Insufficient permissions'); 367 return; 368 } 369 370 // Get paths to purge 371 $paths = isset($_POST['paths']) ? $_POST['paths'] : []; 372 373 if (empty($paths) || !is_array($paths)) { 374 wp_send_json_error('No paths provided'); 375 return; 376 } 377 378 $client = new Client(); 379 $results = []; 380 $errors = []; 381 382 foreach ($paths as $path) { 383 $path = trim($path); 384 if (empty($path)) { 385 continue; 386 } 387 388 // Ensure path starts with / 389 if (substr($path, 0, 1) !== '/') { 390 $path = '/' . $path; 391 } 392 393 $purge_result = $client->purge($path); 394 395 if (!empty($purge_result['success'])) { 396 $results[] = $path; 397 } else { 398 $error_message = isset($purge_result['message']) ? $purge_result['message'] : 'Unknown error'; 399 $errors[] = "{$path}: {$error_message}"; 400 } 401 } 402 403 if (!empty($errors)) { 404 $error_msg = 'Failed to purge some paths: ' . implode('; ', $errors); 405 wp_send_json_error($error_msg); 406 } else if (empty($results)) { 407 wp_send_json_error('No valid paths were processed'); 408 } else { 409 wp_send_json_success([ 410 'message' => 'Successfully purged ' . count($results) . ' path(s)', 411 'paths' => $results 412 ]); 413 } 414 } 415 416 // Register AJAX handlers 417 add_action('wp_ajax_quant_purge_cache', 'quant_purge_cache_ajax'); 418 }
Note: See TracChangeset
for help on using the changeset viewer.