machineHttpClient = $machineHttpClient; $this->mapCalendarToUser = $mapCalendarToUser; $this->logger = $logger; $this->remoteEventConverter = $remoteEventConverter; $this->tokenStorage = $tokenStorage; $this->urlGenerator = $urlGenerator; $this->userHttpClient = $userHttpClient; } public function getMakeReadyResponse(string $returnPath): Response { return new RedirectResponse($this->urlGenerator ->generate('chill_calendar_remote_connect_azure', ['returnPath' => $returnPath])); } public function isReady(): bool { return $this->tokenStorage->hasToken(); } public function listEventsForUser(User $user, DateTimeImmutable $startDate, DateTimeImmutable $endDate): array { $userId = $this->mapCalendarToUser->getUserId($user); if (null === $userId) { return []; } try { $bareEvents = $this->userHttpClient->request( 'GET', 'users/' . $userId . '/calendarView', [ 'query' => [ 'startDateTime' => $startDate->format(DateTimeImmutable::ATOM), 'endDateTime' => $endDate->format(DateTimeImmutable::ATOM), '$select' => 'id,subject,start,end', ], ] )->toArray(); return array_map(function ($item) { return $this->remoteEventConverter->convertToRemote($item); }, $bareEvents['value']); } catch (ClientExceptionInterface $e) { if (403 === $e->getResponse()->getStatusCode()) { return $this->getScheduleTimesForUser($user, $startDate, $endDate); } $this->logger->debug('Could not get list of event on MSGraph', [ 'error_code' => $e->getResponse()->getStatusCode(), 'error' => $e->getResponse()->getInfo(), ]); return []; } } public function removeCalendarRange(string $remoteId, array $remoteAttributes, User $user): void { if ('' === $remoteId) { return; } $this->removeEvent($remoteId, $user); } public function syncCalendarRange(CalendarRange $calendarRange): void { if ($calendarRange->hasRemoteId()) { $this->updateRemoteCalendarRange($calendarRange); } else { $this->createRemoteCalendarRange($calendarRange); } } private function createRemoteCalendarRange(CalendarRange $calendarRange): void { $userId = $this->mapCalendarToUser->getUserId($calendarRange->getUser()); $calendarId = $this->mapCalendarToUser->getCalendarId($calendarRange->getUser()); if (null === $userId || null === $calendarId) { $this->logger->warning('user does not have userId nor calendarId', [ 'user_id' => $calendarRange->getUser()->getId(), 'calendar_range_id' => $calendarRange->getId(), ]); return; } $eventData = $this->remoteEventConverter->calendarRangeToEvent($calendarRange); try { $event = $this->machineHttpClient->request( 'POST', 'users/' . $userId . '/calendar/events', [ 'json' => $eventData, ] )->toArray(); } catch (ClientExceptionInterface $e) { $this->logger->warning('could not save calendar range to remote', [ 'exception' => $e->getTraceAsString(), 'calendarRangeId' => $calendarRange->getId(), ]); throw $e; } $calendarRange->setRemoteId($event['id']) ->addRemoteAttributes([ 'lastModifiedDateTime' => $this->remoteEventConverter->getLastModifiedDate($event)->getTimestamp(), 'changeKey' => $event['changeKey'], ]); } private function getScheduleTimesForUser(User $user, DateTimeImmutable $startDate, DateTimeImmutable $endDate): array { $userId = $this->mapCalendarToUser->getUserId($user); if (null === $userId) { return []; } if (null === $user->getEmailCanonical() || '' === $user->getEmailCanonical()) { return []; } $body = [ 'schedules' => [$user->getEmailCanonical()], 'startTime' => [ 'dateTime' => ($startDate->setTimezone(RemoteEventConverter::getRemoteTimeZone())->format(RemoteEventConverter::getRemoteDateTimeSimpleFormat())), 'timeZone' => 'UTC', ], 'endTime' => [ 'dateTime' => ($endDate->setTimezone(RemoteEventConverter::getRemoteTimeZone())->format(RemoteEventConverter::getRemoteDateTimeSimpleFormat())), 'timeZone' => 'UTC', ], ]; try { $response = $this->userHttpClient->request('POST', 'users/' . $userId . '/calendar/getSchedule', [ 'json' => $body, ])->toArray(); } catch (ClientExceptionInterface $e) { $this->logger->debug('Could not get schedule on MSGraph', [ 'error_code' => $e->getResponse()->getStatusCode(), 'error' => $e->getResponse()->getInfo(), ]); return []; } return array_map( function ($item) { return $this->remoteEventConverter->convertAvailabilityToRemoteEvent($item); }, $response['value'][0]['scheduleItems'] ); } private function removeEvent($remoteId, User $user): void { $userId = $this->mapCalendarToUser->getUserId($user); try { $this->machineHttpClient->request( 'DELETE', 'users/' . $userId . '/calendar/events/' . $remoteId ); } catch (ClientExceptionInterface $e) { $this->logger->warning('could not remove event from calendar', [ 'event_remote_id' => $remoteId, 'user_id' => $user->getId(), ]); } } private function updateRemoteCalendarRange(CalendarRange $calendarRange): void { $userId = $this->mapCalendarToUser->getUserId($calendarRange->getUser()); $calendarId = $this->mapCalendarToUser->getCalendarId($calendarRange->getUser()); if (null === $userId || null === $calendarId) { $this->logger->warning('user does not have userId nor calendarId', [ 'user_id' => $calendarRange->getUser()->getId(), 'calendar_range_id' => $calendarRange->getId(), ]); return; } try { $event = $this->machineHttpClient->request( 'GET', 'users/' . $userId . '/calendar/events/' . $calendarRange->getRemoteId() )->toArray(); } catch (ClientExceptionInterface $e) { $this->logger->warning('Could not get event from calendar', [ 'calendar_range_id' => $calendarRange->getId(), 'calendar_range_remote_id' => $calendarRange->getRemoteId(), ]); throw $e; } if ($this->remoteEventConverter->getLastModifiedDate($event)->getTimestamp() > $calendarRange->getUpdatedAt()->getTimestamp()) { $this->logger->info('Skip updating as the lastModified date seems more fresh than the database one', [ 'calendar_range_id' => $calendarRange->getId(), 'calendar_range_remote_id' => $calendarRange->getRemoteId(), 'db_last_updated' => $calendarRange->getUpdatedAt()->getTimestamp(), 'remote_last_updated' => $this->remoteEventConverter->getLastModifiedDate($event)->getTimestamp(), ]); return; } $eventData = $this->remoteEventConverter->calendarRangeToEvent($calendarRange); try { $event = $this->machineHttpClient->request( 'PATCH', 'users/' . $userId . '/calendar/events/' . $calendarRange->getRemoteId(), [ 'json' => $eventData, ] )->toArray(); } catch (ClientExceptionInterface $e) { $this->logger->warning('could not update calendar range to remote', [ 'exception' => $e->getTraceAsString(), 'calendarRangeId' => $calendarRange->getId(), ]); throw $e; } $calendarRange ->addRemoteAttributes([ 'lastModifiedDateTime' => $this->remoteEventConverter->getLastModifiedDate($event)->getTimestamp(), 'changeKey' => $event['changeKey'], ]); } }