query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s", $wpdb->esc_like( 'fpca_' ) . '%' ) ); // Delete post meta for both public (fpca_) and hidden (_fpca_) variants. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE %s OR meta_key LIKE %s", $wpdb->esc_like( 'fpca_' ) . '%', $wpdb->esc_like( '_fpca_' ) . '%' ) ); // Unschedule all cron events registered by this plugin. // wp_unschedule_hook() rather than wp_clear_scheduled_hook(): the latter only // removes events whose arguments match the ones passed, so it would leave // every fpca_rescore_post event behind — those are always scheduled // with a post ID argument. wp_unschedule_hook( 'fpca_check_overdue' ); wp_unschedule_hook( 'fpca_weekly_rescore' ); wp_unschedule_hook( 'fpca_rescore_post' ); // Delete transients and their paired timeout rows. $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_fpca_' ) . '%', $wpdb->esc_like( '_transient_timeout_fpca_' ) . '%' ) ); // Drop plugin-owned tables. %i is an identifier placeholder (WP 6.2+), so // the table name goes through prepare() like any other value. $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'fpca_posts' ) ); $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'fpca_assignments' ) ); // The deletes above are raw SQL, so they bypass the object cache. Without // this, a persistent cache (Redis/Memcached) keeps serving the deleted // options and meta until eviction. wp_cache_delete( 'alloptions', 'options' ); wp_cache_delete( 'notoptions', 'options' ); foreach ( array( 'options', 'posts' ) as $cache_group ) { if ( function_exists( 'wp_cache_set_last_changed' ) ) { wp_cache_set_last_changed( $cache_group ); } else { // wp_cache_set_last_changed() is WP 6.3+; this is what it does. // Calling it unguarded fatals on 6.0-6.2, which the plugin supports. wp_cache_set( 'last_changed', microtime(), $cache_group ); } } } if ( is_multisite() ) { // On a network install, clean up every site individually. foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0 ) ) as $blog_id ) { switch_to_blog( $blog_id ); fpca_run_uninstall(); restore_current_blog(); } } else { fpca_run_uninstall(); }