get_col( // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- a query WordPress has no API for; nothing to cache. "SELECT option_name FROM {$wpdb->options} WHERE option_name = 'transtrix_settings' OR option_name = 'transtrix_jobs' OR option_name LIKE 'transtrix\_job\_%' OR option_name LIKE 'transtrix\_cancel\_%' OR option_name = 'transtrix_store_key' OR option_name LIKE 'transtrix\_restore\_%' OR option_name LIKE 'transtrix\_fullsite\_state\_%' OR option_name LIKE 'transtrix\_step\_lock\_%' OR option_name LIKE '\_transient\_transtrix\_%' OR option_name LIKE '\_transient\_timeout\_transtrix\_%'" ); foreach ( (array) $options as $option ) { delete_option( $option ); } // Markers on imported media and orders; WooCommerce keeps HPOS order meta in its own table. delete_post_meta_by_key( '_transtrix_checksum' ); delete_post_meta_by_key( '_transtrix_source_order' ); $orders_meta = $wpdb->prefix . 'wc_orders_meta'; if ( $orders_meta === $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $orders_meta ) ) ) ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- a query WordPress has no API for; nothing to cache. $wpdb->delete( $orders_meta, array( 'meta_key' => '_transtrix_source_order' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.SlowDBQuery.slow_db_query_meta_key -- one-off cleanup on uninstall. } // Temp and renamed-aside tables an interrupted whole-site restore left. $tables = array_merge( (array) $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', 'transtrix\_tmp\_' . $wpdb->esc_like( $wpdb->prefix ) . '%' ) ), // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- a query WordPress has no API for; nothing to cache. (array) $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $wpdb->prefix ) . '%\_transtrix\_old' ) ) // phpcs:ignore WordPress.DB.DirectDatabaseQuery -- a query WordPress has no API for; nothing to cache. ); foreach ( $tables as $table ) { $wpdb->query( $wpdb->prepare( 'DROP TABLE IF EXISTS %i', $table ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.DirectDatabaseQuery.SchemaChange -- a query WordPress has no API for; nothing to cache. } $uploads = wp_upload_dir( null, false ); $live = array( get_theme_root(), WP_PLUGIN_DIR ); if ( empty( $uploads['error'] ) ) { // Whole-site work directories and finished archives are large, and a site // owner who asked for the data to go does not expect a couple of hundred // megabytes to stay behind in uploads. transtrix_uninstall_remove_tree( trailingslashit( $uploads['basedir'] ) . 'transtrix' ); $live[] = $uploads['basedir']; } // Folders a whole-site restore moved aside, as the old tables above are dropped. foreach ( $live as $dir ) { foreach ( (array) glob( untrailingslashit( $dir ) . '-transtrix-old-*', GLOB_ONLYDIR ) as $aside ) { transtrix_uninstall_remove_tree( (string) $aside ); } } } /** * Delete a directory and everything in it. * * @param string $dir Directory. * @return void */ function transtrix_uninstall_remove_tree( $dir ) { if ( ! is_dir( $dir ) ) { return; } $items = new RecursiveIteratorIterator( new RecursiveDirectoryIterator( $dir, FilesystemIterator::SKIP_DOTS ), RecursiveIteratorIterator::CHILD_FIRST ); foreach ( $items as $item ) { if ( $item->isDir() ) { rmdir( $item->getPathname() ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- direct file I/O; WP_Filesystem needs credentials a REST request does not have. } else { wp_delete_file( $item->getPathname() ); } } rmdir( $dir ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- direct file I/O; WP_Filesystem needs credentials a REST request does not have. } if ( is_multisite() ) { foreach ( get_sites( array( 'fields' => 'ids', 'number' => 0, ) ) as $transtrix_site ) { switch_to_blog( $transtrix_site ); transtrix_uninstall_site(); restore_current_blog(); } } else { transtrix_uninstall_site(); }