prefix . $table ); $wpdb->query( "DROP TABLE IF EXISTS {$table}" ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared } $options = array( 'storesayer_token', 'storesayer_token_created', 'storesayer_disabled_tools', 'storesayer_db_version', 'storesayer_mcp_enabled', 'storesayer_rate_limit', 'storesayer_readonly_mode', 'storesayer_force_draft', 'storesayer_role_access', 'storesayer_oauth_enabled', 'storesayer_logging_enabled', 'storesayer_legacy_auth_enabled', ); foreach ( $options as $option ) { delete_option( $option ); } // Transients — OAuth auth codes, DCR/token rate limits, logger boot marker, revenue cache. $transient_prefixes = array( 'storesayer_code_', 'storesayer_dcr_', 'storesayer_tf_', 'storesayer_log_boot_', 'sa_code_', 'sa_dcr_', 'sa_tf_', 'sa_log_boot_', 'storesayer_store_rev_', 'storesayer_inv_units_' ); foreach ( $transient_prefixes as $prefix ) { $wpdb->query( // phpcs:ignore WordPress.DB.DirectDatabaseQuery $wpdb->prepare( "DELETE FROM {$wpdb->options} WHERE option_name LIKE %s OR option_name LIKE %s", $wpdb->esc_like( '_transient_' . $prefix ) . '%', $wpdb->esc_like( '_transient_timeout_' . $prefix ) . '%' ) ); } // Debug log directory — wp-content/uploads/storesayer-logs/ (per-site uploads on multisite). $upload = wp_upload_dir( null, false ); if ( empty( $upload['error'] ) ) { $dir = trailingslashit( $upload['basedir'] ) . 'storesayer-logs'; if ( is_dir( $dir ) ) { foreach ( array_merge( glob( $dir . '/*' ) ?: array(), glob( $dir . '/.htaccess' ) ?: array() ) as $file ) { if ( is_file( $file ) ) { wp_delete_file( $file ); } } // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir rmdir( $dir ); } } } if ( is_multisite() ) { foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0, ) ) as $storesayer_site_id ) { switch_to_blog( $storesayer_site_id ); storesayer_uninstall_site(); restore_current_blog(); } } else { storesayer_uninstall_site(); } wp_clear_scheduled_hook( 'storesayer_cleanup_sessions' );