feat: complete production backend integration
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user