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!')); } }