From 36fe6e9aedb17e185528f4c4a63324c217b5eda3 Mon Sep 17 00:00:00 2001 From: Ancocodet Date: Thu, 3 Feb 2022 21:02:01 +0100 Subject: [PATCH 01/16] add HDD cache expiration cron (#255) Introduce a WP cron task to clear cached pages after expiry. The option for changing the expiration time is re-enabled when HDD is selected. On the settings page a small information is added which informs the user that an system cron should be used. --- inc/cachify.settings.php | 9 ++---- inc/class-cachify.php | 69 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/inc/cachify.settings.php b/inc/cachify.settings.php index dfe075c7..9f807e32 100644 --- a/inc/cachify.settings.php +++ b/inc/cachify.settings.php @@ -30,13 +30,10 @@ + + - - -

- - - +

diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 03b419ab..208dc87b 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -132,6 +132,30 @@ public function __construct() { 2 ); + /* Add Cron for clearing the HDD Cache */ + if ( self::METHOD_HDD === self::$options['use_apc'] ) { + add_filter( + 'cron_schedules', + array( + __CLASS__, + 'add_cron_cache_expiration', + ) + ); + + $timestamp = wp_next_scheduled( 'hdd_cache_cron' ); + if ( false === $timestamp ) { + wp_schedule_event( time(), 'cachify_cache_expire', 'hdd_cache_cron' ); + } + + add_action( + 'hdd_cache_cron', + array( + __CLASS__, + 'run_hdd_cache_cron', + ) + ); + } + /* Backend */ if ( is_admin() ) { add_action( @@ -270,6 +294,14 @@ public function __construct() { * @change 2.1.0 */ public static function on_deactivation() { + /* Remove hdd cache cron when hdd is selected */ + if ( self::METHOD_HDD === self::$options['use_apc'] ) { + $timestamp = wp_next_scheduled( 'hdd_cache_cron' ); + if ( false !== $timestamp ) { + wp_unschedule_event( $timestamp, 'hdd_cache_cron' ); + } + } + self::flush_total_cache( true ); } @@ -500,6 +532,32 @@ public static function robots_txt() { } } + /** + * HDD Cache expiration cron action. + * + * @since 2.4 + */ + public static function run_hdd_cache_cron() { + Cachify_HDD::clear_cache(); + } + + /** + * Add cache expiration cron schedule. + * + * @param array $schedules Array of previously added non-default schedules. + * + * @return array Array of non-default schedules with our tasks added. + * + * @since 2.4 + */ + public static function add_cron_cache_expiration( $schedules ) { + $schedules['cachify_cache_expire'] = array( + 'interval' => self::$options['cache_expires'] * 3600, + 'display' => esc_html__( 'Cachify expire', 'cachify' ), + ); + return $schedules; + } + /** * Add the action links * @@ -755,6 +813,16 @@ public static function process_flush_request( $data ) { ); } } + + /* Reschedule HDD Cache Cron */ + if ( self::METHOD_HDD === self::$options['use_apc'] ) { + $timestamp = wp_next_scheduled( 'hdd_cache_cron' ); + if ( false !== $timestamp ) { + wp_reschedule_event( $timestamp, 'cachify_cache_expire', 'hdd_cache_cron' ); + wp_unschedule_event( $timestamp, 'hdd_cache_cron' ); + } + } + if ( ! is_admin() ) { wp_safe_redirect( remove_query_arg( @@ -1666,4 +1734,5 @@ private static function _get_tabs( $options ) { return $tabs; } + } From c7da072704c6fb5b60640f45553abcc545cb22da Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Thu, 3 Feb 2022 21:07:40 +0100 Subject: [PATCH 02/16] specify allow-plugins in Composer configuration We use third party plugins to install PHPCS rulesets. Explicitly allow them to run which is recommended as of Composer 2.2 and will be required in future releases. --- composer.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/composer.json b/composer.json index 0e60b098..befade4c 100644 --- a/composer.json +++ b/composer.json @@ -58,5 +58,11 @@ "lint-php": [ "phpcs --standard=phpcs.xml -s" ] + }, + "config": { + "allow-plugins": { + "dealerdirect/phpcodesniffer-composer-installer": true, + "composer/installers": true + } } } From dd90375b719cb41cb4ac948964892def1eb824b3 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Fri, 4 Feb 2022 18:15:44 +0100 Subject: [PATCH 03/16] use one-line notation for add_action calls (#260) The initialization routines got pretty long and unhandy to read with a mixture of add_* blocks and conditionals. Re-format the code to use one-line notations which do not exceed 96 characters (effectively 102 with tab-size 4) each and compress the class by a total of 176 lines. --- inc/class-cachify.php | 237 ++++++------------------------------------ 1 file changed, 30 insertions(+), 207 deletions(-) diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 208dc87b..dfacecc4 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -83,208 +83,66 @@ public function __construct() { self::$is_nginx = $GLOBALS['is_nginx']; /* Publish hooks */ - add_action( - 'init', - array( - __CLASS__, - 'register_publish_hooks', - ), - 99 - ); + add_action( 'init', array( __CLASS__, 'register_publish_hooks' ), 99 ); /* Flush Hooks */ add_action( 'init', array( __CLASS__, 'register_flush_cache_hooks' ), 10, 0 ); - add_action( - 'cachify_remove_post_cache', - array( - __CLASS__, - 'remove_page_cache_by_post_id', - ) - ); + add_action( 'cachify_remove_post_cache', array( __CLASS__, 'remove_page_cache_by_post_id' ) ); /* Flush icon */ - add_action( - 'admin_bar_menu', - array( - __CLASS__, - 'add_flush_icon', - ), - 90 - ); + add_action( 'admin_bar_menu', array( __CLASS__, 'add_flush_icon' ), 90 ); - add_action( - 'init', - array( - __CLASS__, - 'process_flush_request', - ) - ); + add_action( 'init', array( __CLASS__, 'process_flush_request' ) ); /* Flush (post) cache if comment is made from frontend or backend */ - add_action( - 'pre_comment_approved', - array( - __CLASS__, - 'pre_comment', - ), - 99, - 2 - ); + add_action( 'pre_comment_approved', array( __CLASS__, 'pre_comment' ), 99, 2 ); /* Add Cron for clearing the HDD Cache */ if ( self::METHOD_HDD === self::$options['use_apc'] ) { - add_filter( - 'cron_schedules', - array( - __CLASS__, - 'add_cron_cache_expiration', - ) - ); + add_filter( 'cron_schedules', array( __CLASS__, 'add_cron_cache_expiration' ) ); $timestamp = wp_next_scheduled( 'hdd_cache_cron' ); if ( false === $timestamp ) { wp_schedule_event( time(), 'cachify_cache_expire', 'hdd_cache_cron' ); } - add_action( - 'hdd_cache_cron', - array( - __CLASS__, - 'run_hdd_cache_cron', - ) - ); + add_action( 'hdd_cache_cron', array( __CLASS__, 'run_hdd_cache_cron' ) ); } - /* Backend */ if ( is_admin() ) { - add_action( - 'wpmu_new_blog', - array( - __CLASS__, - 'install_later', - ) - ); + /* Backend */ + add_action( 'wpmu_new_blog', array( __CLASS__, 'install_later' ) ); - add_action( - 'delete_blog', - array( - __CLASS__, - 'uninstall_later', - ) - ); + add_action( 'delete_blog', array( __CLASS__, 'uninstall_later' ) ); - add_action( - 'admin_init', - array( - __CLASS__, - 'register_textdomain', - ) - ); + add_action( 'admin_init', array( __CLASS__, 'register_textdomain' ) ); - add_action( - 'admin_init', - array( - __CLASS__, - 'register_settings', - ) - ); + add_action( 'admin_init', array( __CLASS__, 'register_settings' ) ); - add_action( - 'admin_menu', - array( - __CLASS__, - 'add_page', - ) - ); + add_action( 'admin_menu', array( __CLASS__, 'add_page' ) ); - add_action( - 'admin_enqueue_scripts', - array( - __CLASS__, - 'add_admin_resources', - ) - ); + add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_admin_resources' ) ); - add_action( - 'admin_head', - array( - __CLASS__, - 'admin_dashboard_styles', - ) - ); + add_action( 'admin_head', array( __CLASS__, 'admin_dashboard_styles' ) ); - add_action( - 'doing_dark_mode', - array( - __CLASS__, - 'admin_dashboard_dark_mode_styles', - ) - ); + add_action( 'doing_dark_mode', array( __CLASS__, 'admin_dashboard_dark_mode_styles' ) ); - add_action( - 'transition_comment_status', - array( - __CLASS__, - 'touch_comment', - ), - 10, - 3 - ); + add_action( 'transition_comment_status', array( __CLASS__, 'touch_comment' ), 10, 3 ); - add_action( - 'edit_comment', - array( - __CLASS__, - 'edit_comment', - ) - ); + add_action( 'edit_comment', array( __CLASS__, 'edit_comment' ) ); - add_filter( - 'dashboard_glance_items', - array( - __CLASS__, - 'add_dashboard_count', - ) - ); + add_filter( 'dashboard_glance_items', array( __CLASS__, 'add_dashboard_count' ) ); - add_filter( - 'plugin_row_meta', - array( - __CLASS__, - 'row_meta', - ), - 10, - 2 - ); + add_filter( 'plugin_row_meta', array( __CLASS__, 'row_meta' ), 10, 2 ); - add_filter( - 'plugin_action_links_' . CACHIFY_BASE, - array( - __CLASS__, - 'action_links', - ) - ); + add_filter( 'plugin_action_links_' . CACHIFY_BASE, array( __CLASS__, 'action_links' ) ); - /* Frontend */ } else { - add_action( - 'template_redirect', - array( - __CLASS__, - 'manage_cache', - ), - 0 - ); - - add_action( - 'do_robots', - array( - __CLASS__, - 'robots_txt', - ) - ); - }// End if(). + /* Frontend */ + add_action( 'template_redirect', array( __CLASS__, 'manage_cache' ), 0 ); + add_action( 'do_robots', array( __CLASS__, 'robots_txt' ) ); + } } /** @@ -791,26 +649,14 @@ public static function process_flush_request( $data ) { /* Notice */ if ( is_admin() ) { - add_action( - 'network_admin_notices', - array( - __CLASS__, - 'flush_notice', - ) - ); + add_action( 'network_admin_notices', array( __CLASS__, 'flush_notice' ) ); } } else { self::flush_total_cache(); /* Notice */ if ( is_admin() ) { - add_action( - 'admin_notices', - array( - __CLASS__, - 'flush_notice', - ) - ); + add_action( 'admin_notices', array( __CLASS__, 'flush_notice' ) ); } } @@ -939,22 +785,8 @@ public static function register_publish_hooks() { /* Loop the post types */ foreach ( $post_types as $post_type ) { - add_action( - 'publish_' . $post_type, - array( - __CLASS__, - 'publish_post_types', - ), - 10, - 2 - ); - add_action( - 'publish_future_' . $post_type, - array( - __CLASS__, - 'flush_total_cache', - ) - ); + add_action( 'publish_' . $post_type, array( __CLASS__, 'publish_post_types' ), 10, 2 ); + add_action( 'publish_future_' . $post_type, array( __CLASS__, 'flush_total_cache' ) ); } } @@ -1171,15 +1003,7 @@ public static function register_flush_cache_hooks() { /* Loop all hooks and register actions */ foreach ( $flush_cache_hooks as $hook => $priority ) { - add_action( - $hook, - array( - 'Cachify', - 'flush_total_cache', - ), - $priority, - 0 - ); + add_action( $hook, array( 'Cachify', 'flush_total_cache' ), $priority, 0 ); } } @@ -1734,5 +1558,4 @@ private static function _get_tabs( $options ) { return $tabs; } - } From 4457792320e02792512e512270663cea832f84f0 Mon Sep 17 00:00:00 2001 From: Angelo Cali <72382138+angelocali@users.noreply.github.com> Date: Mon, 7 Feb 2022 09:39:56 +0100 Subject: [PATCH 04/16] Do not flush cache for post revisions (#261) * Do not flush cache on deleted/updated post revisions * move did_action call into if condition --- inc/class-cachify.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/inc/class-cachify.php b/inc/class-cachify.php index dfacecc4..0816d439 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -1159,10 +1159,16 @@ private static function _minify_cache( $data ) { * * @since 0.1 * @change 2.0 + * @change 2.4.0 Do not flush cache for post revisions. * * @param bool $clear_all_methods Flush all caching methods (default: FALSE). */ public static function flush_total_cache( $clear_all_methods = false ) { + // We do not need to flush the cache for saved post revisions. + if ( did_action( 'save_post_revision' ) ) { + return; + } + if ( $clear_all_methods ) { /* DB */ Cachify_DB::clear_cache(); From 2abed98e1029729ab55a1d5e8b5723176213070c Mon Sep 17 00:00:00 2001 From: Angelo Cali <72382138+angelocali@users.noreply.github.com> Date: Tue, 8 Feb 2022 14:21:52 +0100 Subject: [PATCH 05/16] Inform user on cache clear in admin bar (#257) --- .eslintrc.json | 21 +++++ composer.json | 12 ++- css/admin-bar-flush.css | 51 ++++++++++ inc/class-cachify.php | 189 +++++++++++++++++++++++++++++++++++--- js/admin-bar-flush.js | 83 +++++++++++++++++ js/admin-bar-flush.min.js | 6 ++ package.json | 2 + 7 files changed, 350 insertions(+), 14 deletions(-) create mode 100644 .eslintrc.json create mode 100644 css/admin-bar-flush.css create mode 100644 js/admin-bar-flush.js create mode 100644 js/admin-bar-flush.min.js diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 00000000..782125e7 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,21 @@ +{ + "extends": "plugin:@wordpress/eslint-plugin/es5", + "env": { + "browser": true, + "jquery": true + }, + "globals": { + "Raphael": "readonly", + "getAnchors": "readonly" + }, + "rules": { + "camelcase": 0, + "eqeqeq": 0, + "no-mixed-operators": 0, + "no-redeclare": 0, + "no-shadow": 0, + "no-unused-expressions": 0, + "no-unused-vars": 0, + "vars-on-top": 0 + } +} diff --git a/composer.json b/composer.json index befade4c..b93a9125 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,9 @@ "@build" ], "build": [ - "minifycss css/dashboard.css > css/dashboard.min.css" + "minifycss css/dashboard.css > css/dashboard.min.css", + "minifycss css/admin-bar-flush.css > css/admin-bar-flush.min.css", + "minifyjs js/admin-bar-flush.js > js/admin-bar-flush.min.js" ], "cs": [ "@lint-php" @@ -50,10 +52,14 @@ ], "lint-all": [ "@lint-php", - "@lint-css" + "@lint-css", + "@lint-js" ], "lint-css": [ - "npx stylelint css/dashboard.css" + "npx stylelint css/dashboard.css css/admin-bar-flush.css" + ], + "lint-js": [ + "npx eslint js/admin-bar-flush.js" ], "lint-php": [ "phpcs --standard=phpcs.xml -s" diff --git a/css/admin-bar-flush.css b/css/admin-bar-flush.css new file mode 100644 index 00000000..6f798080 --- /dev/null +++ b/css/admin-bar-flush.css @@ -0,0 +1,51 @@ +#wp-admin-bar-cachify .animate-pulse { + animation: cachify-dash-icon-pulse 2s infinite; + animation-timing-function: linear; +} + +#wp-admin-bar-cachify .animate-fade { + animation: cachify-dash-icon-fade-in 0.1s; + animation-timing-function: linear; +} + +@keyframes cachify-dash-icon-pulse { + + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: 0.2; + } +} + +@keyframes cachify-dash-icon-fade-in { + + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +#wp-admin-bar-cachify button.ab-item { + background: none; + border: none; + padding: 0 8px 0 7px; +} + +#wp-admin-bar-cachify button.ab-item:hover { + cursor: pointer; +} + +#wp-admin-bar-cachify button.ab-item:focus { + outline: none; +} + +#wpadminbar #wp-admin-bar-cachify button.ab-item:focus span.ab-label { + color: inherit; +} + diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 0816d439..f53c4df6 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -58,6 +58,14 @@ final class Cachify { const MINIFY_HTML_ONLY = 1; const MINIFY_HTML_JS = 2; + /** + * REST endpoints + * + * @var string + */ + const REST_NAMESPACE = 'cachify/v1'; + const REST_ROUTE_FLUSH = 'flush'; + /** * Pseudo constructor * @@ -90,9 +98,21 @@ public function __construct() { add_action( 'cachify_remove_post_cache', array( __CLASS__, 'remove_page_cache_by_post_id' ) ); + /* Register scripts */ + add_action( 'init', array( __CLASS__, 'register_scripts' ) ); + + /* Register styles */ + add_action( 'init', array( __CLASS__, 'register_styles' ) ); + /* Flush icon */ add_action( 'admin_bar_menu', array( __CLASS__, 'add_flush_icon' ), 90 ); + /* Flush icon script */ + add_action( 'admin_bar_menu', array( __CLASS__, 'add_flush_icon_script' ), 90 ); + + /* Flush REST endpoint */ + add_action( 'rest_api_init', array( __CLASS__, 'add_flush_rest_endpoint' ) ); + add_action( 'init', array( __CLASS__, 'process_flush_request' ) ); /* Flush (post) cache if comment is made from frontend or backend */ @@ -313,6 +333,45 @@ private static function _get_blog_ids() { return $wpdb->get_col( "SELECT blog_id FROM `$wpdb->blogs`" ); } + /** + * Register the styles + * + * @since 2.4.0 + */ + public static function register_styles() { + /* Register dashboard CSS */ + wp_register_style( + 'cachify-dashboard', + plugins_url( 'css/dashboard.min.css', CACHIFY_FILE ), + array(), + filemtime( plugin_dir_path( CACHIFY_FILE ) . 'css/dashboard.min.css' ) + ); + + /* Register admin bar flush CSS */ + wp_register_style( + 'cachify-admin-bar-flush', + plugins_url( 'css/admin-bar-flush.min.css', CACHIFY_FILE ), + array(), + filemtime( plugin_dir_path( CACHIFY_FILE ) . 'css/admin-bar-flush.min.css' ) + ); + } + + /** + * Register the scripts + * + * @since 2.4.0 + */ + public static function register_scripts() { + /* Register admin bar flush script */ + wp_register_script( + 'cachify-admin-bar-flush', + plugins_url( 'js/admin-bar-flush.min.js', CACHIFY_FILE ), + array(), + filemtime( plugin_dir_path( CACHIFY_FILE ) . 'js/admin-bar-flush.min.js' ), + true + ); + } + /** * Register the language file * @@ -565,6 +624,7 @@ public static function get_cache_size() { * * @since 1.2 * @change 2.2.2 + * @change 2.4.0 Adjust icon for flush request via AJAX * * @hook mixed cachify_user_can_flush_cache * @@ -576,8 +636,19 @@ public static function add_flush_icon( $wp_admin_bar ) { return; } + /* Enqueue style */ + wp_enqueue_style( 'cachify-admin-bar-flush' ); + /* Display the admin icon anytime */ - echo ''; + echo ''; + + /* Print area for aria live updates */ + echo ''; + /* Check if the flush action was used without AJAX */ + $dashicon_class = 'dashicons-trash'; + if ( isset( $_GET['_cachify'] ) && 'flushed' === $_GET['_cachify'] ) { + $dashicon_class = self::get_dashicon_success_class(); + } /* Add menu item */ $wp_admin_bar->add_menu( @@ -585,7 +656,7 @@ public static function add_flush_icon( $wp_admin_bar ) { 'id' => 'cachify', 'href' => wp_nonce_url( add_query_arg( '_cachify', 'flush' ), '_cachify__flush_nonce' ), // esc_url in /wp-includes/class-wp-admin-bar.php#L438. 'parent' => 'top-secondary', - 'title' => '' . + 'title' => '' . '' . __( 'Flush site cache', @@ -599,11 +670,95 @@ public static function add_flush_icon( $wp_admin_bar ) { ); } + /** + * Returns the dashicon class for the success state in admin bar flush button + * + * @since 2.4.0 + * + * @return string + */ + public static function get_dashicon_success_class() { + global $wp_version; + if ( version_compare( $wp_version, '5.2', '<' ) ) { + return 'dashicons-yes'; + } + + return 'dashicons-yes-alt'; + } + + /** + * Add a script to query the REST endpoint and animate the flush icon in admin bar menu + * + * @since 2.4.0 + * + * @hook mixed cachify_user_can_flush_cache ? + * + * @param object $wp_admin_bar Object of menu items. + */ + public static function add_flush_icon_script( $wp_admin_bar ) { + /* Quit */ + if ( ! is_admin_bar_showing() || ! apply_filters( 'cachify_user_can_flush_cache', current_user_can( 'manage_options' ) ) ) { + return; + } + + /* Enqueue script */ + wp_enqueue_script( 'cachify-admin-bar-flush' ); + + /* Localize script */ + wp_localize_script( + 'cachify-admin-bar-flush', + 'cachify_admin_bar_flush_ajax_object', + array( + 'url' => esc_url_raw( rest_url( self::REST_NAMESPACE . '/' . self::REST_ROUTE_FLUSH ) ), + 'nonce' => wp_create_nonce( 'wp_rest' ), + 'flushing' => __( 'Flushing cache', 'cachify' ), + 'flushed' => __( 'Cache flushed successfully', 'cachify' ), + 'dashicon_success' => self::get_dashicon_success_class(), + ) + ); + } + + + /** + * Registers an REST endpoint for the flush operation + * + * @change 2.4.0 + */ + public static function add_flush_rest_endpoint() { + register_rest_route( + self::REST_NAMESPACE, + self::REST_ROUTE_FLUSH, + array( + 'methods' => WP_REST_Server::DELETABLE, + 'callback' => array( + __CLASS__, + 'flush_cache', + ), + 'permission_callback' => array( + __CLASS__, + 'user_can_manage_options', + ), + ) + ); + } + + /** + * Check if user can manage options + * + * @since 2.4.0 + * + * @return bool + */ + public static function user_can_manage_options() { + return current_user_can( 'manage_options' ); + } + /** * Process plugin's meta actions * * @since 0.5 * @change 2.2.2 + * @change 2.4.0 Extract cache flushing to own method and always redirect to referer with new value for `_cachify` param. * * @hook mixed cachify_user_can_flush_cache * @@ -630,6 +785,26 @@ public static function process_flush_request( $data ) { require_once( ABSPATH . 'wp-admin/includes/plugin.php' ); } + /* Flush cache */ + self::flush_cache(); + + wp_safe_redirect( + add_query_arg( + '_cachify', + 'flushed', + wp_get_referer() + ) + ); + + exit(); + } + + /** + * Flush cache + * + * @since 2.4.0 + */ + public static function flush_cache() { /* Flush cache */ if ( is_multisite() && is_network_admin() ) { /* Old blog */ @@ -1303,18 +1478,10 @@ public static function add_admin_resources( $hook ) { return; } - /* Plugin data */ - $plugin_data = get_plugin_data( CACHIFY_FILE ); - /* Register css */ switch ( $hook ) { case 'index.php': - wp_enqueue_style( - 'cachify-dashboard', - plugins_url( 'css/dashboard.min.css', CACHIFY_FILE ), - array(), - $plugin_data['Version'] - ); + wp_enqueue_style( 'cachify-dashboard' ); break; default: diff --git a/js/admin-bar-flush.js b/js/admin-bar-flush.js new file mode 100644 index 00000000..081b3708 --- /dev/null +++ b/js/admin-bar-flush.js @@ -0,0 +1,83 @@ +/* global cachify_admin_bar_flush_ajax_object */ +( function() { + var is_flushing = false, + admin_bar_cachify_list_item = document.getElementById( 'wp-admin-bar-cachify' ), + flush_link = admin_bar_cachify_list_item.querySelector( 'a.ab-item' ), + fallback_url = flush_link.getAttribute( 'href' ), + aria_live_area = document.querySelector( '.ab-aria-live-area' ); + + // Replacing flush link with button because with AJAX action, it is semantically not a link anymore. + var button = document.createRange().createContextualFragment( '' ); + flush_link.parentNode.replaceChild( button, flush_link ); + + var admin_bar_icon = admin_bar_cachify_list_item.querySelector( '#wp-admin-bar-cachify .ab-icon' ); + + document.querySelector( '#wp-admin-bar-cachify .ab-item' ).addEventListener( 'click', flush ); + + admin_bar_icon.addEventListener( 'animationend', function() { + admin_bar_icon.classList.remove( 'animate-fade' ); + } ); + + function flush_icon_remove_classes() { + var classes = [ + 'animate-fade', + 'animate-pulse', + 'dashicons-trash', + 'dashicons-yes', + 'dashicons-yes-alt', + 'dashicons-dismiss', + ]; + + for ( var i = 0; i < classes.length; i++ ) { + admin_bar_icon.classList.remove( classes[i] ); + } + } + + function start_flush_icon_reset_timeout() { + setTimeout( function() { + flush_icon_remove_classes(); + admin_bar_icon.classList.add( 'animate-fade' ); + admin_bar_icon.classList.add( 'dashicons-trash' ); + is_flushing = false; + aria_live_area.textContent = ''; + }, 2000 ); + } + + function flush( event ) { + event.preventDefault(); + + if ( is_flushing ) { + return; + } + is_flushing = true; + aria_live_area.textContent = cachify_admin_bar_flush_ajax_object.flushing; + + if ( admin_bar_icon !== null ) { + flush_icon_remove_classes(); + admin_bar_icon.classList.add( 'animate-pulse' ); + admin_bar_icon.classList.add( 'dashicons-trash' ); + } + + var request = new XMLHttpRequest(); + request.addEventListener( 'load', function() { + if ( this.status === 200 ) { + start_flush_icon_reset_timeout(); + flush_icon_remove_classes(); + admin_bar_icon.classList.add( 'animate-fade' ); + admin_bar_icon.classList.add( cachify_admin_bar_flush_ajax_object.dashicon_success ); + aria_live_area.textContent = cachify_admin_bar_flush_ajax_object.flushed; + return; + } + + window.location = fallback_url; + } ); + + request.addEventListener( 'error', function() { + window.location = fallback_url; + } ); + + request.open( 'DELETE', cachify_admin_bar_flush_ajax_object.url ); + request.setRequestHeader( 'X-WP-Nonce', cachify_admin_bar_flush_ajax_object.nonce ); + request.send(); + } +}() ); diff --git a/js/admin-bar-flush.min.js b/js/admin-bar-flush.min.js new file mode 100644 index 00000000..16d25798 --- /dev/null +++ b/js/admin-bar-flush.min.js @@ -0,0 +1,6 @@ +(function(){var is_flushing=!1,admin_bar_cachify_list_item=document.getElementById('wp-admin-bar-cachify'),flush_link=admin_bar_cachify_list_item.querySelector('a.ab-item'),fallback_url=flush_link.getAttribute('href'),aria_live_area=document.querySelector('.ab-aria-live-area');var button=document.createRange().createContextualFragment('');flush_link.parentNode.replaceChild(button,flush_link);var admin_bar_icon=admin_bar_cachify_list_item.querySelector('#wp-admin-bar-cachify .ab-icon');document.querySelector('#wp-admin-bar-cachify .ab-item').addEventListener('click',flush);admin_bar_icon.addEventListener('animationend',function(){admin_bar_icon.classList.remove('animate-fade')});function flush_icon_remove_classes(){var classes=['animate-fade','animate-pulse','dashicons-trash','dashicons-yes','dashicons-yes-alt','dashicons-dismiss',];for(var i=0;i Date: Thu, 10 Feb 2022 17:06:57 +0100 Subject: [PATCH 06/16] Move some inline styles in external CSS and use wp_add_inline_style for others --- css/admin-bar-flush.css | 16 ++++++++++++++++ inc/class-cachify.php | 7 ++----- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/css/admin-bar-flush.css b/css/admin-bar-flush.css index 6f798080..d1b0f024 100644 --- a/css/admin-bar-flush.css +++ b/css/admin-bar-flush.css @@ -49,3 +49,19 @@ color: inherit; } +#wp-admin-bar-cachify { + display: list-item !important; +} + +#wp-admin-bar-cachify .ab-icon { + margin: 0 !important; +} + +#wp-admin-bar-cachify .ab-icon::before { + top: 2px; + margin: 0; +} + +#wp-admin-bar-cachify .ab-label { + margin: 0 5px; +} diff --git a/inc/class-cachify.php b/inc/class-cachify.php index f53c4df6..712cf063 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -144,7 +144,7 @@ public function __construct() { add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_admin_resources' ) ); - add_action( 'admin_head', array( __CLASS__, 'admin_dashboard_styles' ) ); + add_action( 'admin_enqueue_scripts', array( __CLASS__, 'admin_dashboard_styles' ) ); add_action( 'doing_dark_mode', array( __CLASS__, 'admin_dashboard_dark_mode_styles' ) ); @@ -639,9 +639,6 @@ public static function add_flush_icon( $wp_admin_bar ) { /* Enqueue style */ wp_enqueue_style( 'cachify-admin-bar-flush' ); - /* Display the admin icon anytime */ - echo ''; - /* Print area for aria live updates */ echo ''; /* Check if the flush action was used without AJAX */ @@ -1499,7 +1496,7 @@ public static function admin_dashboard_styles() { $wp_version = get_bloginfo( 'version' ); if ( version_compare( $wp_version, '5.3', '<' ) ) { - echo ''; + wp_add_inline_style( 'cachify-dashboard', '#dashboard_right_now .cachify-icon use { fill: #82878c; }' ); } } From da7f2ef09b59cb16968055d018269131643b53da Mon Sep 17 00:00:00 2001 From: Florian Brinkmann Date: Thu, 10 Feb 2022 17:19:38 +0100 Subject: [PATCH 07/16] Change darkmode modification inline style --- inc/class-cachify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 712cf063..6f9d1745 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -1506,7 +1506,7 @@ public static function admin_dashboard_styles() { * @since 2.3.0 */ public static function admin_dashboard_dark_mode_styles() { - echo ''; + wp_add_inline_style( 'cachify-dashboard', '#dashboard_right_now .cachify-icon use { fill: #bbc8d4; }' ); } /** From 9ea110bfc39e677793884076b42b3a14f213da77 Mon Sep 17 00:00:00 2001 From: Angelo Cali <72382138+angelocali@users.noreply.github.com> Date: Tue, 26 Apr 2022 18:11:20 +0200 Subject: [PATCH 08/16] Add filter to disable gzip file creation (#262) --- inc/class-cachify-hdd.php | 27 +++++++++++++++++++++++++-- inc/setup/cachify.hdd.htaccess.php | 20 +++++++++++++------- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/inc/class-cachify-hdd.php b/inc/class-cachify-hdd.php index f65e92d1..f971baa6 100644 --- a/inc/class-cachify-hdd.php +++ b/inc/class-cachify-hdd.php @@ -26,6 +26,22 @@ public static function is_available() { return ! empty( $option ); } + /** + * Returns if gzip file creation is enabled + * + * @since 2.4.0 + * + * @return bool + */ + public static function is_gzip_enabled() { + /** + * Filter that allows to enable/disable gzip file creation + * + * @param bool $create_gzip_files Whether to create gzip files. Default is `true` + */ + return apply_filters( 'cachify_create_gzip_files', true ); + } + /** * Caching method as string * @@ -168,10 +184,17 @@ private static function _create_files( $data ) { trigger_error( esc_html( __METHOD__ . ": Unable to create directory {$file_path}.", E_USER_WARNING ) ); return; } - /* Write to file */ self::_create_file( self::_file_html( $file_path ), $data ); - self::_create_file( self::_file_gzip( $file_path ), gzencode( $data, 9 ) ); + + /** + * Filter that allows to enable/disable gzip file creation + * + * @param bool $create_gzip_files Whether to create gzip files. Default is `true` + */ + if ( self::is_gzip_enabled() ) { + self::_create_file( self::_file_gzip( $file_path ), gzencode( $data, 9 ) ); + } } /** diff --git a/inc/setup/cachify.hdd.htaccess.php b/inc/setup/cachify.hdd.htaccess.php index 81d1a330..a20345c3 100644 --- a/inc/setup/cachify.hdd.htaccess.php +++ b/inc/setup/cachify.hdd.htaccess.php @@ -24,7 +24,17 @@ RewriteRule .* - [E=CACHIFY_DIR:%{REQUEST_URI}] RewriteCond %{REQUEST_URI} ^$ RewriteRule .* - [E=CACHIFY_DIR:/] +{{GZIP}} + # Main Rules + RewriteCond %{REQUEST_METHOD} ="GET" + RewriteCond %{QUERY_STRING} ="" + RewriteCond %{REQUEST_URI} !^/(wp-admin|wp-content/cache)/.* + RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author)_ + RewriteCond '; +$gzip = ''; +if ( Cachify_HDD::is_gzip_enabled() ) { + $gzip = ' # gzip RewriteRule .* - [E=CACHIFY_SUFFIX:] <IfModule mod_mime.c> @@ -33,13 +43,9 @@ AddType text/html .gz AddEncoding gzip .gz </IfModule> - - # Main Rules - RewriteCond %{REQUEST_METHOD} ="GET" - RewriteCond %{QUERY_STRING} ="" - RewriteCond %{REQUEST_URI} !^/(wp-admin|wp-content/cache)/.* - RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author)_ - RewriteCond '; +'; +} +$beginning = str_replace( '{{GZIP}}', $gzip, $beginning ); $middle = '/cache/cachify/%{ENV:CACHIFY_HOST}%{ENV:CACHIFY_DIR}index.html -f RewriteRule ^(.*) '; From 341248d87cc091038a44ce831ec9b2aec60e7176 Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Tue, 17 May 2022 17:21:32 +0200 Subject: [PATCH 09/16] raise requirements to PHP 5.6 and WP 4.7 (#259) (#268) --- CHANGELOG.md | 2 ++ phpcs.xml | 4 ++-- readme.txt | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ef04e44..d1907c54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This projec ## unreleased +Requires PHP 5.6 and WordPress 4.7 or above + * Enhance: adjust styling for setup instructions (#215, props timse201) diff --git a/phpcs.xml b/phpcs.xml index be0ffbf5..750725cb 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -20,7 +20,7 @@ vendor/* - + @@ -29,6 +29,6 @@ - + diff --git a/readme.txt b/readme.txt index 3cbc92e5..c027032b 100644 --- a/readme.txt +++ b/readme.txt @@ -2,9 +2,9 @@ * Contributors: pluginkollektiv * Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=TD4AMD2D8EMZW * Tags: acceleration, cache, caching, minimize, performance, apc, disk, hdd, memcached, compression, minify, speed -* Requires at least: 4.4 -* Tested up to: 5.8 -* Requires PHP: 5.2.4 +* Requires at least: 4.7 +* Tested up to: 5.9 +* Requires PHP: 5.6 * Stable tag: 2.3.2 * License: GPLv2 or later * License URI: http://www.gnu.org/licenses/gpl-2.0.html From 0a4e6d5f3de822772949c3874269c1f1f29c90ba Mon Sep 17 00:00:00 2001 From: Karl Kowald Date: Tue, 17 May 2022 17:48:52 +0200 Subject: [PATCH 10/16] only cache responses with HTTP status 200 by default (#266) (#267) We should not cache error pages by default, so we add a check for HTTP status 200 as default caching indicator. This might still be customized using the "cachify_store_item" hook. --- inc/class-cachify.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 6f9d1745..70ae1ab5 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -1392,7 +1392,14 @@ public static function set_cache( $data ) { * @param string $cache_hash The cache hash. * @param int $cache_expires Cache validity period. */ - $should_cache = apply_filters( 'cachify_store_item', true, $data, self::$method, self::_cache_hash(), self::_cache_expires() ); + $should_cache = apply_filters( + 'cachify_store_item', + 200 === http_response_code(), + $data, + self::$method, + self::_cache_hash(), + self::_cache_expires() + ); /* Save? */ if ( $should_cache ) { From af1919a2bab6e3022294607e2787a9ed1ece14a2 Mon Sep 17 00:00:00 2001 From: Angelo Cali Date: Sun, 24 Jul 2022 17:01:23 +0200 Subject: [PATCH 11/16] Change the condpattern used to check if the request method is GET --- inc/setup/cachify.hdd.htaccess.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/setup/cachify.hdd.htaccess.php b/inc/setup/cachify.hdd.htaccess.php index a20345c3..1f64549a 100644 --- a/inc/setup/cachify.hdd.htaccess.php +++ b/inc/setup/cachify.hdd.htaccess.php @@ -26,7 +26,7 @@ RewriteRule .* - [E=CACHIFY_DIR:/] {{GZIP}} # Main Rules - RewriteCond %{REQUEST_METHOD} ="GET" + RewriteCond %{REQUEST_METHOD} GET RewriteCond %{QUERY_STRING} ="" RewriteCond %{REQUEST_URI} !^/(wp-admin|wp-content/cache)/.* RewriteCond %{HTTP_COOKIE} !(wp-postpass|wordpress_logged_in|comment_author)_ From 03d90c900d42dd72e5e9d915444be111d91d6b9a Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Tue, 16 Aug 2022 20:36:49 +0200 Subject: [PATCH 12/16] update dev-dependencies and GH actions --- .github/workflows/test.yml | 6 +++--- .github/workflows/wordpress-plugin-asset-update.yml | 2 +- .github/workflows/wordpress-plugin-deploy.yml | 2 +- .stylelintrc.json | 1 - composer.json | 2 +- package.json | 8 ++++---- 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 862a1b89..50788e22 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -4,16 +4,16 @@ jobs: quality: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: php-version: '8.0' tools: composer - name: Setup Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: - node-version: '14' + node-version: '16' - name: Code style checks for PHP and CSS run: | composer install diff --git a/.github/workflows/wordpress-plugin-asset-update.yml b/.github/workflows/wordpress-plugin-asset-update.yml index 4e9828a5..b47e1ae9 100644 --- a/.github/workflows/wordpress-plugin-asset-update.yml +++ b/.github/workflows/wordpress-plugin-asset-update.yml @@ -8,7 +8,7 @@ jobs: name: Push to stable runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: diff --git a/.github/workflows/wordpress-plugin-deploy.yml b/.github/workflows/wordpress-plugin-deploy.yml index 64136cc0..e2406894 100755 --- a/.github/workflows/wordpress-plugin-deploy.yml +++ b/.github/workflows/wordpress-plugin-deploy.yml @@ -9,7 +9,7 @@ jobs: name: New tag runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup PHP uses: shivammathur/setup-php@v2 with: diff --git a/.stylelintrc.json b/.stylelintrc.json index d15de6ea..ed7fd2f8 100644 --- a/.stylelintrc.json +++ b/.stylelintrc.json @@ -1,7 +1,6 @@ { "extends": "@wordpress/stylelint-config", "rules": { - "declaration-property-unit-whitelist": null, "selector-id-pattern": null } } diff --git a/composer.json b/composer.json index b93a9125..c3405e4e 100644 --- a/composer.json +++ b/composer.json @@ -28,7 +28,7 @@ "require-dev": { "dealerdirect/phpcodesniffer-composer-installer": "^v0.7", "matthiasmullie/minify": "^1.3", - "squizlabs/php_codesniffer": "^3.6", + "squizlabs/php_codesniffer": "^3.7", "phpcompatibility/phpcompatibility-wp": "^2.1", "wp-coding-standards/wpcs": "^2.3" }, diff --git a/package.json b/package.json index f1a0f810..2aa9ff0f 100644 --- a/package.json +++ b/package.json @@ -1,9 +1,9 @@ { "private": true, "devDependencies": { - "stylelint": "^13.13.1", - "eslint": "^8.4.1", - "@wordpress/eslint-plugin": "^9.0.4", - "@wordpress/stylelint-config": "^19.0.5" + "stylelint": "^14.10.0", + "eslint": "^8.22.0", + "@wordpress/eslint-plugin": "^12.9.0", + "@wordpress/stylelint-config": "^20.0.2" } } From 09bdf189e7c85701fa7f4b817bdbb8043f8c1ba2 Mon Sep 17 00:00:00 2001 From: Latz Date: Tue, 30 Aug 2022 16:38:24 +0200 Subject: [PATCH 13/16] close tag in dashboard widget markup correctly (#269) The dashboard widget contains inline SVG code with an open tag. While most browsers will heal this, it's invalid markup. We now make this tag self-closing to fix this. --- inc/class-cachify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 70ae1ab5..ce6a55dd 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -568,7 +568,7 @@ public static function add_dashboard_count( $items = array() ) { $items[] = sprintf( ' %s', add_query_arg( array( From 34fad2f7ea48a480973649911a3c62a87eec16bf Mon Sep 17 00:00:00 2001 From: Stefan Kalscheuer Date: Sat, 19 Nov 2022 10:45:24 +0100 Subject: [PATCH 14/16] fix URL parsing for cache key generation (#275) (#276) As part of refactoring in #190 the URL parsing has been altered, s.t. we pass a concatenation of host and path to wp_parse_url(). This results in the actual host not being parsed at all which raises a PHP warning. Prefix the URL with double slashes (the protocol is not of interest here) to fix the parsing. --- inc/class-cachify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/class-cachify.php b/inc/class-cachify.php index ce6a55dd..e06c6c16 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -1074,7 +1074,7 @@ private static function _cache_hash( $url = '' ) { if ( empty( $url ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated - $url = wp_unslash( $_SERVER['HTTP_HOST'] ) . wp_unslash( $_SERVER['REQUEST_URI'] ); + $url = '//' . wp_unslash( $_SERVER['HTTP_HOST'] ) . wp_unslash( $_SERVER['REQUEST_URI'] ); } $url_parts = wp_parse_url( $url ); From 643353e2781044a484ff76a0dcff96ec8eaf5936 Mon Sep 17 00:00:00 2001 From: Philipp <32090713+ouun@users.noreply.github.com> Date: Sun, 20 Nov 2022 10:40:27 +0100 Subject: [PATCH 15/16] update deprecated WPMS hooks (#246) Conditionally use "wp_initialize_site" and "wp_delete_site" on sites running on WP 5.1 and above in favor of the deprecated "delete_blog" and "wpmu_new_blog" hooks. Co-authored-by: Stefan Kalscheuer --- CHANGELOG.md | 1 + inc/class-cachify.php | 35 ++++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1907c54..13bd89b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. This projec Requires PHP 5.6 and WordPress 4.7 or above * Enhance: adjust styling for setup instructions (#215, props timse201) +* Enhance: update hooks for Multisite initialization in WordPress 5.1 and above (#246, props ouun) ## 2.3.2 diff --git a/inc/class-cachify.php b/inc/class-cachify.php index e06c6c16..3a88fe7d 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -132,9 +132,14 @@ public function __construct() { if ( is_admin() ) { /* Backend */ - add_action( 'wpmu_new_blog', array( __CLASS__, 'install_later' ) ); - - add_action( 'delete_blog', array( __CLASS__, 'uninstall_later' ) ); + if ( version_compare( get_bloginfo( 'version' ), '5.1', '<' ) ) { + // The following hooks are deprecated since WP 5.1 (#246). + add_action( 'wpmu_new_blog', array( __CLASS__, 'install_later' ) ); + add_action( 'delete_blog', array( __CLASS__, 'uninstall_later' ) ); + } else { + add_action( 'wp_initialize_site', array( __CLASS__, 'install_later' ) ); + add_action( 'wp_delete_site', array( __CLASS__, 'uninstall_later' ) ); + } add_action( 'admin_init', array( __CLASS__, 'register_textdomain' ) ); @@ -210,21 +215,21 @@ public static function on_activation() { } /** - * Plugin installation on new MU blog. + * Plugin installation on new WPMS site. * - * @since 1.0 - * @change 1.0 + * @since 1.0 + * @since 2.4 supports WP_Site argument * - * @param integer $id Blog ID. + * @param int|WP_Site $new_site New site ID or object. */ - public static function install_later( $id ) { + public static function install_later( $new_site ) { /* No network plugin */ if ( ! is_plugin_active_for_network( CACHIFY_BASE ) ) { return; } /* Switch to blog */ - switch_to_blog( $id ); + switch_to_blog( is_int( $new_site ) ? $new_site : $new_site->blog_id ); /* Install */ self::_install_backend(); @@ -281,21 +286,21 @@ public static function on_uninstall() { } /** - * Uninstalling of the plugin for MU and network. + * Uninstalling of the plugin for WPMS site. * - * @since 1.0 - * @change 1.0 + * @since 1.0 + * @since 2.4 supports WP_Site argument * - * @param integer $id Blog ID. + * @param int|WP_Site $old_site Old site ID or object. */ - public static function uninstall_later( $id ) { + public static function uninstall_later( $old_site ) { /* No network plugin */ if ( ! is_plugin_active_for_network( CACHIFY_BASE ) ) { return; } /* Switch to blog */ - switch_to_blog( $id ); + switch_to_blog( is_int( $old_site ) ? $old_site : $old_site->blog_id ); /* Install */ self::_uninstall_backend(); From 7a6b3b4e4c7bf277b75ab26db7da07af48b69540 Mon Sep 17 00:00:00 2001 From: timse201 Date: Sun, 20 Nov 2022 14:56:23 +0100 Subject: [PATCH 16/16] rework flush hooks and add some third-party triggers (#225) * Rework hooks for flushing the cache when modifying posts. * Deprecate register_publish_hooks() and publish_post_types(). * Introduce hooks to flush the cache on WooCommerce product updates. * Flush the cache along with Autoptimize flushing by default. Co-authored-by: Stefan Kalscheuer --- CHANGELOG.md | 1 + inc/class-cachify.php | 102 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13bd89b8..2b36210c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ Requires PHP 5.6 and WordPress 4.7 or above * Enhance: adjust styling for setup instructions (#215, props timse201) * Enhance: update hooks for Multisite initialization in WordPress 5.1 and above (#246, props ouun) +* Enhance: rework flush hooks and add some third-party triggers for Autoptimize and WooCommerce (#225, props timse201) ## 2.3.2 diff --git a/inc/class-cachify.php b/inc/class-cachify.php index 3a88fe7d..748ad2f4 100644 --- a/inc/class-cachify.php +++ b/inc/class-cachify.php @@ -90,14 +90,18 @@ public function __construct() { self::$is_nginx = $GLOBALS['is_nginx']; - /* Publish hooks */ - add_action( 'init', array( __CLASS__, 'register_publish_hooks' ), 99 ); - /* Flush Hooks */ add_action( 'init', array( __CLASS__, 'register_flush_cache_hooks' ), 10, 0 ); - + add_action( 'save_post', array( __CLASS__, 'save_update_trash_post' ) ); + add_action( 'pre_post_update', array( __CLASS__, 'post_update' ), 10, 2 ); add_action( 'cachify_remove_post_cache', array( __CLASS__, 'remove_page_cache_by_post_id' ) ); + /* Flush Hooks - third party */ + add_action( 'woocommerce_product_set_stock', array( __CLASS__, 'flush_woocommerce' ) ); + add_action( 'woocommerce_variation_set_stock', array( __CLASS__, 'flush_woocommerce' ) ); + add_action( 'woocommerce_product_set_stock_status', array( __CLASS__, 'flush_woocommerce' ) ); + add_action( 'woocommerce_variation_set_stock_status', array( __CLASS__, 'flush_woocommerce' ) ); + /* Register scripts */ add_action( 'init', array( __CLASS__, 'register_scripts' ) ); @@ -945,7 +949,7 @@ public static function touch_comment( $new_status, $old_status, $comment ) { * @since 2.1.7 Make the function public * @since 2.0.3 * - * @return void + * @deprecated no longer used since 2.4 */ public static function register_publish_hooks() { /* Available post types */ @@ -975,6 +979,8 @@ public static function register_publish_hooks() { * * @param integer $post_id Post ID. * @param object $post Post object. + * + * @deprecated no longer used since 2.4 */ public static function publish_post_types( $post_id, $post ) { /* No post_id? */ @@ -1000,6 +1006,90 @@ public static function publish_post_types( $post_id, $post ) { } } + /** + * Removes the post type cache if saved or updated + * + * @since 2.0.3 + * @since 2.1.7 Make the function public. + * @since 2.4 Renamed to save_update_trash_post with $id parameter. + * + * @param integer $id Post ID. + */ + public static function save_update_trash_post( $id ) { + $status = get_post_status( $id ); + + /* Post type published? */ + if ( 'publish' === $status ) { + self::flush_cache_for_posts( $id ); + } + } + + /** + * Removes the post type cache before an existing post type is updated in the db + * + * @since 2.0.3 + * @since 2.3.0 + * @since 2.4 Renamed to post_update. + * + * @param integer $id Post ID. + * @param array $data Post data. + */ + public static function post_update( $id, $data ) { + $new_status = $data['post_status']; + $old_status = get_post_status( $id ); + + /* Was it published and is it not trashed now? */ + if ( 'trash' !== $new_status && 'publish' === $old_status ) { + self::flush_cache_for_posts( $id ); + } + } + + /** + * Clear cache when any post type has been created or updated + * + * @since 2.4 + * + * @param integer|WP_Post $post Post ID or object. + */ + public static function flush_cache_for_posts( $post ) { + if ( is_int( $post ) ) { + $post_id = $post; + $data = get_post( $post_id ); + + if ( ! is_object( $data ) ) { + return; + } + } elseif ( is_object( $post ) ) { + $post_id = $post->ID; + } else { + return; + } + + /* Remove cache OR flush */ + if ( 1 !== self::$options['reset_on_post'] ) { + self::remove_page_cache_by_post_id( $post_id ); + } else { + self::flush_total_cache(); + } + } + + /** + * Flush post cache on WooCommerce stock changes. + * + * @since 2.4 + * + * @param int|WC_Product $product Product ID or object. + */ + public static function flush_woocommerce( $product ) { + if ( is_int( $product ) ) { + $id = $product; + } else { + $id = $product->get_id(); + } + + self::flush_cache_for_posts( $id ); + } + /** * Removes a page (id) from cache * @@ -1174,6 +1264,8 @@ public static function register_flush_cache_hooks() { 'user_register' => 10, 'edit_user_profile_update' => 10, 'delete_user' => 10, + /* third party */ + 'autoptimize_action_cachepurged' => 10, ); $flush_cache_hooks = apply_filters( 'cachify_flush_cache_hooks', $flush_cache_hooks );