Files
orderPRO/src/Modules/Automation/AutomationExecutionLogRepository.php
2026-03-28 15:04:35 +01:00

210 lines
6.3 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Modules\Automation;
use PDO;
final class AutomationExecutionLogRepository
{
public function __construct(private readonly PDO $pdo)
{
}
/**
* @param array<string, mixed> $data
*/
public function create(array $data): void
{
$statement = $this->pdo->prepare(
'INSERT INTO automation_execution_logs (
event_type,
rule_id,
rule_name,
order_id,
execution_status,
result_message,
context_json,
executed_at,
created_at
) VALUES (
:event_type,
:rule_id,
:rule_name,
:order_id,
:execution_status,
:result_message,
:context_json,
:executed_at,
NOW()
)'
);
$statement->execute([
'event_type' => (string) ($data['event_type'] ?? ''),
'rule_id' => isset($data['rule_id']) ? (int) $data['rule_id'] : null,
'rule_name' => (string) ($data['rule_name'] ?? ''),
'order_id' => (int) ($data['order_id'] ?? 0),
'execution_status' => (string) ($data['execution_status'] ?? ''),
'result_message' => $this->trimNullable((string) ($data['result_message'] ?? '')),
'context_json' => $this->encodeJson($data['context'] ?? null),
'executed_at' => (string) ($data['executed_at'] ?? date('Y-m-d H:i:s')),
]);
}
/**
* @param array<string, mixed> $filters
* @return list<array<string, mixed>>
*/
public function paginate(array $filters, int $page, int $perPage): array
{
$safePage = max(1, $page);
$safePerPage = max(1, min(100, $perPage));
$offset = ($safePage - 1) * $safePerPage;
['where' => $whereSql, 'params' => $params] = $this->buildFilters($filters);
$sql = 'SELECT id, event_type, rule_id, rule_name, order_id, execution_status, result_message, context_json, executed_at
FROM automation_execution_logs
' . $whereSql . '
ORDER BY executed_at DESC, id DESC
LIMIT :limit OFFSET :offset';
$statement = $this->pdo->prepare($sql);
foreach ($params as $key => $value) {
$statement->bindValue(':' . $key, $value);
}
$statement->bindValue(':limit', $safePerPage, PDO::PARAM_INT);
$statement->bindValue(':offset', $offset, PDO::PARAM_INT);
$statement->execute();
$rows = $statement->fetchAll(PDO::FETCH_ASSOC);
if (!is_array($rows)) {
return [];
}
foreach ($rows as &$row) {
$decoded = json_decode((string) ($row['context_json'] ?? ''), true);
$row['context_json'] = is_array($decoded) ? $decoded : null;
}
unset($row);
return $rows;
}
/**
* @param array<string, mixed> $filters
*/
public function count(array $filters): int
{
['where' => $whereSql, 'params' => $params] = $this->buildFilters($filters);
$statement = $this->pdo->prepare(
'SELECT COUNT(*) FROM automation_execution_logs ' . $whereSql
);
$statement->execute($params);
$value = $statement->fetchColumn();
return max(0, (int) $value);
}
public function purgeOlderThanDays(int $days): int
{
$safeDays = max(1, min(3650, $days));
$statement = $this->pdo->prepare(
'DELETE FROM automation_execution_logs WHERE executed_at < DATE_SUB(NOW(), INTERVAL :days DAY)'
);
$statement->bindValue(':days', $safeDays, PDO::PARAM_INT);
$statement->execute();
return $statement->rowCount();
}
/**
* @return list<string>
*/
public function listEventTypes(): array
{
$statement = $this->pdo->query(
'SELECT DISTINCT event_type FROM automation_execution_logs ORDER BY event_type ASC'
);
$rows = $statement->fetchAll(PDO::FETCH_COLUMN);
if (!is_array($rows)) {
return [];
}
return array_values(array_filter(array_map('strval', $rows), static fn (string $value): bool => $value !== ''));
}
/**
* @param array<string, mixed> $filters
* @return array{where:string,params:array<string,mixed>}
*/
private function buildFilters(array $filters): array
{
$where = [];
$params = [];
$eventType = trim((string) ($filters['event_type'] ?? ''));
if ($eventType !== '') {
$where[] = 'event_type = :event_type';
$params['event_type'] = $eventType;
}
$executionStatus = trim((string) ($filters['execution_status'] ?? ''));
if ($executionStatus !== '') {
$where[] = 'execution_status = :execution_status';
$params['execution_status'] = $executionStatus;
}
$ruleId = (int) ($filters['rule_id'] ?? 0);
if ($ruleId > 0) {
$where[] = 'rule_id = :rule_id';
$params['rule_id'] = $ruleId;
}
$orderId = (int) ($filters['order_id'] ?? 0);
if ($orderId > 0) {
$where[] = 'order_id = :order_id';
$params['order_id'] = $orderId;
}
$dateFrom = trim((string) ($filters['date_from'] ?? ''));
if ($dateFrom !== '') {
$where[] = 'DATE(executed_at) >= :date_from';
$params['date_from'] = $dateFrom;
}
$dateTo = trim((string) ($filters['date_to'] ?? ''));
if ($dateTo !== '') {
$where[] = 'DATE(executed_at) <= :date_to';
$params['date_to'] = $dateTo;
}
if ($where === []) {
return ['where' => '', 'params' => []];
}
return ['where' => 'WHERE ' . implode(' AND ', $where), 'params' => $params];
}
private function trimNullable(string $value): ?string
{
$trimmed = trim($value);
if ($trimmed === '') {
return null;
}
return mb_substr($trimmed, 0, 500);
}
private function encodeJson(mixed $data): ?string
{
if (!is_array($data) || $data === []) {
return null;
}
return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?: null;
}
}