Files
global-autoresponder/exec/lib/DirectAdminVacationSyncService.php
T
2026-06-02 20:51:57 +02:00

107 lines
3.8 KiB
PHP

<?php
declare(strict_types=1);
final class DirectAdminVacationSyncService
{
public function __construct(
private RuleRepository $rules,
private DirectAdminSyncRepository $sync,
private MailboxDirectory $mailboxes,
private DirectAdminVacationApi $api
) {
}
public function syncUser(string $username): void
{
$rules = $this->rulesById($username);
foreach ($this->sync->allRuleEntries($username) as $ruleId => $entries) {
if (!isset($rules[$ruleId]) || empty($rules[$ruleId]['enabled'])) {
$this->deleteEntries($username, $ruleId, $entries);
}
}
foreach ($rules as $ruleId => $rule) {
if (empty($rule['enabled'])) {
continue;
}
$this->syncRule($username, $ruleId, $rule);
}
}
/** @return array<string,array<string,mixed>> */
private function rulesById(string $username): array
{
$out = [];
foreach ($this->rules->all($username) as $rule) {
$id = (string)($rule['id'] ?? '');
if ($id !== '') {
$out[$id] = $rule;
}
}
return $out;
}
/** @param array<string,mixed> $rule */
private function syncRule(string $username, string $ruleId, array $rule): void
{
$existing = $this->indexedEntries($this->sync->entriesForRule($username, $ruleId));
$targets = $this->targetMailboxes($username, $rule);
$next = [];
foreach ($targets as $mailbox) {
$email = strtolower((string)$mailbox['email']);
$this->api->saveVacation($username, $email, $rule, isset($existing[$email]));
$next[] = [
'rule_id' => $ruleId,
'domain' => (string)$mailbox['domain'],
'mailbox' => (string)$mailbox['mailbox'],
'email' => $email,
'api_key' => $email,
'last_sync_at' => time(),
];
unset($existing[$email]);
}
foreach ($existing as $entry) {
$this->api->deleteVacation($username, (string)$entry['email']);
}
$this->sync->replaceRuleEntries($username, $ruleId, $next);
}
/** @param array<int,array<string,mixed>> $entries */
private function deleteEntries(string $username, string $ruleId, array $entries): void
{
foreach ($entries as $entry) {
$email = (string)($entry['email'] ?? $entry['api_key'] ?? '');
if ($email !== '') {
$this->api->deleteVacation($username, $email);
}
}
$this->sync->deleteRuleEntries($username, $ruleId);
}
/** @param array<int,array<string,mixed>> $entries @return array<string,array<string,mixed>> */
private function indexedEntries(array $entries): array
{
$out = [];
foreach ($entries as $entry) {
$email = strtolower((string)($entry['email'] ?? $entry['api_key'] ?? ''));
if ($email !== '') {
$out[$email] = $entry + ['email' => $email];
}
}
return $out;
}
/** @param array<string,mixed> $rule @return array<int,array{domain:string,mailbox:string,email:string}> */
private function targetMailboxes(string $username, array $rule): array
{
if (empty($rule['dynamic_scope']) && isset($rule['mailbox_snapshot']) && is_array($rule['mailbox_snapshot'])) {
return array_values(array_filter($rule['mailbox_snapshot'], static function (mixed $mailbox): bool {
return is_array($mailbox)
&& isset($mailbox['domain'], $mailbox['mailbox'], $mailbox['email'])
&& filter_var((string)$mailbox['email'], FILTER_VALIDATE_EMAIL);
}));
}
return $this->mailboxes->mailboxesForUser($username);
}
}