HEX
Server: nginx/1.24.0
System: Linux nowruzgan 6.8.0-57-generic #59-Ubuntu SMP PREEMPT_DYNAMIC Sat Mar 15 17:40:59 UTC 2025 x86_64
User: babak (1000)
PHP: 8.3.6
Disabled: NONE
Upload Files
File: /var/www/school/wp-content/plugins/simple-site-reset.php
<?php
/**
 * Plugin Name: Simple Site Reset (Free)
 * Description: Wipes content (posts, pages, CPTs), comments, terms, and uploads; deactivates other plugins; optionally recreates default content. Keeps siteurl/home so you stay logged in.
 * Version: 1.0.0
 * Author: You
 */

if (!defined('ABSPATH')) exit;

class Simple_Site_Reset {
    const SLUG = 'simple-site-reset';

    public function __construct() {
        add_action('admin_menu', [$this, 'menu']);
        add_action('admin_post_simple_site_reset_run', [$this, 'handle_reset']);
    }

    public function menu() {
        add_management_page(
            'Simple Site Reset',
            'Simple Site Reset',
            'manage_options',
            self::SLUG,
            [$this, 'render_page']
        );
    }

    private function checkbox($name, $label, $checked = true, $desc = '') {
        printf(
            '<label style="display:block;margin-bottom:8px;"><input type="checkbox" name="%1$s" value="1" %2$s> <strong>%3$s</strong>%4$s</label>',
            esc_attr($name),
            checked($checked, true, false),
            esc_html($label),
            $desc ? ' <em style="opacity:.8;">('.esc_html($desc).')</em>' : ''
        );
    }

    public function render_page() {
        if (!current_user_can('manage_options')) return;
        ?>
        <div class="wrap">
            <h1>Simple Site Reset</h1>
            <p><strong style="color:#b32d2e;">Danger zone:</strong> This will permanently delete selected data. Make a full backup first.</p>
            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
                <?php wp_nonce_field('simple_site_reset'); ?>
                <input type="hidden" name="action" value="simple_site_reset_run" />
                <h2>What to reset</h2>
                <?php
                $this->checkbox('wipe_content', 'Delete all posts/pages/CPTs', true, 'Also deletes post meta.');
                $this->checkbox('wipe_comments', 'Delete all comments', true);
                $this->checkbox('wipe_terms', 'Delete all categories/tags/terms', true);
                $this->checkbox('wipe_uploads', 'Delete all files under wp-content/uploads', false);
                $this->checkbox('deactivate_plugins', 'Deactivate all plugins except this one', true);
                $this->checkbox('delete_users', 'Delete all users except the current admin', false);
                $this->checkbox('recreate_defaults', 'Recreate “Hello world!” post and “Sample Page”', true);
                ?>
                <h2>Type to confirm</h2>
                <p>Type <code>reset</code> to confirm: <input type="text" name="confirm" value="" required></p>
                <p><button class="button button-primary" type="submit">Run Reset</button></p>
            </form>
            <p><small>Notes: Does <em>not</em> drop core tables or touch <code>siteurl</code>/<code>home</code>. For a true reinstall, use a host/CLI or phpMyAdmin.</small></p>
        </div>
        <?php
    }

