Files
ladill-meet/app/Services/Meet/Calendar/GoogleCalendarProvider.php
T
isaaccladandCursor 965fb992e9
Deploy Ladill Meet / deploy (push) Failing after 7s
Initial Ladill Meet release.
Phases 0–18: core meetings, webinar, breakouts, team chat, live streaming, town hall, billing, and Ladill Mail calendar wiring.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-30 23:35:29 +00:00

109 lines
3.7 KiB
PHP

<?php
namespace App\Services\Meet\Calendar;
use App\Models\CalendarConnection;
use App\Models\Room;
use App\Models\User;
use App\Services\Meet\IcalService;
use Illuminate\Support\Facades\Http;
class GoogleCalendarProvider
{
public function authorizeUrl(): ?string
{
$clientId = config('meet.calendar.google.client_id');
$redirect = config('meet.calendar.google.redirect');
if (! $clientId || ! $redirect) {
return null;
}
$params = http_build_query([
'client_id' => $clientId,
'redirect_uri' => $redirect,
'response_type' => 'code',
'scope' => 'https://www.googleapis.com/auth/calendar.events',
'access_type' => 'offline',
'prompt' => 'consent',
]);
return 'https://accounts.google.com/o/oauth2/v2/auth?'.$params;
}
/**
* @return array<string, mixed>|null
*/
public function exchangeCode(string $code): ?array
{
$response = Http::asForm()->post('https://oauth2.googleapis.com/token', [
'code' => $code,
'client_id' => config('meet.calendar.google.client_id'),
'client_secret' => config('meet.calendar.google.client_secret'),
'redirect_uri' => config('meet.calendar.google.redirect'),
'grant_type' => 'authorization_code',
]);
return $response->successful() ? $response->json() : null;
}
public function createEvent(CalendarConnection $connection, Room $room, User $host): ?string
{
if (! $connection->access_token) {
return null;
}
$response = Http::withToken($connection->access_token)->post(
'https://www.googleapis.com/calendar/v3/calendars/'.urlencode($connection->calendar_id ?? 'primary').'/events',
$this->eventPayload($room, $host),
);
return $response->successful() ? $response->json('id') : null;
}
public function updateEvent(CalendarConnection $connection, Room $room, User $host): bool
{
if (! $connection->access_token || ! $room->calendar_event_id) {
return false;
}
$calendar = urlencode($connection->calendar_id ?? 'primary');
$event = urlencode($room->calendar_event_id);
return Http::withToken($connection->access_token)->put(
"https://www.googleapis.com/calendar/v3/calendars/{$calendar}/events/{$event}",
$this->eventPayload($room, $host),
)->successful();
}
public function deleteEvent(CalendarConnection $connection, Room $room): bool
{
if (! $connection->access_token || ! $room->calendar_event_id) {
return false;
}
$calendar = urlencode($connection->calendar_id ?? 'primary');
$event = urlencode($room->calendar_event_id);
return Http::withToken($connection->access_token)->delete(
"https://www.googleapis.com/calendar/v3/calendars/{$calendar}/events/{$event}",
)->successful();
}
/** @return array<string, mixed> */
protected function eventPayload(Room $room, User $host): array
{
$start = ($room->scheduled_at ?? now())->toIso8601String();
$end = ($room->scheduled_at ?? now())->addMinutes($room->duration_minutes ?? 60)->toIso8601String();
return [
'summary' => $room->title,
'description' => trim(($room->description ?? '')."\n\nJoin: ".$room->joinUrl()),
'location' => $room->joinUrl(),
'start' => ['dateTime' => $start, 'timeZone' => $room->timezone],
'end' => ['dateTime' => $end, 'timeZone' => $room->timezone],
'organizer' => ['email' => $host->email, 'displayName' => $host->name],
];
}
}