keyExists($key)); return $key; } public function keyExists(string $key): bool { return ShortUrl::where('url_key', $key)->exists(); } /** * Create and persist a new ShortUrl. * * @param array{ * destination_url: string, * url_key?: string, * notes?: string, * is_enabled?: bool, * redirect_status_code?: int, * single_use?: bool, * forward_query_params?: bool, * expires_at?: Carbon|null, * track_visits?: bool, * track_ip_address?: bool, * track_browser?: bool, * track_browser_version?: bool, * track_operating_system?: bool, * track_operating_system_version?: bool, * track_device_type?: bool, * track_referer_url?: bool, * qr_options?: array, * ga_tracking_id?: string|null, * } $data */ public function create(array $data): ShortUrl { $tracking = config('filament-short-url.tracking', []); $fields = $tracking['fields'] ?? []; $data = array_merge([ 'is_enabled' => true, 'redirect_status_code' => config('filament-short-url.redirect_status_code', 302), 'single_use' => false, 'forward_query_params' => false, 'track_visits' => $tracking['enabled'] ?? true, 'track_ip_address' => $fields['ip_address'] ?? true, 'track_browser' => $fields['browser'] ?? true, 'track_browser_version' => $fields['browser_version'] ?? true, 'track_operating_system' => $fields['operating_system'] ?? true, 'track_operating_system_version' => $fields['operating_system_version'] ?? true, 'track_device_type' => $fields['device_type'] ?? true, 'track_referer_url' => $fields['referer_url'] ?? true, ], $data); if (empty($data['url_key'])) { $data['url_key'] = $this->generateKey(); } return ShortUrl::create($data); } /** * Build the full publicly accessible short URL string. */ public function buildShortUrl(ShortUrl $shortUrl): string { return $shortUrl->getShortUrl(); } /** * Resolve the final redirect target URL, optionally forwarding query params. */ public function resolveRedirectUrl(ShortUrl $shortUrl, Request $request): string { $destination = $shortUrl->resolveDestinationUrl($request); if (! $shortUrl->forward_query_params) { return $destination; } $queryParams = $request->query(); // Remove routing/auth parameters so they don't leak to destination unset($queryParams['confirmed'], $queryParams['password']); if (empty($queryParams)) { return $destination; } $separator = str_contains($destination, '?') ? '&' : '?'; return $destination.$separator.http_build_query($queryParams); } }