mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-27 18:13:48 +00:00
first bootstrap for handling calendar range sync frommsgraph
This commit is contained in:
@@ -34,6 +34,10 @@ class MachineHttpClient implements HttpClientInterface
|
||||
$this->machineTokenStorage = $machineTokenStorage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||
* @throws LogicException if method is not supported
|
||||
*/
|
||||
public function request(string $method, string $url, array $options = []): ResponseInterface
|
||||
{
|
||||
$options['headers'] = array_merge(
|
||||
|
@@ -73,6 +73,19 @@ class MapCalendarToUser
|
||||
return $value[0] ?? null;
|
||||
}
|
||||
|
||||
public function getSubscriptionSecret(User $user): string
|
||||
{
|
||||
if (!array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
|
||||
throw new LogicException('do not contains msgraph metadata');
|
||||
}
|
||||
|
||||
if (!array_key_exists(self::SECRET_SUBSCRIPTION_EVENT, $user->getAttributes()[self::METADATA_KEY])) {
|
||||
throw new LogicException('do not contains secret in msgraph');
|
||||
}
|
||||
|
||||
return $user->getAttributes()[self::METADATA_KEY][self::SECRET_SUBSCRIPTION_EVENT];
|
||||
}
|
||||
|
||||
public function getUserByEmail(string $email): ?array
|
||||
{
|
||||
$value = $this->machineHttpClient->request('GET', 'users', [
|
||||
@@ -105,6 +118,15 @@ class MapCalendarToUser
|
||||
>= (new DateTimeImmutable('now'))->getTimestamp();
|
||||
}
|
||||
|
||||
public function hasSubscriptionSecret(User $user): bool
|
||||
{
|
||||
if (!array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return array_key_exists(self::SECRET_SUBSCRIPTION_EVENT, $user->getAttributes()[self::METADATA_KEY]);
|
||||
}
|
||||
|
||||
public function hasUserId(User $user): bool
|
||||
{
|
||||
if (!array_key_exists(self::METADATA_KEY, $user->getAttributes())) {
|
||||
|
@@ -19,6 +19,7 @@ use Chill\PersonBundle\Entity\Person;
|
||||
use Chill\PersonBundle\Templating\Entity\PersonRenderInterface;
|
||||
use DateTimeImmutable;
|
||||
use DateTimeZone;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Templating\EngineInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -28,10 +29,16 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
*/
|
||||
class RemoteEventConverter
|
||||
{
|
||||
/**
|
||||
* valid when the remote string contains also a timezone, like in
|
||||
* lastModifiedDate
|
||||
*/
|
||||
public const REMOTE_DATETIMEZONE_FORMAT = 'Y-m-d\\TH:i:s.u?P';
|
||||
|
||||
private const REMOTE_DATE_FORMAT = 'Y-m-d\TH:i:s.u0';
|
||||
|
||||
private const REMOTE_DATETIME_WITHOUT_TZ_FORMAT = 'Y-m-d\TH:i:s.u?';
|
||||
|
||||
private DateTimeZone $defaultDateTimeZone;
|
||||
|
||||
private EngineInterface $engine;
|
||||
@@ -147,6 +154,34 @@ class RemoteEventConverter
|
||||
);
|
||||
}
|
||||
|
||||
public static function convertStringDateWithoutTimezone(string $date): DateTimeImmutable
|
||||
{
|
||||
$d = DateTimeImmutable::createFromFormat(
|
||||
self::REMOTE_DATETIME_WITHOUT_TZ_FORMAT,
|
||||
$date,
|
||||
self::getRemoteTimeZone()
|
||||
);
|
||||
|
||||
if (false === $d) {
|
||||
throw new RuntimeException("could not convert string date to datetime: {$date}");
|
||||
}
|
||||
|
||||
return $d->setTimezone((new DateTimeImmutable())->getTimezone());
|
||||
}
|
||||
|
||||
public static function convertStringDateWithTimezone(string $date): DateTimeImmutable
|
||||
{
|
||||
$d = DateTimeImmutable::createFromFormat(self::REMOTE_DATETIMEZONE_FORMAT, $date);
|
||||
|
||||
if (false === $d) {
|
||||
throw new RuntimeException("could not convert string date to datetime: {$date}");
|
||||
}
|
||||
|
||||
$d->setTimezone((new DateTimeImmutable())->getTimezone());
|
||||
|
||||
return $d;
|
||||
}
|
||||
|
||||
public function convertToRemote(array $event): RemoteEvent
|
||||
{
|
||||
$startDate =
|
||||
|
@@ -0,0 +1,97 @@
|
||||
<?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\CalendarRange;
|
||||
use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\MachineHttpClient;
|
||||
use Chill\CalendarBundle\RemoteCalendar\Connector\MSGraph\RemoteEventConverter;
|
||||
use Chill\MainBundle\Entity\User;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
class CalendarRangeSyncer
|
||||
{
|
||||
private EntityManagerInterface $em;
|
||||
|
||||
private LoggerInterface $logger;
|
||||
|
||||
private HttpClientInterface $machineHttpClient;
|
||||
|
||||
/**
|
||||
* @param EntityManagerInterface $em
|
||||
* @param LoggerInterface $logger
|
||||
* @param MachineHttpClient $machineHttpClient
|
||||
*/
|
||||
public function __construct(
|
||||
EntityManagerInterface $em,
|
||||
LoggerInterface $logger,
|
||||
HttpClientInterface $machineHttpClient
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->logger = $logger;
|
||||
$this->machineHttpClient = $machineHttpClient;
|
||||
}
|
||||
|
||||
|
||||
public function handleCalendarRangeSync(CalendarRange $calendarRange, array $notification, User $user): void
|
||||
{
|
||||
switch ($notification['changeType']) {
|
||||
case 'deleted':
|
||||
// test if the notification is not linked to a Calendar
|
||||
if (null !== $calendarRange->getCalendar()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->info(__CLASS__ . ' remove a calendar range because deleted on remote calendar');
|
||||
$this->em->remove($calendarRange);
|
||||
|
||||
break;
|
||||
|
||||
case 'updated':
|
||||
try {
|
||||
$new = $this->machineHttpClient->request(
|
||||
'GET',
|
||||
'v1.0/' . $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'],
|
||||
]);
|
||||
}
|
||||
|
||||
$lastModified = RemoteEventConverter::convertStringDateWithTimezone($new['lastModifiedDateTime']);
|
||||
|
||||
if ($calendarRange->getRemoteAttributes()['lastModifiedDateTime'] === $lastModified->getTimestamp()) {
|
||||
$this->logger->info(__CLASS__ . ' change key is equals. Source is probably a local update', [
|
||||
'calendarRangeId' => $calendarRange->getId(),
|
||||
'remoteEventId' => $notification['resource'],
|
||||
]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$startDate = RemoteEventConverter::convertStringDateWithoutTimezone($new['start']['dateTime']);
|
||||
$endDate = RemoteEventConverter::convertStringDateWithoutTimezone($new['end']['dateTime']);
|
||||
|
||||
$calendarRange
|
||||
->setStartDate($startDate)->setEndDate($endDate)
|
||||
->addRemoteAttributes([
|
||||
'lastModifiedDateTime' => $lastModified->getTimestamp(),
|
||||
'changeKey' => $new['changeKey'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user