statusService = new EmulatorStatusService; $this->jarService = new EmulatorJarService; $this->sourceService = new EmulatorSourceService; $this->buildService = new EmulatorBuildService; $this->sqlService = new EmulatorSqlService; $this->backupService = new EmulatorBackupService; $this->settings = app(SettingsService::class); } public function isConfigured(): bool { return $this->statusService->isConfigured(); } public function getStatus(): array { $status = $this->statusService->getStatus(); $updateCheck = $this->jarService->checkForUpdates(); $sourceInfo = $this->sourceService->checkForUpdates(); return array_merge($status, [ 'update_available' => $updateCheck['update_available'] ?? false, 'current_version' => $updateCheck['current_version'] ?? setting('emulator_version', 'N/A'), 'latest_version' => $updateCheck['latest_version'] ?? 'N/A', 'update_type' => $updateCheck['type'] ?? 'unknown', 'has_source_updates' => $sourceInfo['has_update'] ?? false, 'latest_sha' => $sourceInfo['latest_sha'] ?? null, 'latest_message' => $sourceInfo['latest_message'] ?? null, 'latest_author' => $sourceInfo['latest_author'] ?? null, 'latest_date' => $sourceInfo['latest_date'] ?? null, 'stored_sha' => $sourceInfo['stored_sha'] ?? null, 'stored_date' => $sourceInfo['stored_date'] ?? null, 'source_info' => $sourceInfo, ]); } public function checkForUpdates(): array { return $this->jarService->checkForUpdates(); } public function checkForSqlUpdates(bool $recentOnly = true): array { return $this->sqlService->checkForUpdates($recentOnly); } public function runSqlUpdates(): array { return $this->sqlService->runUpdates(); } public function getAppliedSqlUpdates(): array { return $this->sqlService->getAppliedUpdates(); } public function updateEmulator(): array { if (! $this->isConfigured()) { return ['success' => false, 'error' => 'Geen GitHub URL geconfigureerd']; } $check = $this->checkForUpdates(); if (! ($check['update_available'] ?? false)) { if ($check['type'] === 'not_found' && ($check['source_available'] ?? false)) { return $this->buildFromSource(); } return ['success' => false, 'error' => 'Emulator is al up-to-date']; } $hasSourceUpdates = ($check['has_source_updates'] ?? false) || ($check['type'] ?? '') === 'source_build'; if ($hasSourceUpdates && $this->sourceService->isSourceBuildAvailable()) { return $this->buildFromSource(); } if ($check['type'] === 'source_build') { return $this->buildFromSource(); } if (! ($check['jar_url'] ?? null)) { return ['success' => false, 'error' => 'Geen .jar gevonden']; } $result = $this->jarService->performUpdate($check); if ($result['success']) { $this->runSqlUpdates(); if ($this->restartEmulator()) { $result['restarted'] = true; $result['message'] = ($result['message'] ?? '') . ' | 🔄 Emulator herstart'; } } return $result; } public function performUpdate(array $check): array { return $this->jarService->performUpdate($check); } public function buildFromSource(bool $force = false): array { return $this->buildService->buildFromSource($force); } public function restartEmulator(): bool { $serviceName = $this->settings->getOrDefault('emulator_service_name', 'emulator'); try { Log::info('[EmulatorUpdate] Restarting emulator service: ' . $serviceName); $result = Process::timeout(30)->run("systemctl restart {$serviceName} 2>&1"); if ($result->successful()) { return true; } $result = Process::timeout(30)->run("service {$serviceName} restart 2>&1"); return $result->successful(); } catch (\Exception $e) { Log::error('[EmulatorUpdate] Failed to restart emulator', ['error' => $e->getMessage()]); return false; } } public function getBackupList(): array { return $this->backupService->getList(); } public function restoreBackup(string $backupName): array { return $this->backupService->restore($backupName); } public function getInstalledVersion(): string { return $this->statusService->getInstalledVersion(); } public function getInstalledJar(): ?string { return $this->statusService->getInstalledJar(); } public function getInstalledJarInfo(): array { return $this->statusService->getInstalledJarInfo(); } public function getLastSqlUpdate(): ?string { return setting('emulator_last_sql_update'); } public function debugStatus(): array { return Cache::remember('emulator_debug_status', 120, function () { $installedDate = $this->settings->getOrDefault('emulator_jar_installed_date', null); $sourceCommit = $this->settings->getOrDefault('emulator_source_commit', null); $sourceDate = $this->settings->getOrDefault('emulator_source_date', null); $emulatorVersion = $this->settings->getOrDefault('emulator_version', null); $jarFiles = $this->statusService->getInstalledJarInfo(); return [ 'github_url' => $this->settings->getOrDefault('emulator_github_url', ''), 'github_repo' => $this->settings->getOrDefault('emulator_source_repo', ''), 'github_branch' => $this->settings->getOrDefault('emulator_github_branch', 'main'), 'source_repo' => $this->settings->getOrDefault('emulator_source_repo', ''), 'source_branch' => $this->settings->getOrDefault('emulator_github_branch', 'main'), 'installed_date' => $installedDate, 'installed_date_formatted' => $installedDate ? date('Y-m-d H:i:s', (int) $installedDate) : null, 'source_commit' => $sourceCommit, 'source_date' => $sourceDate, 'source_date_formatted' => $sourceDate ? date('Y-m-d H:i:s', (int) $sourceDate) : null, 'emulator_version' => $emulatorVersion, 'jar_files' => $jarFiles, 'installed_branch' => $this->settings->getOrDefault('emulator_installed_branch', null), ]; }); } public function resetInstalledDate(): void { \App\Models\Miscellaneous\WebsiteSetting::where('key', 'emulator_jar_installed_date')->delete(); \App\Models\Miscellaneous\WebsiteSetting::where('key', 'emulator_source_commit')->delete(); \App\Models\Miscellaneous\WebsiteSetting::where('key', 'emulator_source_date')->delete(); } public function clearAllLogs(): array { $cleared = []; $paths = [ storage_path('logs') => 'Laravel Logs', storage_path('logs/emulator.log') => 'Emulator Log', '/tmp/emulator-update-*' => 'Emulator Update Temp', '/tmp/nitro-switch-*' => 'Nitro Switch Logs', '/tmp/nitro_*' => 'Nitro Temp', '/var/www/Emulator/logs' => 'Emulator Folder Logs', ]; foreach ($paths as $path => $label) { try { if (str_contains($path, '*')) { Process::timeout(10)->run("rm -f {$path} 2>/dev/null || true"); $cleared[] = $label; } elseif (is_dir($path)) { Process::timeout(10)->run("find {$path} -name '*.log' -mtime +1 -delete 2>/dev/null || true"); $cleared[] = $label; } elseif (is_file($path)) { @unlink($path); $cleared[] = $label; } } catch (\Exception) { } } try { $laravelLog = storage_path('logs/laravel.log'); if (is_file($laravelLog)) { file_put_contents($laravelLog, ''); $cleared[] = 'laravel.log'; } } catch (\Exception) { } Process::timeout(10)->run("find /tmp -name 'emulator_*' -mtime +1 -delete 2>/dev/null || true"); Process::timeout(10)->run("find /tmp -name 'nitro_*' -mtime +1 -delete 2>/dev/null || true"); Process::timeout(10)->run("find /tmp -name 'deploy_*' -mtime +1 -delete 2>/dev/null || true"); return [ 'success' => true, 'cleared' => $cleared, 'message' => count($cleared) . ' log locaties geleegd', ]; } public function repairEmulator(): array { $actions = []; $errors = []; Log::info('[EmulatorUpdate] Starting repair process'); try { $status = $this->getStatus(); if (! ($status['jar_exists'] ?? false)) { $actions[] = 'JAR bestand ontbreekt - downloaden...'; $updateResult = $this->updateEmulator(); if (! $updateResult['success']) { $errors[] = 'Kon JAR niet herstellen: ' . ($updateResult['error'] ?? 'Onbekende fout'); } else { $actions[] = 'JAR bestand hersteld'; } } if (! ($status['service_running'] ?? false)) { $actions[] = 'Emulator service niet actief - starten...'; if ($this->restartEmulator()) { $actions[] = 'Emulator service gestart'; } else { $errors[] = 'Kon emulator service niet starten'; } } $sqlRepairResult = $this->sqlService->repair(); if (! empty($sqlRepairResult['actions'])) { $actions = array_merge($actions, $sqlRepairResult['actions']); } if (! empty($sqlRepairResult['errors'])) { $errors = array_merge($errors, $sqlRepairResult['errors']); } if ($errors !== []) { return [ 'success' => false, 'actions' => $actions, 'errors' => $errors, 'error' => implode('; ', $errors), ]; } return [ 'success' => true, 'actions' => $actions, 'message' => count($actions) . ' acties uitgevoerd', ]; } catch (\Exception $e) { Log::error('[EmulatorUpdate] Repair exception', ['error' => $e->getMessage()]); return [ 'success' => false, 'actions' => $actions, 'error' => $e->getMessage(), ]; } } public function diagnoseSqlUpdates(): array { return $this->sqlService->diagnose(); } public function diagnose(): array { $diagnosis = [ 'timestamp' => now()->toIso8601String(), 'checks' => [], 'issues' => [], 'recommendations' => [], ]; try { $status = $this->getStatus(); $diagnosis['checks']['jar_exists'] = $status['jar_exists'] ?? false; $diagnosis['checks']['jar_files'] = $status['jar_files'] ?? []; $diagnosis['checks']['service_running'] = $status['service_running'] ?? false; $diagnosis['checks']['source_exists'] = $status['source_exists'] ?? false; $diagnosis['checks']['emulator_db_connected'] = $status['emulator_db_connected'] ?? false; $diagnosis['checks']['is_configured'] = $this->isConfigured(); $diagnosis['checks']['update_available'] = $status['update_available'] ?? false; $sqlDiagnosis = $this->sqlService->diagnose(); $diagnosis['checks']['sql_table_exists'] = $sqlDiagnosis['table_exists'] ?? false; $diagnosis['checks']['sql_updates_applied'] = $sqlDiagnosis['applied_count'] ?? 0; $diagnosis['checks']['sql_pending'] = $sqlDiagnosis['pending_count'] ?? 0; if (! ($status['jar_exists'] ?? false)) { $diagnosis['issues'][] = 'JAR bestand ontbreekt'; $diagnosis['recommendations'][] = 'Voer emulator:update uit om de JAR te downloaden'; } if (! ($status['service_running'] ?? false)) { $diagnosis['issues'][] = 'Emulator service draait niet'; $diagnosis['recommendations'][] = 'Start de service met: sudo systemctl start ' . $this->settings->getOrDefault('emulator_service_name', 'emulator'); } if (! ($status['emulator_db_connected'] ?? false)) { $diagnosis['issues'][] = 'Emulator database niet bereikbaar'; $diagnosis['recommendations'][] = 'Controleer de database credentials in de settings'; } if (! ($status['source_exists'] ?? false) && $this->sourceService->isSourceBuildAvailable()) { $diagnosis['issues'][] = 'Source code niet gevonden'; $diagnosis['recommendations'][] = 'Voer emulator:update --rebuild uit om vanaf source te bouwen'; } if (! ($sqlDiagnosis['table_exists'] ?? false)) { $diagnosis['issues'][] = 'SQL update tabel ontbreekt'; $diagnosis['recommendations'][] = 'Reparatie zal de tabel aanmaken'; } if (($sqlDiagnosis['pending_count'] ?? 0) > 0) { $diagnosis['issues'][] = $sqlDiagnosis['pending_count'] . ' SQL updates pending'; $diagnosis['recommendations'][] = 'Voer reparatie uit om SQL updates toe te passen'; } } catch (\Exception $e) { $diagnosis['error'] = $e->getMessage(); } return $diagnosis; } }