diff --git a/src/Bundle/ChillCalendarBundle/Entity/RemoteCalendarTrait.php b/src/Bundle/ChillCalendarBundle/Entity/RemoteCalendarTrait.php index 4196de35a..9e162541d 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/RemoteCalendarTrait.php +++ b/src/Bundle/ChillCalendarBundle/Entity/RemoteCalendarTrait.php @@ -15,6 +15,14 @@ use Doctrine\ORM\Mapping as ORM; trait RemoteCalendarTrait { + /** + * If true, the changes won't be enqueued to remote. + * + * This is required to prevent update loop: a persist trigger an event creation on remote, + * which in turn change remoteId and, in turn, trigger an update change, ... + */ + public bool $preventEnqueueChanges = false; + /** * @ORM\Column(type="json", options={"default": "[]"}, nullable=false) */ @@ -25,14 +33,6 @@ trait RemoteCalendarTrait */ private string $remoteId = ''; - /** - * If true, the changes won't be enqueued to remote - * - * This is required to prevent update loop: a persist trigger an event creation on remote, - * which in turn change remoteId and, in turn, trigger an update change, ... - */ - public bool $preventEnqueueChanges = false; - public function addRemoteAttributes(array $remoteAttributes): self { $this->remoteAttributes = array_merge($this->remoteAttributes, $remoteAttributes); diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php index 409a30240..569ec2f56 100644 --- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteEventConverter.php @@ -107,6 +107,11 @@ class RemoteEventConverter ); } + public function getLastModifiedDate(array $event): DateTimeImmutable + { + return DateTimeImmutable::createFromFormat(self::REMOTE_DATETIMEZONE_FORMAT, $event['lastModifiedDateTime']); + } + /** * Return a string which format a DateTime to string. To be used in POST requests,. */ diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php index ade4baa28..db02b4903 100644 --- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php @@ -19,7 +19,6 @@ use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\OnBehalfOfUserTokenSto use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\RemoteEventConverter; use Chill\MainBundle\Entity\User; use DateTimeImmutable; -use Exception; use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Response; @@ -110,9 +109,10 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface public function syncCalendarRange(CalendarRange $calendarRange): void { if ($calendarRange->hasRemoteId()) { - throw new Exception('update existing not implemented'); + $this->updateRemoteCalendarRange($calendarRange); + } else { + $this->createRemoteCalendarRange($calendarRange); } - $this->createRemoteCalendarRange($calendarRange); } private function createRemoteCalendarRange(CalendarRange $calendarRange): void @@ -148,11 +148,9 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface throw $e; } - dump($event); - $calendarRange->setRemoteId($event['id']) ->addRemoteAttributes([ - 'lastModifiedDateTime' => (DateTimeImmutable::createFromFormat(RemoteEventConverter::REMOTE_DATETIMEZONE_FORMAT, $event['lastModifiedDateTime']))->getTimestamp(), + 'lastModifiedDateTime' => $this->remoteEventConverter->getLastModifiedDate($event)->getTimestamp(), 'changeKey' => $event['changeKey'], ]); } @@ -201,4 +199,69 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface $response['value'][0]['scheduleItems'] ); } + + 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'], + ]); + } }