kithkin/app/Http/Controllers/SubscriptionController.php

159 lines
5.4 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)
{
/* validate the submission */
$data = $request->validate([
'source' => 'required|url',
'displayname' => 'nullable|string|max:255',
'color' => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
'refreshrate' => 'nullable|string|max:10',
]);
/* normalize hard to check against this url */
$source = rtrim(trim($data['source']), '/');
/* set the principal URI */
$principalUri = $request->user()->uri;
/* check for existing subscriptions */
$already = Subscription::query()
->where('principaluri', $principalUri)
->where('source', $source)
->exists();
if ($already) {
return Redirect::route('calendar.index')->with('toast', [
'message' => __('You are already subscribed to that calendar.'),
'type' => 'info',
]);
}
$sub = DB::transaction(function () use ($data, $principalUri, $source) {
/* 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,
]);
// create new empty calendar container
$calId = Calendar::create([
'synctoken' => 1,
'components' => 'VEVENT',
])->id;
// create mirror calendarinstance row (description can be user-editable, not relied on)
CalendarInstance::create([
'calendarid' => $calId,
'principaluri' => $principalUri,
'uri' => (string) Str::uuid(),
'displayname' => $sub->displayname,
'description' => 'Remote feed: '.$source, // informational only
'calendarcolor' => $sub->calendarcolor,
'timezone' => config('app.timezone', 'UTC'),
]);
// meta entry
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!'));
}
}