Files
ladill-link/app/Services/Link/LinkClickRecorder.php
T
isaaccladandCursor d9c91ad7d8 Add Ladill Link URL shortener on ladl.link.
Management UI at link.ladill.com with GHS 0.05 per link wallet billing,
click analytics, and legacy fallback to ladill.com/q for QR ecosystem codes.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-27 10:58:41 +00:00

54 lines
1.6 KiB
PHP

<?php
namespace App\Services\Link;
use App\Models\LinkClick;
use App\Models\LinkWallet;
use App\Models\ShortLink;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class LinkClickRecorder
{
public function record(ShortLink $link, Request $request): void
{
$ipHash = hash('sha256', $request->ip().'|'.config('app.key'));
$windowHours = (int) config('link.click_unique_window_hours', 24);
$isUnique = ! LinkClick::query()
->where('short_link_id', $link->id)
->where('ip_hash', $ipHash)
->where('clicked_at', '>=', now()->subHours($windowHours))
->exists();
DB::transaction(function () use ($link, $request, $ipHash, $isUnique) {
LinkClick::create([
'short_link_id' => $link->id,
'ip_hash' => $ipHash,
'user_agent' => $this->truncate($request->userAgent(), 512),
'referer' => $this->truncate($request->header('referer'), 512),
'is_unique' => $isUnique,
'clicked_at' => now(),
]);
$link->increment('clicks_total');
if ($isUnique) {
$link->increment('unique_clicks_total');
}
$link->update(['last_clicked_at' => now()]);
LinkWallet::query()
->where('user_id', $link->user_id)
->increment('clicks_total');
});
}
private function truncate(?string $value, int $max): ?string
{
if ($value === null) {
return null;
}
return mb_strlen($value) > $max ? mb_substr($value, 0, $max) : $value;
}
}