170 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			170 lines
		
	
	
		
			5.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						||
 | 
						||
namespace App\Http\Controllers;
 | 
						||
 | 
						||
use Illuminate\Http\Request;
 | 
						||
use Illuminate\Support\Str;
 | 
						||
use Illuminate\Support\Facades\DB;
 | 
						||
use App\Models\Calendar;
 | 
						||
use App\Models\CalendarMeta;
 | 
						||
use App\Models\CalendarInstance;
 | 
						||
 | 
						||
class CalendarController extends Controller
 | 
						||
{
 | 
						||
    /**
 | 
						||
     * list calendars owned by the logged-in user
 | 
						||
     */
 | 
						||
    public function index()
 | 
						||
    {
 | 
						||
        $principal = auth()->user()->principal_uri;
 | 
						||
 | 
						||
        $calendars = Calendar::query()
 | 
						||
            ->select('calendars.*', 'ci.displayname as instance_displayname')  // ← add
 | 
						||
            ->join('calendarinstances as ci', 'ci.calendarid', '=', 'calendars.id')
 | 
						||
            ->where('ci.principaluri', $principal)
 | 
						||
            ->orderBy('ci.displayname')
 | 
						||
            ->with(['meta'])          // no need to eager-load full instances any more
 | 
						||
            ->get();
 | 
						||
 | 
						||
        return view('calendars.index', compact('calendars'));
 | 
						||
    }
 | 
						||
 | 
						||
    public function create()
 | 
						||
    {
 | 
						||
        return view('calendars.create');
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * create sabre calendar + meta
 | 
						||
     */
 | 
						||
    public function store(Request $request)
 | 
						||
    {
 | 
						||
        $data = $request->validate([
 | 
						||
            'name'        => 'required|string|max:100',
 | 
						||
            'description' => 'nullable|string|max:255',
 | 
						||
            'timezone'    => 'required|string',
 | 
						||
            'color'       => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
 | 
						||
        ]);
 | 
						||
 | 
						||
        // update master calendar entry
 | 
						||
        $calId = DB::table('calendars')->insertGetId([
 | 
						||
            'synctoken'  => 1,
 | 
						||
            'components' => 'VEVENT', // or 'VEVENT,VTODO' if you add tasks
 | 
						||
        ]);
 | 
						||
 | 
						||
        // update the calendar instance row
 | 
						||
        $instance = CalendarInstance::create([
 | 
						||
            'calendarid'   => $calId,
 | 
						||
            'principaluri' => auth()->user()->principal_uri,
 | 
						||
            'uri'          => Str::uuid(),
 | 
						||
            'displayname'  => $data['name'],
 | 
						||
            'description'  => $data['description'] ?? null,
 | 
						||
            'calendarcolor'=> $data['color'] ?? null,
 | 
						||
            'timezone'     => $data['timezone'],
 | 
						||
        ]);
 | 
						||
 | 
						||
        // update calendar meta
 | 
						||
        $instance->meta()->create([
 | 
						||
            'calendar_id' => $instanceId,
 | 
						||
            'color'       => $data['color'] ?? null,
 | 
						||
            'created_at'  => now(),
 | 
						||
            'updated_at'  => now(),
 | 
						||
        ]);
 | 
						||
 | 
						||
        return redirect()->route('calendars.index');
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * show calendar details
 | 
						||
     */
 | 
						||
    public function show(Calendar $calendar)
 | 
						||
    {
 | 
						||
        $this->authorize('view', $calendar);
 | 
						||
 | 
						||
        $calendar->load([
 | 
						||
            'meta',
 | 
						||
            'instances' => fn ($q) => $q->where('principaluri', auth()->user()->principal_uri),
 | 
						||
        ]);
 | 
						||
 | 
						||
        /* grab the single instance for convenience in the view */
 | 
						||
        $instance = $calendar->instances->first();
 | 
						||
        $caldavUrl = $instance?->caldavUrl();   // null-safe
 | 
						||
 | 
						||
        /* events + meta, newest first */
 | 
						||
        $events = $calendar->events()
 | 
						||
            ->with('meta')
 | 
						||
            ->orderByDesc('lastmodified')
 | 
						||
            ->get();
 | 
						||
 | 
						||
        return view(
 | 
						||
            'calendars.show',
 | 
						||
            compact('calendar', 'instance', 'events', 'caldavUrl')
 | 
						||
        );
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * edit calendar page
 | 
						||
     */
 | 
						||
    public function edit(Calendar $calendar)
 | 
						||
    {
 | 
						||
        $this->authorize('update', $calendar);
 | 
						||
 | 
						||
        $calendar->load([
 | 
						||
        'meta',
 | 
						||
        'instances' => fn ($q) =>
 | 
						||
            $q->where('principaluri', auth()->user()->principal_uri),
 | 
						||
        ]);
 | 
						||
 | 
						||
        $instance = $calendar->instances->first();   // may be null but shouldn’t
 | 
						||
 | 
						||
        return view('calendars.edit', compact('calendar', 'instance'));
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * update sabre + meta records
 | 
						||
     */
 | 
						||
    public function update(Request $request, Calendar $calendar)
 | 
						||
    {
 | 
						||
        $this->authorize('update', $calendar);
 | 
						||
 | 
						||
        $data = $request->validate([
 | 
						||
            'name'        => 'required|string|max:100',
 | 
						||
            'description' => 'nullable|string|max:255',
 | 
						||
            'timezone'    => 'required|string',
 | 
						||
            'color'       => 'nullable|regex:/^#[0-9A-Fa-f]{6}$/',
 | 
						||
        ]);
 | 
						||
 | 
						||
        // update the instance row
 | 
						||
        $calendar->instances()
 | 
						||
            ->where('principaluri', auth()->user()->principal_uri)
 | 
						||
            ->update([
 | 
						||
                'displayname' => $data['name'],
 | 
						||
                'description' => $data['description'] ?? '',
 | 
						||
                'calendarcolor' => $data['color'] ?? null,
 | 
						||
                'timezone'    => $data['timezone'],
 | 
						||
            ]);
 | 
						||
 | 
						||
        // bump synctoken on master calendar row
 | 
						||
        $calendar->increment('synctoken');
 | 
						||
 | 
						||
        // update calendar meta (our table)
 | 
						||
        $calendar->meta()->updateOrCreate([], [
 | 
						||
            'color' => $data['color'] ?? null]
 | 
						||
        );
 | 
						||
 | 
						||
        return redirect()
 | 
						||
            ->route('calendars.show', $calendar)
 | 
						||
            ->with('toast', __('Calendar saved successfully!'));
 | 
						||
    }
 | 
						||
 | 
						||
    /**
 | 
						||
     * delete calendar @todo
 | 
						||
     */
 | 
						||
    public function destroy(Calendar $calendar)
 | 
						||
    {
 | 
						||
        $this->authorize('delete', $calendar);
 | 
						||
        $calendar->delete();          // cascades to meta via FK
 | 
						||
        return redirect()->route('calendars.index');
 | 
						||
    }
 | 
						||
}
 |