You've already forked Atomcms-edit
f5666c104d
- Add DiagnosticRunner integration to Commandocentrum for system health display - Refactor EmulatorUpdateService from 2524 lines to 395 lines (facade pattern) - Extract EmulatorStatusService, EmulatorJarService, EmulatorSourceService - Extract EmulatorBuildService, EmulatorSqlService, EmulatorBackupService - Add shared EmulatorConfiguration trait for dependency injection - Preserve backward compatibility on all public methods
396 lines
15 KiB
PHP
Executable File
396 lines
15 KiB
PHP
Executable File
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Services\Emulator\EmulatorBackupService;
|
|
use App\Services\Emulator\EmulatorBuildService;
|
|
use App\Services\Emulator\EmulatorJarService;
|
|
use App\Services\Emulator\EmulatorSourceService;
|
|
use App\Services\Emulator\EmulatorSqlService;
|
|
use App\Services\Emulator\EmulatorStatusService;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Process;
|
|
|
|
class EmulatorUpdateService
|
|
{
|
|
private readonly EmulatorStatusService $statusService;
|
|
private readonly EmulatorJarService $jarService;
|
|
private readonly EmulatorSourceService $sourceService;
|
|
private readonly EmulatorBuildService $buildService;
|
|
private readonly EmulatorSqlService $sqlService;
|
|
private readonly EmulatorBackupService $backupService;
|
|
private readonly SettingsService $settings;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->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 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;
|
|
}
|
|
}
|