From f149b2480239b429b5e2965e7e17a19dee9aa8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 9 Jun 2022 17:06:57 +0200 Subject: [PATCH] small fixes on sync from remote --- .../ChillCalendarBundle/Entity/Calendar.php | 1 - .../MSGraphChangeNotificationHandler.php | 24 +++ .../RemoteToLocalSync/CalendarRangeSyncer.php | 7 +- .../RemoteToLocalSync/CalendarSyncer.php | 93 +++++++++ .../Connector/MSGraph/CalendarSyncerTest.php | 194 ++++++++++++++++++ 5 files changed, 317 insertions(+), 2 deletions(-) create mode 100644 src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarSyncer.php create mode 100644 src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/CalendarSyncerTest.php diff --git a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php index 6d0a476cb..c0d1fbb9a 100644 --- a/src/Bundle/ChillCalendarBundle/Entity/Calendar.php +++ b/src/Bundle/ChillCalendarBundle/Entity/Calendar.php @@ -550,7 +550,6 @@ class Calendar implements TrackCreationInterface, TrackUpdateInterface public function setStartDate(DateTimeImmutable $startDate): self { - dump('startDate', $startDate); $this->startDate = $startDate; return $this; diff --git a/src/Bundle/ChillCalendarBundle/Messenger/Handler/MSGraphChangeNotificationHandler.php b/src/Bundle/ChillCalendarBundle/Messenger/Handler/MSGraphChangeNotificationHandler.php index 183b26799..410c5f9a2 100644 --- a/src/Bundle/ChillCalendarBundle/Messenger/Handler/MSGraphChangeNotificationHandler.php +++ b/src/Bundle/ChillCalendarBundle/Messenger/Handler/MSGraphChangeNotificationHandler.php @@ -23,6 +23,8 @@ use Psr\Log\LoggerInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface; /** + * Handle notification of chagnes from MSGraph + * * @AsMessageHandler */ class MSGraphChangeNotificationHandler implements MessageHandlerInterface @@ -43,6 +45,26 @@ class MSGraphChangeNotificationHandler implements MessageHandlerInterface private UserRepository $userRepository; + public function __construct( + CalendarRangeRepository $calendarRangeRepository, + CalendarRangeSyncer $calendarRangeSyncer, + CalendarRepository $calendarRepository, + EntityManagerInterface $em, + InviteRepository $inviteRepository, + LoggerInterface $logger, + MapCalendarToUser $mapCalendarToUser, + UserRepository $userRepository + ) { + $this->calendarRangeRepository = $calendarRangeRepository; + $this->calendarRangeSyncer = $calendarRangeSyncer; + $this->calendarRepository = $calendarRepository; + $this->em = $em; + $this->inviteRepository = $inviteRepository; + $this->logger = $logger; + $this->mapCalendarToUser = $mapCalendarToUser; + $this->userRepository = $userRepository; + } + public function __invoke(MSGraphChangeNotificationMessage $changeNotificationMessage): void { $user = $this->userRepository->find($changeNotificationMessage->getUserId()); @@ -74,6 +96,8 @@ class MSGraphChangeNotificationHandler implements MessageHandlerInterface } elseif (null !== $invite = $this->inviteRepository->findOneBy(['remoteId' => $remoteId])) { $this->remoteToLocalSyncer->handleInviteSync($invite, $notification, $user); $this->em->flush(); + } else { + $this->logger->info(__CLASS__." id not found in any calendar, calendar range nor invite"); } } } diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarRangeSyncer.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarRangeSyncer.php index 39ea2a32a..d92e263fa 100644 --- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarRangeSyncer.php +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarRangeSyncer.php @@ -63,13 +63,15 @@ class CalendarRangeSyncer try { $new = $this->machineHttpClient->request( 'GET', - 'v1.0/' . $notification['resource'] + $notification['resource'] )->toArray(); } catch (ClientExceptionInterface $clientException) { $this->logger->warning(__CLASS__ . ' could not retrieve event from ms graph. Already deleted ?', [ 'calendarRangeId' => $calendarRange->getId(), 'remoteEventId' => $notification['resource'], ]); + + return; } $lastModified = RemoteEventConverter::convertStringDateWithTimezone($new['lastModifiedDateTime']); @@ -94,6 +96,9 @@ class CalendarRangeSyncer ]) ->preventEnqueueChanges = true ; + break; + default: + throw new \RuntimeException('This changeType is not suppored: '.$notification['changeType']); } } } diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarSyncer.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarSyncer.php new file mode 100644 index 000000000..ace9515ea --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraph/RemoteToLocalSync/CalendarSyncer.php @@ -0,0 +1,93 @@ +logger = $logger; + $this->machineHttpClient = $machineHttpClient; + } + + public function handleCalendarSync(Calendar $calendar, array $notification, User $user): void + { + switch ($notification['changeType']) { + case 'deleted': + $this->handleDeleteCalendar($calendar, $notification, $user); + break; + + case 'updated': + $this->handleUpdateCalendar($calendar, $notification, $user); + break; + + default: + throw new \RuntimeException("this change type is not supported: ".$notification['changeType']); + } + } + + private function handleDeleteCalendar(Calendar $calendar, array $notification, User $user): void + { + $calendar + ->setStatus(Calendar::STATUS_CANCELED) + ->setCalendarRange(null) + ; + $calendar->preventEnqueueChanges = true; + } + + private function handleUpdateCalendar(Calendar $calendar, array $notification, User $user): void + { + try { + $new = $this->machineHttpClient->request( + 'GET', + $notification['resource'] + )->toArray(); + } catch (ClientExceptionInterface $clientException) { + $this->logger->warning(__CLASS__ . ' could not retrieve event from ms graph. Already deleted ?', [ + 'calendarId' => $calendar->getId(), + 'remoteEventId' => $notification['resource'], + ]); + } + + $lastModified = RemoteEventConverter::convertStringDateWithTimezone( + $new['lastModifiedDateTime'] + ); + + if ($calendar->getRemoteAttributes()['lastModifiedDateTime'] === $lastModified->getTimestamp()) { + $this->logger->info(__CLASS__ . ' change key is equals. Source is probably a local update', [ + 'calendarRangeId' => $calendar->getId(), + 'remoteEventId' => $notification['resource'], + ]); + + return; + } + + $startDate = RemoteEventConverter::convertStringDateWithoutTimezone($new['start']['dateTime']); + $endDate = RemoteEventConverter::convertStringDateWithoutTimezone($new['end']['dateTime']); + + $calendar + ->setStartDate($startDate)->setEndDate($endDate) + ->setStatus(Calendar::STATUS_MOVED) + ->addRemoteAttributes([ + 'lastModifiedDateTime' => $lastModified->getTimestamp(), + 'changeKey' => $new['changeKey'], + ]) + ->preventEnqueueChanges = true + ; + } +} diff --git a/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/CalendarSyncerTest.php b/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/CalendarSyncerTest.php new file mode 100644 index 000000000..fb3da1ce6 --- /dev/null +++ b/src/Bundle/ChillCalendarBundle/Tests/RemoteCalendar/Connector/MSGraph/CalendarSyncerTest.php @@ -0,0 +1,194 @@ +setMainUser($user = new User()) + ->setCalendarRange($calendarRange = new CalendarRange()); + ; + $notification = json_decode(self::NOTIF_DELETE, true); + + $calendarSyncer->handleCalendarSync( + $calendar, + $notification['value'][0], + $user); + + $this->assertEquals(Calendar::STATUS_CANCELED, $calendar->getStatus()); + $this->assertNull($calendar->getCalendarRange()); + $this->assertTrue($calendar->preventEnqueueChanges); + } + + public function testHandleMoveCalendar(): void + { + $machineHttpClient = new MockHttpClient([ + new MockResponse(self::REMOTE_CALENDAR_NO_ATTENDEES, ['http_code' => 200]) + ]); + + $calendarSyncer = new CalendarSyncer( + new NullLogger(), + $machineHttpClient + ); + + $calendar = new Calendar(); + $calendar + ->setMainUser($user = new User()) + ->setStartDate(new \DateTimeImmutable('2020-01-01 10:00:00')) + ->setEndDate(new \DateTimeImmutable('2020-01-01 12:00:00')) + ->setCalendarRange(new CalendarRange()) + ->addRemoteAttributes([ + 'lastModifiedDateTime' => 0, + 'changeKey' => 'abcd', + ]) + ; + $notification = json_decode(self::NOTIF_UPDATE, true); + + $calendarSyncer->handleCalendarSync( + $calendar, + $notification['value'][0], + $user); + + $this->assertStringContainsString('2022-06-10T15:30:00', + $calendar->getStartDate()->format(\DateTimeImmutable::ATOM)); + $this->assertStringContainsString('2022-06-10T17:30:00', + $calendar->getEndDate()->format(\DateTimeImmutable::ATOM)); + $this->assertTrue($calendar->preventEnqueueChanges); + $this->assertEquals(Calendar::STATUS_MOVED, $calendar->getStatus()); + } +}