    public function handle_reset() {
        if (!current_user_can('manage_options')) wp_die('Insufficient permissions.');
        check_admin_referer('simple_site_reset');
        if (!isset($_POST['confirm']) || trim($_POST['confirm']) !== 'reset') wp_die('Confirmation text mismatch.');

        global $wpdb;
        $log = [];

        // Safeguards
        if (is_multisite()) {
            // Operate only on current blog. Network-wide "factory reset" is intentionally not supported here.
            $log[] = 'Multisite detected: operating on current site only.';
        }

        // Options
        $wipe_content       = !empty($_POST['wipe_content']);
        $wipe_comments      = !empty($_POST['wipe_comments']);
        $wipe_terms         = !empty($_POST['wipe_terms']);
        $wipe_uploads       = !empty($_POST['wipe_uploads']);
        $deactivate_plugins = !empty($_POST['deactivate_plugins']);
        $delete_users       = !empty($_POST['delete_users']);
        $recreate_defaults  = !empty($_POST['recreate_defaults']);

        // 1) Deactivate all other plugins
        if ($deactivate_plugins) {
            $active = (array) get_option('active_plugins', []);
            $me = plugin_basename(__FILE__);
            $keep = array_filter($active, function($p) use ($me){ return $p === $me; });
            update_option('active_plugins', array_values($keep));
            $log[] = 'Deactivated all plugins except this one.';
        }

        // 2) Wipe uploads
        if ($wipe_uploads) {
            $upload = wp_get_upload_dir();
            $base   = trailingslashit($upload['basedir']);
            $deleted = $this->rrmdir($base);
            $log[] = $deleted ? 'Deleted all files under uploads.' : 'Uploads folder already empty or not writable.';
        }

        // 3) Delete content (posts, pages, CPTs) & postmeta
        if ($wipe_content) {
            // Faster than wp_delete_post for large sites; we deliberately nuke relationships & meta.
            $wpdb->query("DELETE FROM {$wpdb->postmeta}");
            $wpdb->query("DELETE FROM {$wpdb->posts}");
            $log[] = 'Deleted all posts/pages/custom post types and post meta.';
        }

        // 4) Comments
        if ($wipe_comments) {
            $wpdb->query("DELETE FROM {$wpdb->commentmeta}");
            $wpdb->query("DELETE FROM {$wpdb->comments}");
            $log[] = 'Deleted all comments and comment meta.';
        }

        // 5) Terms (cats/tags/taxonomies)
        if ($wipe_terms) {
            $wpdb->query("DELETE FROM {$wpdb->term_relationships}");
            $wpdb->query("DELETE FROM {$wpdb->term_taxonomy}");
            $wpdb->query("DELETE FROM {$wpdb->terms}");
            if ($this->table_exists($wpdb->termmeta)) {
                $wpdb->query("DELETE FROM {$wpdb->termmeta}");
            }
            $log[] = 'Deleted all terms, term taxonomies, and relationships.';
        }

        // 6) Users (except current)
        if ($delete_users) {
            $current = get_current_user_id();
            $users = get_users(['fields' => ['ID']]);
            foreach ($users as $u) {
                if ((int)$u->ID === (int)$current) continue;
                require_once ABSPATH . 'wp-admin/includes/user.php';
                wp_delete_user($u->ID, $current); // reassign to current admin
            }
            $log[] = 'Deleted all users except the current admin (content reassigned).';
        }

        // 7) Recreate defaults
        if ($recreate_defaults) {
            // Hello world
            $hello_id = wp_insert_post([
                'post_title'   => 'Hello world!',
                'post_content' => 'Welcome to WordPress. This is your first post. Edit or delete it, then start writing!',
                'post_status'  => 'publish',
                'post_type'    => 'post',
            ]);

            // Sample Page
            $page_id = wp_insert_post([
                'post_title'   => 'Sample Page',
                'post_content' => "This is an example page. It's different from a blog post...",
                'post_status'  => 'publish',
                'post_type'    => 'page',
            ]);

            // Default category (if we nuked terms)
            if ($wipe_terms) {
                $cat = wp_insert_term('Uncategorized', 'category', ['slug' => 'uncategorized']);
                if (!is_wp_error($cat)) update_option('default_category', (int)$cat['term_id']);
            }

            flush_rewrite_rules();
            $log[] = 'Recreated default “Hello world!” post and “Sample Page”; flushed permalinks.';
        }

        // Redirect back with log
        $url = add_query_arg([
            'page' => self::SLUG,
            'ssr_done' => 1,
            'ssr_log'  => rawurlencode(base64_encode(wp_json_encode($log)))
        ], admin_url('tools.php'));
        wp_safe_redirect($url);
        exit;
    }

    private function table_exists($table) {
        global $wpdb;
        $table = esc_sql($table);
        return (bool) $wpdb->get_var($wpdb->prepare("SHOW TABLES LIKE %s", $table));
    }

    private function rrmdir($dir) {
        // Delete contents of a directory but keep the directory itself.
        if (!is_dir($dir)) return false;
        $ok = true;
        $items = @scandir($dir);
        if ($items === false) return false;
        foreach ($items as $item) {
            if ($item === '.' || $item === '..') continue;
            $path = $dir . $item;
            if (is_dir($path)) {
                $ok = $this->rrmdir(trailingslashit($path)) && @rmdir($path) && $ok;
            } else {
                $ok = @unlink($path) && $ok;
            }
        }
        return $ok;
    }
}
new Simple_Site_Reset();