Files
fotospiel-app/app/Services/Analytics/JoinTokenAnalyticsRecorder.php
Codex Agent fa33e7cbcf Fix Event & EventType resource issues and apply formatting
- Fix EventType deletion error handling (constraint violations)
- Fix Event update error (package_id column missing)
- Fix Event Type dropdown options (JSON display issue)
- Fix EventPackagesRelationManager query error
- Add missing translations for deletion errors
- Apply Pint formatting
2026-01-21 10:34:06 +01:00

111 lines
3.2 KiB
PHP

<?php
namespace App\Services\Analytics;
use App\Models\EventJoinToken;
use App\Models\EventJoinTokenEvent;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
class JoinTokenAnalyticsRecorder
{
public function record(
?EventJoinToken $joinToken,
string $eventType,
Request $request,
array $context = [],
?string $providedToken = null,
?int $httpStatus = null
): void {
try {
EventJoinTokenEvent::create($this->buildPayload(
$joinToken,
$eventType,
$request,
$context,
$providedToken,
$httpStatus
));
} catch (\Throwable $exception) {
// Never block the main request if analytics fails
report($exception);
}
}
private function buildPayload(
?EventJoinToken $joinToken,
string $eventType,
Request $request,
array $context,
?string $providedToken,
?int $httpStatus
): array {
$route = $request->route();
$routeName = $route ? $route->getName() : null;
$deviceId = (string) $request->header('X-Device-Id', $request->input('device_id', ''));
$deviceId = $deviceId !== '' ? substr(preg_replace('/[^a-zA-Z0-9_-]/', '', $deviceId), 0, 64) : null;
$tokenHash = null;
$tokenPreview = null;
if ($joinToken) {
$tokenHash = $joinToken->token_hash ?? null;
$tokenPreview = $joinToken->token_preview ?? null;
} elseif ($providedToken) {
$tokenHash = hash('sha256', $providedToken);
$tokenPreview = $this->buildPreview($providedToken);
}
$eventId = $joinToken?->event_id;
$tenantId = null;
if ($joinToken && $joinToken->relationLoaded('event')) {
$tenantId = $joinToken->event?->tenant_id;
} elseif ($joinToken) {
$tenantId = $joinToken->event()->value('tenant_id');
}
return [
'event_join_token_id' => $joinToken?->getKey(),
'event_id' => $eventId,
'tenant_id' => $tenantId,
'token_hash' => $tokenHash,
'token_preview' => $tokenPreview,
'event_type' => $eventType,
'route' => $routeName,
'http_method' => $request->getMethod(),
'http_status' => $httpStatus,
'device_id' => $deviceId,
'ip_address' => $request->ip(),
'user_agent' => $this->shortenUserAgent($request->userAgent()),
'context' => $context ?: null,
'occurred_at' => now(),
];
}
private function shortenUserAgent(?string $userAgent): ?string
{
if ($userAgent === null) {
return null;
}
if (Str::length($userAgent) > 1024) {
return Str::substr($userAgent, 0, 1024);
}
return $userAgent;
}
private function buildPreview(string $token): string
{
$token = trim($token);
$length = Str::length($token);
if ($length <= 10) {
return $token;
}
return Str::substr($token, 0, 6).'…'.Str::substr($token, -4);
}
}