mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-28 10:33:49 +00:00
db constraint with unique remoteId if set, handle sync with tests
This commit is contained in:
@@ -31,7 +31,7 @@ class RemoteEventConverter
|
||||
{
|
||||
/**
|
||||
* valid when the remote string contains also a timezone, like in
|
||||
* lastModifiedDate
|
||||
* lastModifiedDate.
|
||||
*/
|
||||
public const REMOTE_DATETIMEZONE_FORMAT = 'Y-m-d\\TH:i:s.u?P';
|
||||
|
||||
|
@@ -17,6 +17,7 @@ use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\RemoteEventConverter;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
@@ -29,8 +30,6 @@ class CalendarRangeSyncer
|
||||
private HttpClientInterface $machineHttpClient;
|
||||
|
||||
/**
|
||||
* @param EntityManagerInterface $em
|
||||
* @param LoggerInterface $logger
|
||||
* @param MachineHttpClient $machineHttpClient
|
||||
*/
|
||||
public function __construct(
|
||||
@@ -43,7 +42,6 @@ class CalendarRangeSyncer
|
||||
$this->machineHttpClient = $machineHttpClient;
|
||||
}
|
||||
|
||||
|
||||
public function handleCalendarRangeSync(CalendarRange $calendarRange, array $notification, User $user): void
|
||||
{
|
||||
switch ($notification['changeType']) {
|
||||
@@ -94,11 +92,12 @@ class CalendarRangeSyncer
|
||||
'lastModifiedDateTime' => $lastModified->getTimestamp(),
|
||||
'changeKey' => $new['changeKey'],
|
||||
])
|
||||
->preventEnqueueChanges = true
|
||||
;
|
||||
->preventEnqueueChanges = true;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \RuntimeException('This changeType is not suppored: '.$notification['changeType']);
|
||||
throw new RuntimeException('This changeType is not suppored: ' . $notification['changeType']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,13 +1,27 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\RemoteToLocalSync;
|
||||
|
||||
use Chill\CalendarBundle\Entity\Calendar;
|
||||
use Chill\CalendarBundle\Entity\Invite;
|
||||
use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\RemoteEventConverter;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Chill\MainBundle\Repository\UserRepositoryInterface;
|
||||
use LogicException;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
use function in_array;
|
||||
|
||||
class CalendarSyncer
|
||||
{
|
||||
@@ -15,14 +29,13 @@ class CalendarSyncer
|
||||
|
||||
private HttpClientInterface $machineHttpClient;
|
||||
|
||||
/**
|
||||
* @param LoggerInterface $logger
|
||||
* @param HttpClientInterface $machineHttpClient
|
||||
*/
|
||||
public function __construct(LoggerInterface $logger, HttpClientInterface $machineHttpClient)
|
||||
private UserRepositoryInterface $userRepository;
|
||||
|
||||
public function __construct(LoggerInterface $logger, HttpClientInterface $machineHttpClient, UserRepositoryInterface $userRepository)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
$this->machineHttpClient = $machineHttpClient;
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
public function handleCalendarSync(Calendar $calendar, array $notification, User $user): void
|
||||
@@ -30,14 +43,16 @@ class CalendarSyncer
|
||||
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']);
|
||||
throw new RuntimeException('this change type is not supported: ' . $notification['changeType']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +60,7 @@ class CalendarSyncer
|
||||
{
|
||||
$calendar
|
||||
->setStatus(Calendar::STATUS_CANCELED)
|
||||
->setCalendarRange(null)
|
||||
;
|
||||
->setCalendarRange(null);
|
||||
$calendar->preventEnqueueChanges = true;
|
||||
}
|
||||
|
||||
@@ -64,6 +78,10 @@ class CalendarSyncer
|
||||
]);
|
||||
}
|
||||
|
||||
if (false === $new['isOrganizer']) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lastModified = RemoteEventConverter::convertStringDateWithTimezone(
|
||||
$new['lastModifiedDateTime']
|
||||
);
|
||||
@@ -77,17 +95,91 @@ class CalendarSyncer
|
||||
return;
|
||||
}
|
||||
|
||||
$this->syncAttendees($calendar, $new['attendees']);
|
||||
|
||||
$startDate = RemoteEventConverter::convertStringDateWithoutTimezone($new['start']['dateTime']);
|
||||
$endDate = RemoteEventConverter::convertStringDateWithoutTimezone($new['end']['dateTime']);
|
||||
|
||||
if ($startDate->getTimestamp() !== $calendar->getStartDate()->getTimestamp()) {
|
||||
$calendar->setStartDate($startDate)->setStatus(Calendar::STATUS_MOVED);
|
||||
}
|
||||
|
||||
if ($endDate->getTimestamp() !== $calendar->getEndDate()->getTimestamp()) {
|
||||
$calendar->setEndDate($endDate)->setStatus(Calendar::STATUS_MOVED);
|
||||
}
|
||||
|
||||
$calendar
|
||||
->setStartDate($startDate)->setEndDate($endDate)
|
||||
->setStatus(Calendar::STATUS_MOVED)
|
||||
->addRemoteAttributes([
|
||||
'lastModifiedDateTime' => $lastModified->getTimestamp(),
|
||||
'changeKey' => $new['changeKey'],
|
||||
])
|
||||
->preventEnqueueChanges = true
|
||||
;
|
||||
->preventEnqueueChanges = true;
|
||||
}
|
||||
|
||||
private function syncAttendees(Calendar $calendar, array $attendees): void
|
||||
{
|
||||
$emails = [];
|
||||
|
||||
foreach ($attendees as $attendee) {
|
||||
$status = $attendee['status']['response'];
|
||||
|
||||
if ('organizer' === $status) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$email = $attendee['emailAddress']['address'];
|
||||
$emails[] = strtolower($email);
|
||||
$user = $this->userRepository->findOneByUsernameOrEmail($email);
|
||||
|
||||
if (null === $user) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$calendar->isInvited($user)) {
|
||||
$calendar->addUser($user);
|
||||
}
|
||||
|
||||
$invite = $calendar->getInviteForUser($user);
|
||||
|
||||
switch ($status) {
|
||||
// none, organizer, tentativelyAccepted, accepted, declined, notResponded.
|
||||
case 'none':
|
||||
case 'notResponded':
|
||||
$invite->setStatus(Invite::PENDING);
|
||||
|
||||
break;
|
||||
|
||||
case 'organizer':
|
||||
throw new LogicException('should not happens');
|
||||
|
||||
break;
|
||||
|
||||
case 'tentativelyAccepted':
|
||||
$invite->setStatus(Invite::TENTATIVELY_ACCEPTED);
|
||||
|
||||
break;
|
||||
|
||||
case 'accepted':
|
||||
$invite->setStatus(Invite::ACCEPTED);
|
||||
|
||||
break;
|
||||
|
||||
case 'declined':
|
||||
$invite->setStatus(Invite::DECLINED);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new LogicException('should not happens, not implemented: ' . $status);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($calendar->getUsers() as $user) {
|
||||
if (!in_array(strtolower($user->getEmailCanonical()), $emails, true)) {
|
||||
$calendar->removeUser($user);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user