This commit is contained in:
Ty Clifford
2026-06-14 15:25:31 -04:00
parent 2f67ae718f
commit b7eaa81501
34 changed files with 3814 additions and 2 deletions
+79
View File
@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Budget;
use PDO;
final class Support
{
public static function month(?string $month): string
{
$month = $month ?: date('Y-m');
if (!preg_match('/^\d{4}-(0[1-9]|1[0-2])$/', $month)) {
return date('Y-m');
}
return $month;
}
public static function money(float|int|string $amount, string $symbol = '$'): string
{
$value = (float) $amount;
return ($value < 0 ? '-' : '') . $symbol . number_format(abs($value), 2);
}
public static function csrf(): string
{
if (empty($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = bin2hex(random_bytes(32));
}
return (string) $_SESSION['csrf_token'];
}
public static function verifyCsrf(?string $token): void
{
if (!is_string($token) || !hash_equals(self::csrf(), $token)) {
throw new \RuntimeException('The form expired. Please try again.');
}
}
public static function flash(string $type, string $message): void
{
$_SESSION['flash'][] = ['type' => $type, 'message' => $message];
}
public static function pullFlash(): array
{
$messages = $_SESSION['flash'] ?? [];
unset($_SESSION['flash']);
return is_array($messages) ? $messages : [];
}
public static function audit(PDO $pdo, ?int $userId, string $action, ?string $entityType = null, ?int $entityId = null, array $metadata = []): void
{
$statement = $pdo->prepare(
'INSERT INTO audit_logs (user_id, action, entity_type, entity_id, metadata)
VALUES (:user_id, :action, :entity_type, :entity_id, :metadata)'
);
$statement->execute([
'user_id' => $userId,
'action' => $action,
'entity_type' => $entityType,
'entity_id' => $entityId,
'metadata' => $metadata === [] ? null : json_encode($metadata, JSON_UNESCAPED_SLASHES),
]);
}
public static function trackVisit(PDO $pdo, string $route): void
{
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
return;
}
$ip = (string) ($_SERVER['REMOTE_ADDR'] ?? 'local');
$agent = (string) ($_SERVER['HTTP_USER_AGENT'] ?? 'unknown');
$hash = hash('sha256', date('Y-m-d') . '|' . $ip . '|' . $agent);
$statement = $pdo->prepare('INSERT INTO visits (route, visitor_hash) VALUES (:route, :visitor_hash)');
$statement->execute(['route' => $route, 'visitor_hash' => $hash]);
}
}