'affiliate_product', 'post_status' => 'any', 'numberposts' => -1, 'fields' => 'ids', ) ); foreach ( $affiliateboxes_products as $affiliateboxes_product_id ) { wp_delete_post( $affiliateboxes_product_id, true ); // true = force delete, bypass trash. } // Delete any orphaned meta, including keys used by versions before the rename. foreach ( array( '\_affprod\_%', '\_affiliateboxes\_%' ) as $affiliateboxes_meta_pattern ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk cleanup on uninstall; there is no API for deleting by key pattern. $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->postmeta WHERE meta_key LIKE %s", $affiliateboxes_meta_pattern ) ); } // Delete named options. $affiliateboxes_options = array( 'affiliateboxes_settings', 'affiliateboxes_last_sync', 'affiliateboxes_migrated_to_products', 'affiliateboxes_receive_debug_log', 'affiliateboxes_signature_failure', ); foreach ( $affiliateboxes_options as $affiliateboxes_option ) { delete_option( $affiliateboxes_option ); } /* * Delete transients. Batch IDs and rate-limit keys carry a generated suffix, so these * have to be matched by prefix rather than deleted by name. Timeout rows are matched by * the same prefix pattern. */ // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Bulk cleanup on uninstall; there is no API for deleting transients by prefix. $wpdb->query( $wpdb->prepare( "DELETE FROM $wpdb->options WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_affiliateboxes_' ) . '%', $wpdb->esc_like( '_transient_timeout_affiliateboxes_' ) . '%' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching if ( function_exists( 'wp_cache_flush' ) ) { wp_cache_flush(); } } /** * Remove this plugin's queued jobs from the shared Action Scheduler tables. * * Action Scheduler is not loaded during uninstall, so its API is unavailable and the rows are * removed directly. Only rows in this plugin's group are touched; the tables themselves may * belong to WooCommerce or another plugin and are left alone. */ function affiliateboxes_uninstall_scheduled_actions() { global $wpdb; $affiliateboxes_actions_table = $wpdb->prefix . 'actionscheduler_actions'; $affiliateboxes_groups_table = $wpdb->prefix . 'actionscheduler_groups'; $affiliateboxes_logs_table = $wpdb->prefix . 'actionscheduler_logs'; // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Cleanup on uninstall; table names cannot use placeholders. $affiliateboxes_has_tables = $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $affiliateboxes_actions_table ) ) ); if ( $affiliateboxes_has_tables !== $affiliateboxes_actions_table ) { return; } $affiliateboxes_group_id = $wpdb->get_var( $wpdb->prepare( "SELECT group_id FROM {$affiliateboxes_groups_table} WHERE slug = %s", 'affiliateboxes' ) ); if ( ! $affiliateboxes_group_id ) { return; } $affiliateboxes_group_id = (int) $affiliateboxes_group_id; $affiliateboxes_action_ids = $wpdb->get_col( $wpdb->prepare( "SELECT action_id FROM {$affiliateboxes_actions_table} WHERE group_id = %d", $affiliateboxes_group_id ) ); if ( ! empty( $affiliateboxes_action_ids ) ) { // Every value is cast through absint(), so the list is safe to interpolate. $affiliateboxes_id_list = implode( ',', array_map( 'absint', $affiliateboxes_action_ids ) ); $wpdb->query( "DELETE FROM {$affiliateboxes_logs_table} WHERE action_id IN ({$affiliateboxes_id_list})" ); } $wpdb->delete( $affiliateboxes_actions_table, array( 'group_id' => $affiliateboxes_group_id ), array( '%d' ) ); $wpdb->delete( $affiliateboxes_groups_table, array( 'group_id' => $affiliateboxes_group_id ), array( '%d' ) ); // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared } /** * Remove the log directory written by versions before 1.1.0. * * Current versions log through error_log() and create no files, but an older install may have * left a wp-content/affiliateboxes-logs directory behind. */ function affiliateboxes_uninstall_legacy_log_directory() { $affiliateboxes_log_dir = WP_CONTENT_DIR . '/affiliateboxes-logs'; if ( ! is_dir( $affiliateboxes_log_dir ) ) { return; } require_once ABSPATH . 'wp-admin/includes/file.php'; global $wp_filesystem; if ( ! WP_Filesystem() || ! $wp_filesystem ) { return; } $wp_filesystem->delete( $affiliateboxes_log_dir, true ); } if ( is_multisite() ) { $affiliateboxes_site_ids = get_sites( array( 'fields' => 'ids', 'number' => 0, ) ); foreach ( $affiliateboxes_site_ids as $affiliateboxes_site_id ) { switch_to_blog( $affiliateboxes_site_id ); affiliateboxes_uninstall_site(); restore_current_blog(); } } else { affiliateboxes_uninstall_site(); } // Queued jobs and the retired log directory are shared across the install, not per site. affiliateboxes_uninstall_scheduled_actions(); affiliateboxes_uninstall_legacy_log_directory();