mailwolt/app/Livewire/Ui/Mail/MailboxList.php

469 lines
18 KiB
PHP

<?php
namespace App\Livewire\Ui\Mail;
use App\Models\Domain;
use App\Models\Setting;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Str;
use Livewire\Attributes\On;
use Livewire\Component;
class MailboxList extends Component
{
public string $search = '';
public bool $showSystemCard = false;
#[On('mailbox:updated')]
#[On('mailbox:deleted')]
#[On('mailbox:created')]
public function refreshMailboxList(): void
{
$this->dispatch('$refresh');
}
#[On('focus:domain')]
public function focusDomain(int $id): void
{
// z. B. Domain nach oben holen / scrollen / highlighten
// oder direkt den "+ Postfach" Dialog:
// $this->openMailboxCreate($id);
}
#[On('focus:user')]
public function focusUser(int $id): void
{
// später: Benutzerseite / Filter setzen ...
}
public function openMailboxCreate(int $domainId): void
{
$this->dispatch('openModal', component: 'ui.mail.modal.mailbox-create-modal', arguments: [
'domainId' => $domainId,
]);
}
public function openMailboxEdit(int $domainId): void
{
// $domainId == mailbox_id
$this->dispatch('openModal', component: 'ui.mail.modal.mailbox-edit-modal', arguments: [
$domainId, // <— nur der Wert, kein Key!
]);
}
public function openMailboxDelete(int $domainId): void
{
$this->dispatch('openModal', component: 'ui.mail.modal.mailbox-delete-modal', arguments: [
$domainId, // <— nur der Wert, kein Key!
]);
}
public function updateMailboxStats()
{
// führe Artisan-Command direkt aus
Artisan::call('mail:update-stats');
$this->dispatch('$refresh');
$this->dispatch('toast',
type: 'done',
badge: 'Mailbox',
title: 'Mailbox aktualisiert',
text: 'Die Mailbox-Statistiken wurden aktualisiert.',
duration: 6000,
);
}
public function updateMailboxStatsOne(string $email)
{
Artisan::call('mail:update-stats', ['--user' => $email]);
$this->dispatch('$refresh');
$this->dispatch('toast',
type: 'done',
badge: 'Mailbox',
title: 'Mailbox aktualisiert',
text: 'Die Mailbox-Statistiken wurden aktualisiert.',
duration: 6000
);
}
public function render()
{
$system = Domain::query()->where('is_system', true)->first();
$term = trim($this->search);
$hasTerm = $term !== '';
$needle = '%'.str_replace(['%','_'], ['\%','\_'], $term).'%'; // LIKE-sicher
$domains = Domain::query()
->when($system, fn ($q) => $q->whereKeyNot($system->id))
// Domain selbst ODER MailUser müssen matchen
->when($hasTerm, function ($q) use ($needle) {
$q->where(function ($w) use ($needle) {
$w->where('domain', 'like', $needle)
->orWhereHas('mailUsers', fn($u) => $u->where('localpart', 'like', $needle));
});
})
->withCount(['mailUsers'])
// Relationen zunächst ggf. gefiltert laden
->with([
'mailUsers' => function ($q) use ($hasTerm, $needle) {
if ($hasTerm) $q->where('localpart', 'like', $needle);
$q->orderBy('localpart');
},
])
->orderBy('domain')
->get();
// Wenn der Domainname selbst matched → alle Mailboxen/Aliasse vollständig nachladen
if ($hasTerm) {
$lower = Str::lower($term);
foreach ($domains as $d) {
if (Str::contains(Str::lower($d->domain), $lower)) {
$d->setRelation('mailUsers', $d->mailUsers()->orderBy('localpart')->get());
$d->setRelation('mailAliases', $d->mailAliases()->orderBy('local')->get());
}
}
}
// Vorbereitung für Blade
foreach ($domains as $d) {
$prepared = [];
$domainActive = (bool)($d->is_active ?? true);
foreach ($d->mailUsers as $u) {
$email = trim($u->email ?? '') !== ''
? $u->email
: ($u->localpart !== '' ? ($u->localpart.'@'.$d->domain) : null);
$stats = $email ? Setting::get("mailbox.$email") : null;
$usedBytes = is_array($stats) && isset($stats['used_bytes']) ? (int)$stats['used_bytes'] : (int)($u->used_bytes ?? 0);
$messageCount = is_array($stats) && isset($stats['message_count']) ? (int)$stats['message_count'] : (int)($u->message_count ?? 0);
$usedMB = (int) round($usedBytes / 1024 / 1024);
$quota = (int)($u->quota_mb ?? 0);
$usage = $quota > 0 ? min(100, (int) round($usedMB / max(1, $quota) * 100)) : 0;
$mailboxActive = (bool)($u->is_active ?? true);
$effective = $domainActive && $mailboxActive;
$reason = null;
if (!$effective) {
$reason = !$domainActive ? 'Domain inaktiv'
: (!$mailboxActive ? 'Postfach inaktiv' : null);
}
$prepared[] = [
'id' => $u->id,
'localpart' => (string)$u->localpart,
'quota_mb' => $quota,
'usage_percent' => $usage,
'used_mb' => $usedMB, // MiB fürs UI
'message_count' => $messageCount,
'is_active' => $mailboxActive,
'is_effective_active' => $effective,
'inactive_reason' => $reason,
];
}
$d->prepared_mailboxes = $prepared;
}
return view('livewire.ui.mail.mailbox-list', [
'domains' => $domains,
'system' => $this->showSystemCard ? $system : null,
]);
}
// public function render()
// {
// $system = Domain::query()->where('is_system', true)->first();
// $term = trim($this->search);
// $hasTerm = $term !== '';
// $needle = '%'.str_replace(['%','_'], ['\%','\_'], $term).'%'; // LIKE-sicher
//
// $domains = Domain::query()
// ->when($system, fn ($q) => $q->whereKeyNot($system->id))
//
// // Domain selbst ODER MailUser/ Aliasse müssen matchen
// ->when($hasTerm, function ($q) use ($needle) {
// $q->where(function ($w) use ($needle) {
// $w->where('domain', 'like', $needle)
// ->orWhereHas('mailUsers', fn($u) => $u->where('localpart', 'like', $needle));
// });
// })
//
// ->withCount(['mailUsers'])
//
// // Beziehungen zunächst gefiltert laden (damit "test" nur passende Mailboxen zeigt)
// ->with([
// 'mailUsers' => function ($q) use ($hasTerm, $needle) {
// if ($hasTerm) $q->where('localpart', 'like', $needle);
// $q->orderBy('localpart');
// },
// ])
//
// ->orderBy('domain')
// ->get();
//
// // Domains, deren NAME den Suchbegriff trifft → ALLE Mailboxen/Aliasse zeigen
// if ($hasTerm) {
// $lower = Str::lower($term);
// foreach ($domains as $d) {
// if (Str::contains(Str::lower($d->domain), $lower)) {
// // volle Relationen nachladen (überschreibt die gefilterten)
// $d->setRelation('mailUsers', $d->mailUsers()->orderBy('localpart')->get());
// $d->setRelation('mailAliases', $d->mailAliases()->orderBy('local')->get());
// }
// }
// }
//
// // Vorbereitung für Blade (unverändert, arbeitet auf den ggf. gefilterten Relationen)
// foreach ($domains as $d) {
// $prepared = [];
// $domainActive = (bool)($d->is_active ?? true);
//
// foreach ($d->mailUsers as $u) {
// $stats = Setting::get("mailbox.{$u->email}");
// $usedBytes = $stats['used_bytes'] ?? ($u->used_bytes ?? 0);
// $messageCount = $stats['message_count'] ?? ($u->message_count ?? 0);
// $usedMB = (int) round(($usedBytes) / 1024 / 1024);
// $quota = (int)($u->quota_mb ?? 0);
// $usage = $quota > 0 ? min(100, (int) round($usedMB / max(1,$quota) * 100)) : 0;
//
//
//// $quota = (int)($u->quota_mb ?? 0);
//// $used = (int)($u->used_mb ?? 0);
//// $usage = $quota > 0 ? min(100, (int)round($used / max(1, $quota) * 100)) : 0;
//
// $mailboxActive = (bool)($u->is_active ?? true);
// $effective = $domainActive && $mailboxActive;
//
// $reason = null;
// if (!$effective) {
// $reason = !$domainActive ? 'Domain inaktiv'
// : (!$mailboxActive ? 'Postfach inaktiv' : null);
// }
//
// $prepared[] = [
// 'id' => $u->id,
// 'localpart' => (string)$u->localpart,
// 'quota_mb' => $quota,
// 'usage_percent' => $usage,
// 'used_mb' => $usedMB,
// 'message_count' => $messageCount,
// 'is_active' => $mailboxActive,
// 'is_effective_active' => $effective,
// 'inactive_reason' => $reason,
// ];
// }
//
// // für Blade
// $d->prepared_mailboxes = $prepared;
// }
//
// return view('livewire.ui.mail.mailbox-list', [
// 'domains' => $domains,
// 'system' => $this->showSystemCard ? $system : null,
// ]);
// }
// public function render()
// {
// $system = Domain::query()->where('is_system', true)->first();
// $term = trim($this->search);
//
// $domains = Domain::query()
// ->when($system, fn ($q) => $q->where('id', '!=', $system->id))
// ->withCount(['mailUsers','mailAliases'])
// ->with([
// 'mailUsers' => fn ($q) => $q->orderBy('localpart'),
// 'mailAliases' => fn ($q) => $q->orderBy('local'),
// ])
// ->when($term !== '', function ($q) use ($term) {
// $q->where(function ($w) use ($term) {
// $w->where('domain', 'like', "%{$term}%")
// ->orWhereHas('mailUsers', fn($u) =>
// $u->where('localpart', 'like', "%{$term}%")
// );
// });
// })
// ->orderBy('domain')
// ->get();
//
// // Vorbereitung für Blade (unverändert)
// foreach ($domains as $d) {
// $prepared = [];
// $domainActive = (bool)($d->is_active ?? true);
//
// foreach ($d->mailUsers as $u) {
// $quota = (int) ($u->quota_mb ?? 0);
// $used = (int) ($u->used_mb ?? 0);
// $usage = $quota > 0 ? min(100, (int) round($used / max(1,$quota) * 100)) : 0;
//
// $mailboxActive = (bool)($u->is_active ?? true);
// $effective = $domainActive && $mailboxActive;
//
// $reason = null;
// if (!$effective) {
// $reason = !$domainActive ? 'Domain inaktiv'
// : (!$mailboxActive ? 'Postfach inaktiv' : null);
// }
//
// $prepared[] = [
// 'id' => $u->id,
// 'localpart' => (string) $u->localpart,
// 'quota_mb' => $quota,
// 'used_mb' => $used,
// 'usage_percent' => $usage,
// 'message_count' => (int) ($u->message_count ?? $u->mails_count ?? 0),
// 'is_active' => $mailboxActive,
// 'is_effective_active' => $effective,
// 'inactive_reason' => $reason,
// ];
// }
//
// $d->prepared_mailboxes = $prepared;
// }
//
// return view('livewire.ui.mail.mailbox-list', [
// 'domains' => $domains,
// 'system' => $this->showSystemCard ? $system : null,
// ]);
// }
// public function render()
// {
// $system = Domain::query()->where('is_system', true)->first();
//
// $term = trim($this->search);
//
// $domains = Domain::query()
// ->when($system, fn ($q) => $q->where('id', '!=', $system->id))
// ->withCount(['mailUsers','mailAliases'])
// ->with([
// 'mailUsers' => fn ($q) => $q->orderBy('localpart'),
// 'mailAliases' => fn ($q) => $q->orderBy('source'),
// ])
// ->when($term !== '', function ($q) use ($term) {
// $q->where(function ($w) use ($term) {
// $w->where('domain', 'like', "%{$term}%")
// ->orWhereHas('mailUsers', fn($u) =>
// $u->where('localpart', 'like', "%{$term}%")
// );
// });
// })
// ->orderBy('domain')
// ->get();
//
// // Für das Blade vorbereiten (ohne Relations zu mutieren)
// foreach ($domains as $d) {
// $prepared = [];
// $domainActive = (bool)($d->is_active ?? true);
//
// foreach ($d->mailUsers as $u) {
// $quota = (int) ($u->quota_mb ?? 0);
// $used = (int) ($u->used_mb ?? 0);
// $usage = $quota > 0 ? min(100, (int) round($used / max(1,$quota) * 100)) : 0;
//
// $mailboxActive = (bool)($u->is_active ?? true);
// $effective = $domainActive && $mailboxActive;
//
// $reason = null;
// if (!$effective) {
// $reason = !$domainActive ? 'Domain inaktiv'
// : (!$mailboxActive ? 'Postfach inaktiv' : null);
// }
//
// $prepared[] = [
// 'id' => $u->id,
// 'localpart' => (string) $u->localpart,
// 'quota_mb' => $quota,
// 'used_mb' => $used,
// 'usage_percent' => $usage,
// 'message_count' => (int) ($u->message_count ?? $u->mails_count ?? 0),
// 'is_active' => $mailboxActive, // ursprünglicher Flag (falls du ihn brauchst)
// 'is_effective_active' => $effective, // ← NEU: Domain & Mailbox aktiv?
// 'inactive_reason' => $reason, // ← NEU: warum gesperrt
// ];
// }
//
// $d->prepared_mailboxes = $prepared;
// }
//
// return view('livewire.ui.mail.mailbox-list', [
// 'domains' => $domains,
// 'system' => $this->showSystemCard ? $system : null,
// ]);
// }
}
//namespace App\Livewire\Ui\Mail;
//
//use App\Models\Domain;
//use Livewire\Component;
//
//class MailboxList extends Component
//{
// public string $search = '';
// public bool $showSystemCard = false; // optional: Info-Karte anzeigen
//
// public function openMailboxCreate(int $domainId): void
// {
// $this->dispatch('openModal', component: 'ui.mail.modal.mailbox-create-modal', arguments: [
// 'domainId' => $domainId,
// ]);
// }
//
// public function render()
// {
// // System-Domain direkt aus der DB (bool Spalte: is_system)
// $system = Domain::query()
// ->where('is_system', true) // <-- deine DB-Flag-Spalte
// ->first();
//
// // Benutzer-Domains (ohne System-Domain)
// $domains = Domain::query()
// ->when($system, fn($q) => $q->where('id', '!=', $system->id))
// ->withCount(['mailUsers', 'mailAliases'])
// ->with([
// 'mailUsers' => fn($q) => $q->orderBy('localpart'),
// 'mailAliases' => fn($q) => $q->orderBy('source'),
// ])
// ->when($this->search !== '', function ($q) {
// $q->where('domain', 'like', "%{$this->search}%")
// ->orWhereHas('mailUsers', fn($qq) => $qq->where('localpart', 'like', "%{$this->search}%"));
// })
// ->orderBy('domain') // falls bei dir anders: exakt die vorhandene Spalte eintragen
// ->get();
//
// // Alle Mailboxen vorbereiten (keine Logik im Blade)
// $domains->each(function ($domain) {
// $domain->mailUsers->transform(function ($u) use ($domain) {
// $quota = (int)($u->quota_mb ?? 0);
// $used = (int)($u->used_mb ?? 0);
// $usage = $quota > 0 ? min(100, round(($used / max(1, $quota)) * 100)) : 0;
//
// // neue Properties für das Blade
// $u->email = $u->localpart ? "{$u->localpart}@{$domain->domain}" : '—';
// $u->quota_mb = $quota;
// $u->used_mb = $used;
// $u->usage_percent = $usage;
// $u->message_count = (int)($u->message_count ?? $u->mails_count ?? 0);
//
// return $u;
// });
// });
//
//
// return view('livewire.ui.mail.mailbox-list', [
// 'domains' => $domains,
// 'system' => $this->showSystemCard ? $system : null, // read-only Karte optional
// ]);
// }
//}