clear_scheduled_hooks(); $this->clear_cache(); $this->log_deactivation(); // Note: We don't delete user data on deactivation // Data is only removed on uninstall } /** * Clear all scheduled hooks * * @return void */ private function clear_scheduled_hooks(): void { $scheduled_hooks = [ 'thinkrank_monthly_credit_reset', 'thinkrank_cache_cleanup', 'thinkrank_usage_analytics', ]; foreach ($scheduled_hooks as $hook) { $timestamp = wp_next_scheduled($hook); if ($timestamp) { wp_unschedule_event($timestamp, $hook); } } // Clear all instances of our hooks wp_clear_scheduled_hook('thinkrank_monthly_credit_reset'); wp_clear_scheduled_hook('thinkrank_cache_cleanup'); wp_clear_scheduled_hook('thinkrank_usage_analytics'); } /** * Clear plugin cache * * @return void */ private function clear_cache(): void { global $wpdb; // Clear AI cache table with proper escaping $cache_table = $wpdb->prefix . 'thinkrank_ai_cache'; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Plugin deactivation requires direct database access to check table existence $table_exists = $wpdb->get_var( $wpdb->prepare("SHOW TABLES LIKE %s", $cache_table) ); if ($table_exists === $cache_table) { // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Table name is properly constructed from controlled prefix, plugin deactivation requires direct database access $wpdb->query("TRUNCATE TABLE {$cache_table}"); } // Clear WordPress transients with proper escaping // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- $wpdb->options is a WordPress core property, plugin deactivation requires direct database access $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like('_transient_thinkrank_') . '%', $wpdb->esc_like('_transient_timeout_thinkrank_') . '%' ) ); // Clear object cache if available if (function_exists('wp_cache_flush_group')) { wp_cache_flush_group('thinkrank'); } } /** * Log deactivation for analytics * * @return void */ private function log_deactivation(): void { $deactivation_data = [ 'timestamp' => time(), 'version' => THINKRANK_VERSION, 'wp_version' => get_bloginfo('version'), 'php_version' => PHP_VERSION, 'active_plugins' => get_option('active_plugins', []), 'site_url' => get_site_url(), ]; // Store deactivation data for potential feedback update_option('thinkrank_last_deactivation', $deactivation_data); // Remove activation flag delete_option('thinkrank_activated'); } }