where('original_url', $original_url) ->first(); if ($existing && $existing->isValid()) { return $existing->short_code; } $short_code = $this->generateUniqueCode(); $expires_at = null; if ($expires_in_hours) { $expires_at = date('Y-m-d H:i:s', strtotime("+{$expires_in_hours} hours")); } $shortener = new UrlShortener(); $shortener->tenant_id = $tenant_id; $shortener->short_code = $short_code; $shortener->original_url = $original_url; $shortener->expires_at = $expires_at; $shortener->save(); return $short_code; } catch (Exception $e) { error_log("UrlShortenerService::createShortUrl error: " . $e->getMessage()); return null; } } /** * Get original URL from short code and track visit * * @param string $short_code * @return string|null Original URL or null if not found/expired */ public function getOriginalUrl($short_code) { try { $shortener = UrlShortener::where('short_code', $short_code)->first(); if (!$shortener) { return null; } if ($shortener->isExpired()) { return null; } $shortener->incrementVisits(); return $shortener->original_url; } catch (Exception $e) { error_log("UrlShortenerService::getOriginalUrl error: " . $e->getMessage()); return null; } } /** * Generate a unique short code * * @return string */ private function generateUniqueCode() { $chars = '23456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ'; $code_length = 6; do { $short_code = ''; for ($i = 0; $i < $code_length; $i++) { $short_code .= $chars[random_int(0, strlen($chars) - 1)]; } } while (UrlShortener::where('short_code', $short_code)->exists()); return $short_code; } /** * Clean up expired URLs * * @return int Number of deleted records */ public function cleanupExpiredUrls() { try { return UrlShortener::where('expires_at', '<', date('Y-m-d H:i:s')) ->whereNotNull('expires_at') ->delete(); } catch (Exception $e) { error_log("UrlShortenerService::cleanupExpiredUrls error: " . $e->getMessage()); return 0; } } }