171 lines
6.1 KiB
PHP
171 lines
6.1 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers;
|
||
|
||
use App\Jobs\SyncSubscription;
|
||
use App\Models\Subscription;
|
||
use App\Models\Calendar;
|
||
use App\Models\CalendarInstance;
|
||
use App\Models\CalendarMeta;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Str;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Redirect;
|
||
|
||
class SubscriptionController extends Controller
|
||
{
|
||
public function index()
|
||
{
|
||
$subs = Subscription::where('principaluri', auth()->user()->uri)->get();
|
||
|
||
return view('subscription.index', compact('subs'));
|
||
}
|
||
|
||
public function create()
|
||
{
|
||
return view('subscription.create');
|
||
}
|
||
|
||
public function store(Request $request)
|
||
{
|
||
$data = $request->validate([
|
||
'source' => 'required|url',
|
||
'displayname' => 'nullable|string|max:255',
|
||
'color' => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
|
||
'refreshrate' => 'nullable|string|max:10',
|
||
]);
|
||
|
||
$principalUri = $request->user()->uri;
|
||
$source = rtrim(trim($data['source']), '/');
|
||
$desc = 'Remote feed: '.$source;
|
||
|
||
/* if they already subscribed to this exact feed, don’t create duplicates */
|
||
if (Subscription::where('principaluri', $principalUri)->where('source', $source)->exists()) {
|
||
return Redirect::route('calendar.index')->with('toast', [
|
||
'message' => __('You are already subscribed to that calendar.'),
|
||
'type' => 'info',
|
||
]);
|
||
}
|
||
|
||
$sub = DB::transaction(function () use ($request, $data, $principalUri, $source, $desc) {
|
||
|
||
/* check if a mirror instance already exists */
|
||
$existingInstance = CalendarInstance::where('principaluri', $principalUri)
|
||
->where('description', $desc)
|
||
->first();
|
||
|
||
|
||
/* create the calendarsubscriptions record */
|
||
$sub = Subscription::create([
|
||
'uri' => (string) Str::uuid(),
|
||
'principaluri' => $principalUri,
|
||
'source' => $source,
|
||
'displayname' => $data['displayname'] ?: $source,
|
||
'calendarcolor' => $data['color'] ?? '#1a1a1a',
|
||
'refreshrate' => 'P1D',
|
||
'lastmodified' => now()->timestamp,
|
||
]);
|
||
|
||
// choose the calendar container
|
||
if ($existingInstance) {
|
||
$calId = $existingInstance->calendarid;
|
||
|
||
// keep the mirror instance’s user-facing bits up to date
|
||
$existingInstance->update([
|
||
'displayname' => $sub->displayname,
|
||
'calendarcolor' => $sub->calendarcolor,
|
||
'timezone' => config('app.timezone', 'UTC'),
|
||
]);
|
||
} else {
|
||
// create new empty calendar container
|
||
$calId = Calendar::create([
|
||
'synctoken' => 1,
|
||
'components' => 'VEVENT',
|
||
])->id;
|
||
|
||
// create mirror calendarinstance row
|
||
CalendarInstance::create([
|
||
'calendarid' => $calId,
|
||
'principaluri' => $sub->principaluri,
|
||
'uri' => Str::uuid(),
|
||
'displayname' => $sub->displayname,
|
||
'description' => $desc,
|
||
'calendarcolor' => $sub->calendarcolor,
|
||
'timezone' => config('app.timezone', 'UTC'),
|
||
]);
|
||
}
|
||
|
||
// upsert our calendar_meta entry by calendar_id (since that’s your pk)
|
||
CalendarMeta::updateOrCreate(
|
||
['calendar_id' => $calId],
|
||
[
|
||
'subscription_id' => $sub->id,
|
||
'title' => $sub->displayname,
|
||
'color' => $sub->calendarcolor,
|
||
'color_fg' => contrast_text_color($sub->calendarcolor),
|
||
'is_shared' => true,
|
||
'is_remote' => true,
|
||
]
|
||
);
|
||
|
||
return $sub;
|
||
});
|
||
|
||
// sync immediately so events appear without waiting for the */10 dispatcher
|
||
SyncSubscription::dispatch($sub)->afterCommit();
|
||
|
||
return redirect()
|
||
->route('calendar.index')
|
||
->with('toast', [
|
||
'message' => __('Subscription added! Syncing events now...'),
|
||
'type' => 'success',
|
||
]);
|
||
}
|
||
|
||
public function edit(Subscription $subscription)
|
||
{
|
||
$this->authorize('update', $subscription);
|
||
return view('subscription.edit', ['subscription' => $subscription]);
|
||
}
|
||
|
||
public function update(Request $request, Subscription $subscription)
|
||
{
|
||
$this->authorize('update', $subscription);
|
||
|
||
$data = $request->validate([
|
||
'displayname' => 'nullable|string|max:255',
|
||
'calendarcolor' => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
|
||
'refreshrate' => 'nullable|string|max:10',
|
||
'striptodos' => 'sometimes|boolean',
|
||
'stripalarms' => 'sometimes|boolean',
|
||
'stripattachments' => 'sometimes|boolean',
|
||
]);
|
||
|
||
// update calendarsubscriptions record
|
||
$subscription->update($data);
|
||
|
||
// update corresponding calendar_meta record
|
||
$subscription->meta()->updateOrCreate(
|
||
[], // no “where” clause → look at subscription_id FK
|
||
[
|
||
'title' => $subscription->displayname,
|
||
'color' => $subscription->calendarcolor ?? '#1a1a1a',
|
||
'color_fg' => contrast_text_color(
|
||
$subscription->calendarcolor ?? '#1a1a1a'
|
||
),
|
||
'updated_at'=> now(),
|
||
]
|
||
);
|
||
|
||
return back()->with('toast', __('Subscription updated!'));
|
||
}
|
||
|
||
public function destroy(Subscription $subscription)
|
||
{
|
||
$this->authorize('delete', $subscription);
|
||
$subscription->delete();
|
||
|
||
return back()->with('toast', __('Subscription removed!'));
|
||
}
|
||
}
|