diff --git a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php index 8e384ff33..7eb1b7c55 100644 --- a/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php +++ b/src/Bundle/ChillCalendarBundle/RemoteCalendar/Connector/MSGraphRemoteCalendarConnector.php @@ -17,6 +17,7 @@ use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\MapCalendarToUser; use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\OnBehalfOfUserHttpClient; use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\OnBehalfOfUserTokenStorage; use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\RemoteEventConverter; +use Chill\CalendarBundle\Repository\CalendarRangeRepository; use Chill\MainBundle\Entity\User; use DateTimeImmutable; use Psr\Log\LoggerInterface; @@ -27,6 +28,8 @@ use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface; class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface { + private CalendarRangeRepository $calendarRangeRepository; + private LoggerInterface $logger; private MachineHttpClient $machineHttpClient; @@ -42,6 +45,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface private OnBehalfOfUserHttpClient $userHttpClient; public function __construct( + CalendarRangeRepository $calendarRangeRepository, MachineHttpClient $machineHttpClient, MapCalendarToUser $mapCalendarToUser, LoggerInterface $logger, @@ -50,6 +54,7 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface RemoteEventConverter $remoteEventConverter, UrlGeneratorInterface $urlGenerator ) { + $this->calendarRangeRepository = $calendarRangeRepository; $this->machineHttpClient = $machineHttpClient; $this->mapCalendarToUser = $mapCalendarToUser; $this->logger = $logger; @@ -91,7 +96,21 @@ class MSGraphRemoteCalendarConnector implements RemoteCalendarConnectorInterface ] )->toArray(); - return array_map(function ($item) { return $this->remoteEventConverter->convertToRemote($item); }, $bareEvents['value']); + $ids = array_map(function ($item) { return $item['id']; }, $bareEvents['value']); + $existingIdsInRange = $this->calendarRangeRepository->findRemoteIdsPresent($ids); + + return array_map( + function ($item) { + return $this->remoteEventConverter->convertToRemote($item); + }, + // filter all event to keep only the one not in range + array_filter( + $bareEvents['value'], + function ($item) use ($existingIdsInRange) { + return (!$existingIdsInRange[$item['id']]) ?? true; + } + ) + ); } catch (ClientExceptionInterface $e) { if (403 === $e->getResponse()->getStatusCode()) { return $this->getScheduleTimesForUser($user, $startDate, $endDate); diff --git a/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php b/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php index 33feb8401..70746073f 100644 --- a/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php +++ b/src/Bundle/ChillCalendarBundle/Repository/CalendarRangeRepository.php @@ -13,8 +13,10 @@ namespace Chill\CalendarBundle\Repository; use Chill\CalendarBundle\Entity\CalendarRange; use Chill\MainBundle\Entity\User; +use Doctrine\DBAL\Types\Types; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Doctrine\ORM\Query\ResultSetMapping; use Doctrine\ORM\QueryBuilder; use Doctrine\Persistence\ObjectRepository; @@ -22,8 +24,11 @@ class CalendarRangeRepository implements ObjectRepository { private EntityRepository $repository; + private EntityManagerInterface $em; + public function __construct(EntityManagerInterface $entityManager) { + $this->em = $entityManager; $this->repository = $entityManager->getRepository(CalendarRange::class); } @@ -107,4 +112,54 @@ class CalendarRangeRepository implements ObjectRepository 'endDate' => $to, ]); } + + /** + * Given a list of remote ids, return an array where + * keys are the remoteIds, and value is a boolean, true if the + * id is present in database. + * + * @param array|list $remoteIds + * @return array + */ + public function findRemoteIdsPresent(array $remoteIds): array + { + if (0 === count($remoteIds)) { + return []; + } + + $sql = "SELECT + sq.remoteId as remoteid, + EXISTS (SELECT 1 FROM chill_calendar.calendar_range cr WHERE cr.remoteId = sq.remoteId) AS present + FROM + ( + VALUES %remoteIds% + ) AS sq(remoteId); + "; + + $remoteIdsStr = \implode( + ', ', + array_fill(0, count($remoteIds), '((?))') + ); + + $rsm = new ResultSetMapping(); + $rsm + ->addScalarResult('remoteid', 'remoteId', Types::STRING) + ->addScalarResult('present', 'present', Types::BOOLEAN); + + $rows = $this->em + ->createNativeQuery( + \strtr($sql, ['%remoteIds%' => $remoteIdsStr]), + $rsm + ) + ->setParameters(array_values($remoteIds)) + ->getResult(); + + $results = []; + + foreach ($rows as $r) { + $results[$r['remoteId']] = $r['present']; + } + + return $results; + } }