From ba8a2327be312171ee3aa4a7201aa7ed708797d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Mon, 9 May 2022 16:44:46 +0200 Subject: [PATCH] fallback on schedule items when no access to calendar --- .../MSGraph/RemoteEventConverter.php | 39 ++++++++++++++- .../MSGraphRemoteCalendarConnector.php | 49 +++++++++++++++++++ .../translations/messages.fr.yml | 13 ++++- 3 files changed, 97 insertions(+), 4 deletions(-) diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php index 4d358b95b..2ccb48683 100644 --- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php @@ -14,6 +14,7 @@ namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph; use Chill\CalendarBundle\RemoteCalendar\Model\RemoteEvent; use DateTimeImmutable; use DateTimeZone; +use Symfony\Contracts\Translation\TranslatorInterface; /** * Convert Chill Calendar event to Remote MS Graph event, and MS Graph @@ -27,10 +28,31 @@ class RemoteEventConverter private DateTimeZone $remoteDateTimeZone; - public function __construct() + private TranslatorInterface $translator; + + public function __construct(TranslatorInterface $translator) { + $this->translator = $translator; $this->defaultDateTimeZone = (new DateTimeImmutable())->getTimezone(); - $this->remoteDateTimeZone = new DateTimeZone('UTC'); + $this->remoteDateTimeZone = self::getRemoteTimeZone(); + } + + public function convertAvailabilityToRemoteEvent(array $event): RemoteEvent + { + $startDate = + DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['start']['dateTime']) + ->setTimezone($this->defaultDateTimeZone); + $endDate = + DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['end']['dateTime'], $this->remoteDateTimeZone) + ->setTimezone($this->defaultDateTimeZone); + + return new RemoteEvent( + uniqid('generated_'), + $this->translator->trans('remote_ms_graph.freebusy_statuses.' . $event['status']), + '', + $startDate, + $endDate + ); } public function convertToRemote(array $event): RemoteEvent @@ -50,4 +72,17 @@ class RemoteEventConverter $endDate ); } + + /** + * Return a string which format a DateTime to string. To be used in POST requests,. + */ + public static function getRemoteDateTimeSimpleFormat(): string + { + return 'Y-m-d\TH:i:s'; + } + + public static function getRemoteTimeZone(): DateTimeZone + { + return new DateTimeZone('UTC'); + } } diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php index b9df6be27..914aece91 100644 --- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php @@ -92,6 +92,10 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface 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(), @@ -100,4 +104,49 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface return []; } } + + 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'] + ); + } } diff --git a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml index 56ac8543c..d8c8a5d2e 100644 --- a/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml +++ b/src/Bundle/ChillCalendarBundle/translations/messages.fr.yml @@ -17,7 +17,7 @@ status: Statut du rendez-vous calendar location: Localistion du rendez-vous calendar comment: Remarque sur le rendez-vous sendSMS: Envoi d'un SMS -Send s m s: Envoi d'un SMS ? +Send s m s: Envoi d'un SMS ? Cancel reason: Motif d'annulation Add a new calendar: Ajouter un nouveau rendez-vous "Success : calendar item updated!": "Rendez-vous mis à jour" @@ -25,4 +25,13 @@ Add a new calendar: Ajouter un nouveau rendez-vous The calendar item has been successfully removed.: Le rendez-vous a été supprimé From the day: Du to the day: au -Transform to activity: Transformer en échange \ No newline at end of file +Transform to activity: Transformer en échange + +remote_ms_graph: + freebusy_statuses: + busy: Occupé + free: Libre + tentative: En attente de confirmation + oof: En dehors du bureau + workingElsewhere: Travaille à l'extérieur + unknown: Inconnu