get_col( "SELECT ID FROM {$wpdb->posts} WHERE post_type LIKE 'easy\_invoice%'" ); if ( ! empty( $ids ) ) { $id_list = implode( ',', array_map( 'intval', $ids ) ); $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE post_id IN ({$id_list})" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- integers. $wpdb->query( "DELETE FROM {$wpdb->term_relationships} WHERE object_id IN ({$id_list})" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- integers. $wpdb->query( "DELETE FROM {$wpdb->posts} WHERE ID IN ({$id_list})" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- integers. } // Meta the plugin attaches to other posts (WooCommerce orders, pages). $wpdb->query( "DELETE FROM {$wpdb->postmeta} WHERE meta_key LIKE '\_easy\_invoice\_%' OR meta_key LIKE 'easy\_invoice\_%'" ); // Client records live on users as meta; the users themselves stay. $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE '\\_easy\\_invoice\\_%' OR meta_key LIKE 'easy\\_invoice\\_%'" ); // Options and transients, ours and the addons'. $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'easy\\_invoice\\_%' OR option_name LIKE '\\_transient\\_easy\\_invoice\\_%' OR option_name LIKE '\\_transient\\_timeout\\_easy\\_invoice\\_%' OR option_name LIKE '\\_site\\_transient\\_easy\\_invoice\\_%'" ); // Tables the addons created. $tables = $wpdb->get_col( $wpdb->prepare( 'SHOW TABLES LIKE %s', $wpdb->esc_like( $wpdb->prefix . 'easy_invoice_' ) . '%' ) ); foreach ( $tables as $table ) { $wpdb->query( "DROP TABLE IF EXISTS `{$table}`" ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name from SHOW TABLES. } // Roles the plugin added. foreach ( [ 'ei_manager', 'ei_accountant', 'ei_sales', 'ei_viewer', 'easy_invoice_client' ] as $role ) { if ( get_role( $role ) ) { remove_role( $role ); } } wp_cache_flush();