mailwolt/app/Livewire/Ui/System/BackupStatusCard.php

171 lines
5.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Livewire\Ui\System;
use Carbon\CarbonImmutable;
use Illuminate\Support\Str;
use Livewire\Component;
class BackupStatusCard extends Component
{
public ?string $lastAt = null; // formatierte Zeit
public ?string $lastSize = null; // human readable
public ?string $lastDuration = null; // human readable
public ?bool $ok = null;
// Laufzeit/Progress
public string $state = 'idle'; // idle|running|done|error
public string $step = ''; // aktueller Schritt
public array $steps = [
'mysqldump' => 'Datenbank sichern',
'maildir' => 'Maildir kopieren',
'app' => 'App sichern',
'configs' => 'Configs sichern',
'archive' => 'Archiv erstellen',
'compress' => 'Komprimieren',
'retention' => 'Aufräumen',
'finish' => 'Abschluss',
];
protected string $statusFile = '/var/lib/mailwolt/backup.status';
public function mount(): void
{
$this->load(true);
}
public function render()
{
return view('livewire.ui.system.backup-status-card');
}
public function refresh(): void
{
$this->load(true);
}
public function runNow(): void
{
@shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-backup >/dev/null 2>&1 &');
// Sofort in "running" gehen Poll übernimmt dann
$this->state = 'running';
$this->step = 'mysqldump';
}
public function load(bool $force = false): void
{
$raw = $this->readStatus();
$this->state = $raw['state'] ?? 'idle';
$this->step = $raw['step'] ?? '';
// Datum/Zeit hübsch
if (!empty($raw['time'])) {
$this->lastAt = $this->fmtTime($raw['time']);
} else {
$this->lastAt = null;
}
// Größe/Dauer hübsch
$bytes = isset($raw['size_bytes']) ? (int)$raw['size_bytes'] : null;
$secs = isset($raw['dur_seconds']) ? (int)$raw['dur_seconds'] : null;
$this->lastSize = $bytes !== null ? $this->humanBytes($bytes) : null;
$this->lastDuration = $secs !== null ? $this->humanDuration($secs) : null;
$this->ok = isset($raw['ok']) ? ((string)$raw['ok'] === '1') : null;
}
protected function readStatus(): array
{
if (!is_file($this->statusFile)) return [];
$out = [];
foreach (@file($this->statusFile, FILE_IGNORE_NEW_LINES) ?: [] as $ln) {
if (!str_contains($ln, '=')) continue;
[$k, $v] = array_map('trim', explode('=', $ln, 2));
$out[$k] = $v;
}
// Backward compatibility (alte Keys)
if (isset($out['size']) && !isset($out['size_bytes'])) {
$out['size_bytes'] = (int)$out['size'];
}
if (isset($out['dur']) && !isset($out['dur_seconds'])) {
$out['dur_seconds'] = (int)$out['dur'];
}
return $out;
}
protected function fmtTime(string $iso): string
{
try {
$tz = config('app.timezone', 'UTC');
// ISO aus Script ist idealerweise UTC (Z)
$dt = CarbonImmutable::parse($iso)->timezone($tz);
// z.B. 27.10.2025, 16:48:02 (CET)
return $dt->isoFormat('L, LTS') . ' ' . $dt->format('T');
} catch (\Throwable) {
return $iso;
}
}
protected function humanBytes(int $bytes): string
{
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return number_format($bytes, $i === 0 ? 0 : 1, ',', '.') . ' ' . $units[$i];
}
protected function humanDuration(int $secs): string
{
if ($secs < 60) return $secs . ' s';
$m = intdiv($secs, 60);
$s = $secs % 60;
if ($m < 60) return sprintf('%d min %02d s', $m, $s);
$h = intdiv($m, 60);
$m = $m % 60;
return sprintf('%d h %02d min', $h, $m);
}
}
//
//namespace App\Livewire\Ui\System;
//
//use Livewire\Component;
//
//class BackupStatusCard extends Component
//{
// public ?string $lastAt = null;
// public ?string $lastSize = null;
// public ?string $lastDuration = null;
// public ?bool $ok = null;
//
// public function mount(): void { $this->load(); }
// public function render() { return view('livewire.ui.system.backup-status-card'); }
// public function refresh(): void { $this->load(true); }
//
// public function runNow(): void
// {
// @shell_exec('nohup sudo -n /usr/local/sbin/mailwolt-backup >/dev/null 2>&1 &');
//// $this->dispatch('toast', type:'info', title:'Backup gestartet');
// }
//
// protected function load(bool $force=false): void
// {
// // Example: parse a tiny status file your backup script writes.
// $f = '/var/lib/mailwolt/backup.status';
// if (is_file($f)) {
// $lines = @file($f, FILE_IGNORE_NEW_LINES) ?: [];
// foreach ($lines as $ln) {
// if (str_starts_with($ln,'time=')) $this->lastAt = substr($ln,5);
// if (str_starts_with($ln,'size=')) $this->lastSize = substr($ln,5);
// if (str_starts_with($ln,'dur=')) $this->lastDuration = substr($ln,4);
// if (str_starts_with($ln,'ok=')) $this->ok = (substr($ln,3) === '1');
// }
// }
// }
//}