Deploy Ladill Link / deploy (push) Successful in 41s
Co-authored-by: Cursor <cursoragent@cursor.com>
146 lines
4.8 KiB
PHP
146 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Link;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\ShortLink;
|
|
use App\Services\Link\LinkAnalyticsService;
|
|
use App\Services\Link\LinkBillingService;
|
|
use App\Services\Link\LinkCatalogSyncService;
|
|
use App\Services\Link\LinkManagerService;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
use RuntimeException;
|
|
|
|
class LinkController extends Controller
|
|
{
|
|
public function __construct(
|
|
private LinkManagerService $links,
|
|
private LinkBillingService $billing,
|
|
private LinkCatalogSyncService $catalogSync,
|
|
private LinkAnalyticsService $analytics,
|
|
) {}
|
|
|
|
public function index(Request $request): View
|
|
{
|
|
$account = ladill_account();
|
|
$this->catalogSync->syncForUser($account);
|
|
|
|
$links = ShortLink::query()
|
|
->where('user_id', $account->id)
|
|
->latest()
|
|
->paginate(20);
|
|
|
|
$wallet = $account->getOrCreateLinkWallet();
|
|
|
|
return view('links.index', [
|
|
'links' => $links,
|
|
'wallet' => $wallet,
|
|
'balance' => $this->billing->balanceCedis($account),
|
|
'canCreate' => $this->billing->canCreate($account),
|
|
'pricePerLink' => \App\Models\LinkWallet::pricePerLink(),
|
|
'topupUrl' => ladill_account_url('wallet'),
|
|
]);
|
|
}
|
|
|
|
public function create(): View
|
|
{
|
|
$account = ladill_account();
|
|
|
|
return view('links.create', [
|
|
'canCreate' => $this->billing->canCreate($account),
|
|
'pricePerLink' => \App\Models\LinkWallet::pricePerLink(),
|
|
]);
|
|
}
|
|
|
|
public function store(Request $request): RedirectResponse
|
|
{
|
|
$validated = $request->validate([
|
|
'destination_url' => ['required', 'string', 'max:2048'],
|
|
'label' => ['nullable', 'string', 'max:120'],
|
|
'custom_slug' => ['nullable', 'string', 'max:20', 'regex:/^[a-z0-9][a-z0-9-]{1,18}[a-z0-9]$/'],
|
|
'expires_at' => ['nullable', 'date', 'after:now'],
|
|
]);
|
|
|
|
try {
|
|
$link = $this->links->create(ladill_account(), $validated);
|
|
} catch (RuntimeException $e) {
|
|
return back()->withInput()->withErrors(['balance' => $e->getMessage()]);
|
|
}
|
|
|
|
return redirect()
|
|
->route('user.links.show', $link)
|
|
->with('success', 'Short link created.');
|
|
}
|
|
|
|
public function show(ShortLink $link): View
|
|
{
|
|
$this->authorizeLink($link);
|
|
|
|
return view('links.show', [
|
|
'link' => $link,
|
|
'summary' => $this->analytics->summaryForLink($link),
|
|
'dailyClicks' => $this->analytics->dailyClicksForLink($link, 30),
|
|
'devices' => $this->analytics->breakdownForLink($link, 'device_type'),
|
|
'browsers' => $this->analytics->breakdownForLink($link, 'browser'),
|
|
'platforms' => $this->analytics->breakdownForLink($link, 'os'),
|
|
'countries' => $this->analytics->breakdownForLink($link, 'country'),
|
|
'referrers' => $this->analytics->referrersForLink($link),
|
|
'recentClicks' => $this->analytics->recentClicksForLink($link),
|
|
]);
|
|
}
|
|
|
|
public function update(Request $request, ShortLink $link): RedirectResponse
|
|
{
|
|
$this->authorizeLink($link);
|
|
|
|
if (! $link->is_managed_here) {
|
|
return back()->withErrors(['link' => 'This link is managed in '.$link->sourceAppLabel().'.']);
|
|
}
|
|
|
|
$validated = $request->validate([
|
|
'destination_url' => ['sometimes', 'required', 'string', 'max:2048'],
|
|
'label' => ['nullable', 'string', 'max:120'],
|
|
'is_active' => ['sometimes', 'boolean'],
|
|
'expires_at' => ['nullable', 'date'],
|
|
]);
|
|
|
|
try {
|
|
$this->links->update($link, $validated);
|
|
} catch (RuntimeException $e) {
|
|
return back()->withInput()->withErrors(['destination_url' => $e->getMessage()]);
|
|
}
|
|
|
|
return back()->with('success', 'Link updated.');
|
|
}
|
|
|
|
public function destroy(ShortLink $link): RedirectResponse
|
|
{
|
|
$this->authorizeLink($link);
|
|
|
|
if (! $link->is_managed_here) {
|
|
return back()->withErrors(['link' => 'This link is managed in '.$link->sourceAppLabel().'.']);
|
|
}
|
|
|
|
$link->delete();
|
|
|
|
return redirect()->route('user.links.index')->with('success', 'Link deleted.');
|
|
}
|
|
|
|
public function checkSlug(Request $request): \Illuminate\Http\JsonResponse
|
|
{
|
|
$slug = strtolower((string) $request->query('slug', ''));
|
|
$taken = $slug !== '' && ShortLink::where('slug', $slug)->exists();
|
|
|
|
return response()->json(['available' => ! $taken]);
|
|
}
|
|
|
|
private function authorizeLink(ShortLink $link): void
|
|
{
|
|
if ($link->user_id !== ladill_account()->id) {
|
|
abort(403);
|
|
}
|
|
}
|
|
}
|