feat: initial release v1.0.0
This commit is contained in:
126
src/Services/ShortUrlService.php
Normal file
126
src/Services/ShortUrlService.php
Normal file
@@ -0,0 +1,126 @@
|
||||
<?php
|
||||
|
||||
namespace Bjanczak\FilamentShortUrl\Services;
|
||||
|
||||
use Bjanczak\FilamentShortUrl\Models\ShortUrl;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class ShortUrlService
|
||||
{
|
||||
/**
|
||||
* Start building a ShortUrl programmatically using a fluent interface.
|
||||
*/
|
||||
public function destination(string $url): ShortUrlBuilder
|
||||
{
|
||||
return new ShortUrlBuilder($this, $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique, collision-free URL key.
|
||||
*
|
||||
* Uses base62 (a-z A-Z 0-9) for maximum URL friendliness.
|
||||
* Retries automatically on the rare collision chance.
|
||||
*/
|
||||
public function generateKey(?int $length = null): string
|
||||
{
|
||||
$length ??= (int) config('filament-short-url.key_length', 6);
|
||||
$characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
||||
$maxIndex = strlen($characters) - 1;
|
||||
|
||||
do {
|
||||
$key = '';
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$key .= $characters[random_int(0, $maxIndex)];
|
||||
}
|
||||
} while ($this->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->destination_url;
|
||||
|
||||
if (! $shortUrl->forward_query_params) {
|
||||
return $destination;
|
||||
}
|
||||
|
||||
$queryParams = $request->query();
|
||||
|
||||
if (empty($queryParams)) {
|
||||
return $destination;
|
||||
}
|
||||
|
||||
$separator = str_contains($destination, '?') ? '&' : '?';
|
||||
|
||||
return $destination.$separator.http_build_query($queryParams);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user