223 lines
6.9 KiB
PHP
223 lines
6.9 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\CalendarInstance;
|
|
use App\Models\CalendarMeta;
|
|
use App\Models\Subscription;
|
|
use App\Services\Calendar\CreateCalendar;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\Support\Str;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Redirect;
|
|
|
|
class CalendarSettingsController extends Controller
|
|
{
|
|
/* landing page shows the first settings pane */
|
|
public function index()
|
|
{
|
|
return redirect()->route('calendar.settings.create');
|
|
}
|
|
|
|
/**
|
|
* Create a local calendar
|
|
**/
|
|
|
|
public function createForm(Request $request)
|
|
{
|
|
$user = $request->user();
|
|
|
|
$data = [
|
|
'title' => __('calendar.settings.create.title'),
|
|
'sub' => __('calendar.settings.create.subtitle'),
|
|
'defaults' => [
|
|
'name' => '',
|
|
'description' => '',
|
|
'timezone' => $user->timezone ?? config('app.timezone', 'UTC'),
|
|
'color' => default_calendar_color(),
|
|
],
|
|
'redirect' => route('calendar.settings'),
|
|
];
|
|
|
|
if ($request->header('HX-Request')) {
|
|
$data['redirect'] = route('calendar.index');
|
|
return view('calendar.partials.create-modal', $data);
|
|
}
|
|
|
|
return $this->frame('calendar.settings.create', $data);
|
|
}
|
|
|
|
public function createStore(Request $request, CreateCalendar $creator)
|
|
{
|
|
$data = $request->validate([
|
|
'name' => 'required|string|max:100',
|
|
'description' => 'nullable|string|max:255',
|
|
'timezone' => 'required|string',
|
|
'color' => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
|
|
]);
|
|
|
|
$creator->create($request->user(), $data);
|
|
$redirect = $data['redirect'] ?? route('calendar.index');
|
|
|
|
return redirect($redirect)->with('toast', [
|
|
'message' => __('Calendar created!'),
|
|
'type' => 'success',
|
|
]);
|
|
}
|
|
|
|
|
|
/**
|
|
* Subscribe
|
|
**/
|
|
|
|
/* show “Subscribe to a calendar” form */
|
|
public function subscribeForm()
|
|
{
|
|
return $this->frame(
|
|
'calendar.settings.subscribe',
|
|
[
|
|
'title' => __('calendar.settings.subscribe.title'),
|
|
'sub' => __('calendar.settings.subscribe.subtitle'),
|
|
]);
|
|
}
|
|
|
|
/* handle POST from the subscribe form */
|
|
public function subscribeStore(Request $request)
|
|
{
|
|
$data = $request->validate([
|
|
'source' => ['required', 'url'],
|
|
'displayname' => ['nullable', 'string', 'max:100'],
|
|
'color' => ['nullable', 'regex:/^#[0-9A-F]{6}$/i'],
|
|
]);
|
|
|
|
// create the calendarsubscription and calendar_meta rows in one call via Subscription model
|
|
Subscription::createWithMeta(
|
|
$request->user(),
|
|
[
|
|
'source' => $data['source'],
|
|
'displayname' => $data['displayname'] ?: $data['source'],
|
|
'calendarcolor' => calendar_color($data),
|
|
// you can add 'refreshrate' => 'P1D' here if you like
|
|
]
|
|
);
|
|
|
|
return redirect()
|
|
->route('calendar.index')
|
|
->with('toast', __('Subscription added successfully!'));
|
|
}
|
|
|
|
|
|
/**
|
|
* individual calendar settings
|
|
*/
|
|
public function calendarForm(Request $request, string $calendarUri)
|
|
{
|
|
$user = $request->user();
|
|
$principalUri = $user->uri;
|
|
|
|
// this is the user's "instance" of the calendar (displayname/color/etc live here in sabre)
|
|
$instance = CalendarInstance::query()
|
|
->where('principaluri', $principalUri)
|
|
->where('uri', $calendarUri)
|
|
->firstOrFail();
|
|
|
|
// your app meta (optional row)
|
|
$meta = $instance->meta;
|
|
|
|
// if it's remote
|
|
$icsUrl = null;
|
|
if (($meta?->is_remote ?? false) && $meta?->subscription_id) {
|
|
$icsUrl = Subscription::query()
|
|
->whereKey($meta->subscription_id)
|
|
->value('source');
|
|
}
|
|
|
|
return $this->frame(
|
|
'calendar.settings.calendar',
|
|
[
|
|
'title' => __('calendar.settings.calendar.title'),
|
|
'sub' => __('calendar.settings.calendar.subtitle'),
|
|
'instance' => $instance,
|
|
'meta' => $meta,
|
|
'icsUrl' => $icsUrl,
|
|
'userTz' => $user->timezone,
|
|
]);
|
|
}
|
|
|
|
public function calendarStore(Request $request, string $calendarUri): RedirectResponse
|
|
{
|
|
$user = $request->user();
|
|
$principalUri = $user->uri;
|
|
|
|
$instance = CalendarInstance::query()
|
|
->where('principaluri', $principalUri)
|
|
->where('uri', $calendarUri)
|
|
->with('meta')
|
|
->firstOrFail();
|
|
|
|
$data = $request->validate([
|
|
'displayname' => ['required', 'string', 'max:100'],
|
|
'description' => ['nullable', 'string', 'max:500'],
|
|
'timezone' => ['nullable', 'string', 'max:64'],
|
|
'color' => ['nullable', 'regex:/^#[0-9A-F]{6}$/i'],
|
|
]);
|
|
|
|
$timezone = filled($data['timezone'] ?? null)
|
|
? $data['timezone']
|
|
: $user->timezone;
|
|
|
|
$color = $data['color'] ?? $instance->resolvedColor();
|
|
|
|
DB::transaction(function () use ($instance, $data, $timezone, $color) {
|
|
|
|
// update sabre calendar instance (dav-facing)
|
|
$instance->update([
|
|
'displayname' => $data['displayname'],
|
|
'description' => $data['description'] ?? null,
|
|
'timezone' => $timezone,
|
|
'calendarcolor' => $color,
|
|
]);
|
|
|
|
// update ui meta (kithkin-facing)
|
|
CalendarMeta::updateOrCreate(
|
|
['calendar_id' => $instance->calendarid],
|
|
[
|
|
'title' => $data['displayname'],
|
|
'color' => $color,
|
|
'color_fg' => contrast_text_color($color),
|
|
]
|
|
);
|
|
});
|
|
|
|
return Redirect::route('calendar.settings.calendars.show', $calendarUri)
|
|
->with('toast', [
|
|
'message' => __('calendar.settings.saved'),
|
|
'type' => 'success',
|
|
]);
|
|
}
|
|
|
|
|
|
/**
|
|
* content frame handler
|
|
*/
|
|
private function frame(?string $view = null, array $data = [])
|
|
{
|
|
$user = request()->user();
|
|
|
|
/* pull user's calendar instances and adapt ordering keys to calendarorder */
|
|
$calendars = CalendarInstance::query()
|
|
->forUser($user)
|
|
->withUiMeta()
|
|
->ordered()
|
|
->get();
|
|
|
|
return view('calendar.settings.index', [
|
|
'view' => $view,
|
|
'data' => $data,
|
|
'calendars' => $calendars,
|
|
'timezones' => config('timezones'),
|
|
]);
|
|
}
|
|
}
|