. // (team.update, trash.purge, auth.login_failed, export.membership_leads…). require_once __DIR__ . '/../shared/platform-tools/functions_audit.php'; function audit(string $action, array $d = []): void { platform_audit($GLOBALS['pdo'] ?? null, $action, $d); } // Email mascarado para registos de falhas: permite ver padrões (o mesmo // endereço atacado muitas vezes) sem guardar o endereço de quem se enganou. function audit_mask_email(string $email): string { $email = strtolower(trim($email)); if (!str_contains($email, '@')) return $email === '' ? '' : mb_substr($email, 0, 1) . '…'; [$u, $d] = explode('@', $email, 2); return mb_substr($u, 0, 1) . '…@' . $d; } // ─── Escritas de conteúdo ──────────────────────────────────────────────────── // Os modelos (config/functions_*.php) chamam audit_row() antes de alterar e // audit_change() depois: o registo leva o antes/depois campo a campo // (platform_audit_diff) ou, numa criação, os campos criados. Tabela e chave vêm // do código, nunca do pedido, e ainda assim são validadas. function audit_row(PDO $pdo, string $table, string $pk, int $id): ?array { if (!preg_match('/^[A-Za-z0-9_]+$/', $table) || !preg_match('/^[A-Za-z0-9_]+$/', $pk)) return null; try { $st = $pdo->prepare("SELECT * FROM `{$table}` WHERE `{$pk}` = ? LIMIT 1"); $st->execute([$id]); $row = $st->fetch(PDO::FETCH_ASSOC); return $row ?: null; } catch (Throwable $e) { return null; } } function audit_change(PDO $pdo, string $entity, string $table, string $pk, int $id, string $verb, ?array $before = null, string $labelCol = 'name'): void { if (!function_exists('platform_audit') || $id < 1) return; $after = audit_row($pdo, $table, $pk, $id) ?? []; $changes = $before !== null ? platform_audit_diff($before, $after, ['updated_at', 'created_at', 'updated_by']) : platform_audit_created(array_diff_key($after, array_flip(['created_at', 'updated_at']))); if ($verb !== 'create' && $before !== null && !$changes) return; // gravou sem mudar nada platform_audit($pdo, $entity . '.' . $verb, [ 'target_type' => $entity, 'target_id' => $id, 'target_label' => (string) ($after[$labelCol] ?? $before[$labelCol] ?? ''), 'changes' => $changes, ]); }