get_charset_collate(); $templates = self::table('templates'); $deployments = self::table('deployments'); $audit_logs = self::table('audit_logs'); dbDelta("CREATE TABLE {$templates} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, template_key varchar(80) NOT NULL, name varchar(160) NOT NULL, description text NOT NULL, os_type varchar(24) NOT NULL, cpu_cores int unsigned NOT NULL, memory_mb int unsigned NOT NULL, disk_gb int unsigned NOT NULL, default_ttl_hours int unsigned NOT NULL, proxmox_template_id int unsigned NOT NULL, is_active tinyint(1) NOT NULL DEFAULT 1, created_at datetime NOT NULL, updated_at datetime NOT NULL, PRIMARY KEY (id), UNIQUE KEY template_key (template_key) ) {$charset_collate};"); dbDelta("CREATE TABLE {$deployments} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, name varchar(160) NOT NULL, status varchar(32) NOT NULL, proxmox_vm_id int unsigned DEFAULT NULL, ip_addresses longtext NULL, error_message text NULL, expires_at datetime NULL, created_at datetime NOT NULL, updated_at datetime NOT NULL, template_id bigint(20) unsigned NOT NULL, requested_by bigint(20) unsigned NOT NULL, PRIMARY KEY (id), KEY status (status), KEY expires_at (expires_at), KEY template_id (template_id), KEY requested_by (requested_by) ) {$charset_collate};"); $wpdb->query("ALTER TABLE {$deployments} MODIFY expires_at datetime NULL"); $ip_column = $wpdb->get_var($wpdb->prepare("SHOW COLUMNS FROM {$deployments} LIKE %s", 'ip_addresses')); if ($ip_column === null) { $wpdb->query("ALTER TABLE {$deployments} ADD COLUMN ip_addresses longtext NULL AFTER proxmox_vm_id"); } dbDelta("CREATE TABLE {$audit_logs} ( id bigint(20) unsigned NOT NULL AUTO_INCREMENT, action varchar(80) NOT NULL, entity_type varchar(80) NOT NULL, entity_id bigint(20) unsigned NOT NULL, actor_id bigint(20) unsigned NOT NULL, metadata longtext NULL, created_at datetime NOT NULL, PRIMARY KEY (id), KEY entity_lookup (entity_type, entity_id), KEY created_at (created_at) ) {$charset_collate};"); } private static function schedule_expiration_check(): void { if (!wp_next_scheduled('spp_expire_deployments')) { wp_schedule_event(time() + 5 * MINUTE_IN_SECONDS, 'hourly', 'spp_expire_deployments'); } } public static function table(string $name): string { global $wpdb; return $wpdb->prefix . 'spp_' . $name; } private static function seed_templates(): void { global $wpdb; $table = self::table('templates'); $now = current_time('mysql'); $templates = [ [ 'template_key' => 'turnkey-pbx-test', 'name' => 'Turnkey PBX Test Appliance', 'description' => 'Small PBX appliance for call-flow reproduction and support testing.', 'os_type' => 'APPLIANCE', 'cpu_cores' => 2, 'memory_mb' => 2048, 'disk_gb' => 24, 'default_ttl_hours' => 72, 'proxmox_template_id' => 9001, ], [ 'template_key' => 'windows-support-client', 'name' => 'Windows Support Client', 'description' => 'Standard Windows client VM with support tooling pre-installed.', 'os_type' => 'WINDOWS', 'cpu_cores' => 4, 'memory_mb' => 8192, 'disk_gb' => 80, 'default_ttl_hours' => 48, 'proxmox_template_id' => 9002, ], [ 'template_key' => 'linux-utility-vm', 'name' => 'Linux Utility VM', 'description' => 'Lightweight Linux host for network checks, packet capture, and diagnostics.', 'os_type' => 'LINUX', 'cpu_cores' => 2, 'memory_mb' => 2048, 'disk_gb' => 32, 'default_ttl_hours' => 168, 'proxmox_template_id' => 9003, ], ]; foreach ($templates as $template) { $exists = (int) $wpdb->get_var( $wpdb->prepare("SELECT id FROM {$table} WHERE template_key = %s", $template['template_key']) ); $data = array_merge($template, [ 'is_active' => 1, 'updated_at' => $now, ]); if ($exists > 0) { $wpdb->update($table, $data, ['id' => $exists]); continue; } $wpdb->insert($table, array_merge($data, ['created_at' => $now])); } } }