get_col( $wpdb->prepare( 'SELECT option_name FROM %i WHERE option_name LIKE %s LIMIT 1000', $wpdb->options, $wpdb->esc_like( 'accessible_forms_altcha_used_' ) . '%' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching foreach ( $accessible_forms_receipts as $accessible_forms_receipt ) { delete_option( $accessible_forms_receipt ); } } while ( count( $accessible_forms_receipts ) === 1000 ); $accessible_forms_settings = get_option( 'accessible_forms_settings', array() ); // Preview snapshots, unfinished reports and action feedback are temporary, // even when the administrator keeps forms, saved reports and entries. foreach ( array( 'accessible_forms_undo_', 'accessible_forms_bulk_notice_', 'accessible_forms_test_preview_', '_accessible_forms_accessibility_reviews_', 'accessible_forms_publication_blocks_', ) as $accessible_forms_prefix ) { // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Only plugin-owned temporary options. $accessible_forms_options = $wpdb->get_col( $wpdb->prepare( 'SELECT option_name FROM %i WHERE option_name LIKE %s OR option_name LIKE %s', $wpdb->options, $wpdb->esc_like( '_transient_' . $accessible_forms_prefix ) . '%', $wpdb->esc_like( '_transient_timeout_' . $accessible_forms_prefix ) . '%' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching foreach ( $accessible_forms_options as $accessible_forms_option ) { delete_option( $accessible_forms_option ); } } // Saved progress never outlives uninstall, even when the administrator // keeps completed submissions for later reactivation. foreach ( array( 'drafts' ) as $accessible_forms_suffix ) { // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Plugin-owned temporary storage. $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'accessible_form_' . $accessible_forms_suffix ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange } delete_option( 'accessible_forms_db_version' ); delete_option( 'accessible_forms_access_version' ); if ( empty( $accessible_forms_settings['delete_data'] ) ) { return; } // Checklist completion is scoped to this site and removed with its form data. // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Administrator opted into removing plugin-owned user metadata. $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE meta_key LIKE %s', $wpdb->usermeta, $wpdb->esc_like( '_accessible_forms_setup_' . get_current_blog_id() . '_' ) . '%' ) ); do { $accessible_forms_ids = get_posts( array( 'post_type' => 'accessible_form', 'post_status' => array( 'publish', 'draft', 'pending', 'private', 'future', 'trash', 'auto-draft' ), 'posts_per_page' => 100, 'fields' => 'ids', ) ); foreach ( $accessible_forms_ids as $accessible_forms_id ) { wp_delete_post( $accessible_forms_id, true ); } } while ( count( $accessible_forms_ids ) === 100 ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Explicit opt-in uninstall of the plugin-owned table. $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'accessible_form_entries' ) ); foreach ( array( 'activity', 'notifications', 'files' ) as $accessible_forms_suffix ) { // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange -- Administrator opted into removing all plugin data. $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $wpdb->prefix . 'accessible_form_' . $accessible_forms_suffix ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.DirectDatabaseQuery.SchemaChange } require_once __DIR__ . '/src/Capabilities.php'; \AccessibleForms\Capabilities::remove(); require_once __DIR__ . '/src/Access.php'; \AccessibleForms\Access::uninstall( true ); foreach ( array( 'accessible_forms_templates', 'accessible_forms_brand_presets', 'accessible_forms_last_cleanup', 'accessible_forms_extension_failure', 'accessible_forms_placement_generation', 'accessible_forms_search_index', 'accessible_forms_search_cursor', 'accessible_forms_time_migration', 'accessible_forms_live_checks', ) as $accessible_forms_option ) { delete_option( $accessible_forms_option ); } delete_metadata( 'user', 0, '_accessible_forms_saved_views_' . get_current_blog_id(), '', true ); delete_metadata( 'user', 0, '_accessible_forms_mail_notice_dismissed_' . get_current_blog_id(), '', true ); // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Only plugin-owned leases. $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE option_name LIKE %s OR option_name LIKE %s', $wpdb->options, $wpdb->esc_like( 'accessible_forms_lock_' ) . '%', $wpdb->esc_like( 'accessible_forms_reply_' ) . '%' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching delete_option( 'accessible_forms_settings' ); delete_option( 'accessible_forms_db_version' ); foreach ( array( 'accessible_forms_rl_', 'accessible_forms_errors_', 'accessible_forms_draft_', 'accessible_forms_test_result_', 'accessible_forms_settings_error_', 'accessible_forms_limit_', 'accessible_forms_import_', 'accessible_forms_placements_', 'accessible_forms_placement_error_', 'accessible_forms_spam_test_', 'accessible_forms_challenge_rate_', 'accessible_forms_reply_', 'accessible_forms_notice_', 'accessible_forms_headings_', 'accessible_forms_bulk_result_', 'accessible_forms_webhook_test_', 'accessible_forms_restored_', 'accessible_forms_search_retry', 'accessible_forms_install_retry', ) as $accessible_forms_prefix ) { // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Clean only plugin-owned transient options on uninstall. $wpdb->query( $wpdb->prepare( 'DELETE FROM %i WHERE option_name LIKE %s OR option_name LIKE %s', $wpdb->options, $wpdb->esc_like( '_transient_' . $accessible_forms_prefix ) . '%', $wpdb->esc_like( '_transient_timeout_' . $accessible_forms_prefix ) . '%' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching } } if ( is_multisite() ) { $accessible_forms_offset = 0; do { $accessible_forms_sites = get_sites( array( 'fields' => 'ids', 'number' => 100, 'offset' => $accessible_forms_offset, ) ); foreach ( $accessible_forms_sites as $accessible_forms_site ) { switch_to_blog( $accessible_forms_site ); accessible_forms_uninstall_site(); restore_current_blog(); } $accessible_forms_offset += 100; } while ( count( $accessible_forms_sites ) === 100 ); } else { accessible_forms_uninstall_site(); }