Use at your own risk!

Bulk Remove Themes

Download the plugin uploaded zip file

The Code

Can be added as snippet

<?php
/**
 * Plugin Name: Bulk Remove Themes
 * Plugin URI: https://peteringersoll.com/
 * Description: Adds functionality to bulk remove themes from the WordPress admin under the Appearance menu.
 * Version: 1.0
 * Author: Peter Ingersoll (AI generated)
 * Author URI: https://peteringersoll.com/
 */

add_action('admin_menu', function() {
    add_submenu_page(
        'themes.php',
        'Bulk Remove Themes', // Admin Page title
        'Bulk Remove Themes', // Admin Menu title
        'manage_options',
        'bulk-remove-themes', // Menu slug
        'bulk_remove_themes_page' // Function name
    );
});

function bulk_remove_themes_page() {
    $action = isset($_REQUEST['action']) ? sanitize_text_field($_REQUEST['action']) : '';
    $user_id = get_current_user_id();
    if ('confirm_delete' === $action && get_transient("themes_to_delete_{$user_id}")) {
        echo '<div class="wrap"><h1>These themes will be removed:</h1><ul>';
        $themes_to_delete = get_transient("themes_to_delete_{$user_id}");
        foreach ($themes_to_delete as $theme_stylesheet) {
            $theme = wp_get_theme($theme_stylesheet);
            echo '<li>' . esc_html($theme->Name) . '</li>';
        }
        echo '</ul>';
        echo '<form action="" method="post">';
        wp_nonce_field('confirm-delete-themes');
        submit_button('Delete Themes', 'primary', 'confirm_delete');
        echo ' <a href="' . esc_url(admin_url('admin.php?page=bulk-remove-themes')) . '" class="button">Abort / Back</a>';
        echo '</form></div>';
    } else {
        $themes = wp_get_themes();
        $active_theme = wp_get_theme();
        echo '<div class="wrap"><h1>Bulk Remove Themes</h1>'; // Changed heading
        echo '<form method="post" action="'.esc_url(admin_url('admin-post.php')).'">';
        wp_nonce_field('bulk-delete-themes');
        echo '<input type="hidden" name="action" value="submit_themes_for_deletion">';
        echo '<table class="wp-list-table widefat fixed striped">';
        echo '<thead><tr><th scope="col" class="check-column"><input type="checkbox" /></th><th scope="col">Theme Name</th></tr></thead>';
        echo '<tbody id="the-list">';
        foreach ($themes as $theme) {
            if ($theme->get_stylesheet() != $active_theme->get_stylesheet()) {
                echo '<tr><th scope="row" class="check-column"><input type="checkbox" name="themes[]" value="' . esc_attr($theme->get_stylesheet()) . '" /></th><td>' . esc_html($theme->get('Name')) . '</td></tr>';
            }
        }
        echo '</tbody></table>';
        submit_button('Delete Selected Themes');
        echo '</form></div>';
    }
}

add_action('admin_post_submit_themes_for_deletion', function() {
    check_admin_referer('bulk-delete-themes');
    $user_id = get_current_user_id();
    $themes = isset($_POST['themes']) ? array_map('sanitize_text_field', $_POST['themes']) : [];
    set_transient("themes_to_delete_{$user_id}", $themes, 60 * 60); // Store for 1 hour
    wp_redirect(admin_url('admin.php?page=bulk-remove-themes&action=confirm_delete'));
    exit;
});

add_action('admin_init', function() {
    if (isset($_POST['confirm_delete']) && check_admin_referer('confirm-delete-themes')) {
        $user_id = get_current_user_id();
        $themes_to_delete = get_transient("themes_to_delete_{$user_id}");
        if ($themes_to_delete) {
            foreach ($themes_to_delete as $theme_stylesheet) {
                if (current_user_can('delete_themes') && $theme_stylesheet !== get_stylesheet()) {
                    delete_theme($theme_stylesheet);
                }
            }
            set_transient("themes_deleted_success_{$user_id}", '1', 10); // Short expiry, just for the redirect.
            delete_transient("themes_to_delete_{$user_id}");
        }
        wp_redirect(admin_url('admin.php?page=bulk-remove-themes'));
        exit;
    }
    // Check for the success transient and add admin notice
    $user_id = get_current_user_id();
    if (get_transient("themes_deleted_success_{$user_id}")) {
        add_action('admin_notices', function() {
            echo '<div class="notice notice-success is-dismissible"><p>Selected themes have been deleted.</p></div>';
        });
        delete_transient("themes_deleted_success_{$user_id}");
    }
});