Plugin Directory

Changeset 3383047


Ignore:
Timestamp:
10/23/2025 04:46:42 AM (4 months ago)
Author:
stooit
Message:

Release 1.6.0

Location:
quant/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • quant/trunk/quant.php

    r3343846 r3383047  
    66 * Author: www.quantcdn.io
    77 * Plugin URI: https://www.quantcdn.io
    8  * Version: 1.5.2
     8 * Version: 1.6.0
    99 * License: GPL-2.0+
    1010 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
     
    3939    add_option(QUANT_SETTINGS_KEY, [
    4040        'enabled' => 0,
     41        'purge_on_save' => 1,
    4142        'api_endpoint' => 'https://api.quantcdn.io',
    4243        'webserver_url' => '',
  • quant/trunk/readme.txt

    r3343846 r3383047  
    55Requires at least: 4.6
    66Tested up to: 6.8.2
    7 Requires PHP: 8.1
    8 Stable tag: 1.5.2
     7Requires PHP: 7.4
     8Stable tag: 1.6.0
    99License: GPLv2 or later
    1010License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    6666== Changelog ==
    6767
     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
    6878= 1.5.2 =
    6979* Tested with WordPress 6.8.2.
     80* Updated minimum PHP requirement to 7.4 (previously stated 8.1).
    7081
    7182= 1.5.1 =
  • quant/trunk/src/Client.php

    r2888755 r3383047  
    172172    /**
    173173     * Purge the cache for a route in Quant.
     174     * Automatically purges both with and without trailing slash (except homepage).
    174175     *
    175176     * @param string $route
     177     * @return array Array with 'success' (bool), 'message' (string), and optional 'body' (string)
    176178     */
    177179    public function purge($route) {
    178180
    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;
    194247    }
    195248
  • quant/trunk/src/Settings.php

    r2993628 r3383047  
    3939         * General settings form fields.
    4040         */
    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', [
    4242            'name' => "{$key}[enabled]",
    43             'description' => 'Enable QuantCDN integration',
     43            'description' => 'Automatically push static content to Quant when content changes',
    4444            '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,
    4551        ]);
    4652
     
    195201    public static function sanitize($input)
    196202    {
    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       
    198209        return $input;
    199210    }
  • quant/trunk/src/SettingsScreen.php

    r2993628 r3383047  
    9595                <a href="?page=quant&tab=settings" class="nav-tab <?php echo $active_tab == 'settings' ? 'nav-tab-active' : ''; ?>">Settings</a>
    9696                <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>
    9798            </h2>
    9899
     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 { ?>
    99104            <form method="post" action="<?php echo esc_url( add_query_arg('tab', $active_tab, admin_url( 'options.php' )) ); ?>">
    100105
     
    119124                ?>
    120125            </form>
     126            <?php } ?>
    121127
    122128        </div><?php
    123129    }
     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&#10;/another/path&#10;/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    }
    124282}
  • quant/trunk/src/functions.php

    r2888755 r3383047  
    8585    function quant_save_post($id)
    8686    {
    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        }
    99109    }
    100110}
     
    135145    function quant_save_category($id)
    136146    {
     147        $options = quant_get_options();
    137148        $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        }
    139162    }
    140163}
     
    284307    function quant_init_hooks()
    285308    {
    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'])) {
    287313            return;
    288314        }
     
    321347
    322348}
     349
     350if (!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.