- Add single-line class docblocks to all 59 repository classes and interfaces describing scope and responsibility - Add multi-line docblocks to key services documenting business rules: AuthService (6-step login cascade), ImportService (3-phase CSV workflow), TenantScopeService (strict/permissive modes), PermissionService (RBAC resolution + two-tier caching), UserAccountService (atomicity + audit) - Add transaction(callable) wrapper to DatabaseSessionRepository to DRY up begin/commit/rollback boilerplate Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
121 lines
4.0 KiB
PHP
121 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace MintyPHP\Repository\Mail;
|
|
|
|
use MintyPHP\DB;
|
|
use MintyPHP\Domain\Taxonomy\MailLogStatus;
|
|
use MintyPHP\Repository\Support\RepoQuery;
|
|
|
|
/** Logs outgoing emails with queued/sent/failed status transitions and provider message IDs. */
|
|
class MailLogRepository implements MailLogRepositoryInterface
|
|
{
|
|
public function create(array $data): ?int
|
|
{
|
|
$id = DB::insert(
|
|
'insert into mail_log (to_email, subject, template, status, created_at) values (?,?,?,?,NOW())',
|
|
$data['to_email'],
|
|
$data['subject'],
|
|
$data['template'] ?? null,
|
|
$data['status'] ?? MailLogStatus::Queued->value
|
|
);
|
|
return $id ? (int) $id : null;
|
|
}
|
|
|
|
public function markSent(int $id, ?string $providerMessageId = null): bool
|
|
{
|
|
$result = DB::update(
|
|
'update mail_log set status = ?, sent_at = NOW(), provider_message_id = ?, error_message = NULL where id = ?',
|
|
MailLogStatus::Sent->value,
|
|
$providerMessageId,
|
|
(string) $id
|
|
);
|
|
return $result !== false;
|
|
}
|
|
|
|
public function markFailed(int $id, string $errorMessage): bool
|
|
{
|
|
$result = DB::update(
|
|
'update mail_log set status = ?, error_message = ? where id = ?',
|
|
MailLogStatus::Failed->value,
|
|
$errorMessage,
|
|
(string) $id
|
|
);
|
|
return $result !== false;
|
|
}
|
|
|
|
public function listPaged(array $options): array
|
|
{
|
|
$search = trim((string) ($options['search'] ?? ''));
|
|
$status = MailLogStatus::tryNormalize((string) ($options['status'] ?? ''))?->value ?? '';
|
|
$createdFrom = trim((string) ($options['created_from'] ?? ''));
|
|
$createdTo = trim((string) ($options['created_to'] ?? ''));
|
|
|
|
$allowedOrder = ['id', 'created_at', 'sent_at', 'to_email', 'subject', 'status'];
|
|
[$limit, $offset] = RepoQuery::sanitizeLimitOffset($options);
|
|
[$order, $dir] = RepoQuery::sanitizeOrder($options, $allowedOrder, 'created_at', 'desc');
|
|
|
|
$where = [];
|
|
$params = [];
|
|
RepoQuery::addLikeFilter($where, $params, ['to_email', 'subject', 'template'], $search);
|
|
RepoQuery::addEqualsFilter($where, $params, $status, 'status = ?');
|
|
if ($createdFrom !== '') {
|
|
$where[] = 'created_at >= ?';
|
|
$params[] = $createdFrom . ' 00:00:00';
|
|
}
|
|
if ($createdTo !== '') {
|
|
$where[] = 'created_at <= ?';
|
|
$params[] = $createdTo . ' 23:59:59';
|
|
}
|
|
|
|
$whereSql = $where ? (' where ' . implode(' and ', $where)) : '';
|
|
$count = DB::selectValue('select count(*) from mail_log' . $whereSql, ...$params);
|
|
$total = $count ? (int) $count : 0;
|
|
|
|
$query = 'select id, to_email, subject, template, status, created_at, sent_at, error_message, provider_message_id from mail_log' .
|
|
$whereSql .
|
|
sprintf(' order by `%s` %s limit ? offset ?', $order, $dir);
|
|
|
|
$queryParams = array_merge($params, [(string) $limit, (string) $offset]);
|
|
$rows = call_user_func_array(['MintyPHP\\DB', 'select'], array_merge([$query], $queryParams));
|
|
|
|
return [
|
|
'total' => $total,
|
|
'rows' => $this->unwrapList($rows),
|
|
];
|
|
}
|
|
|
|
public function find(int $id): ?array
|
|
{
|
|
$row = DB::selectOne(
|
|
'select id, to_email, subject, template, status, created_at, sent_at, error_message, provider_message_id from mail_log where id = ? limit 1',
|
|
(string) $id
|
|
);
|
|
return $this->unwrap($row);
|
|
}
|
|
|
|
private function unwrap(?array $row): ?array
|
|
{
|
|
if (!$row) {
|
|
return null;
|
|
}
|
|
return $row['mail_log'] ?? null;
|
|
}
|
|
|
|
private function unwrapList(mixed $rows): array
|
|
{
|
|
if (!is_array($rows)) {
|
|
return [];
|
|
}
|
|
|
|
$list = [];
|
|
foreach ($rows as $row) {
|
|
$mailLog = $row['mail_log'] ?? null;
|
|
if (is_array($mailLog)) {
|
|
$list[] = $mailLog;
|
|
}
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
}
|