defaultDateTimeZone = (new \DateTimeImmutable())->getTimezone(); $this->remoteDateTimeZone = self::getRemoteTimeZone(); } /** * Transform a CalendarRange into a representation suitable for storing into MSGraph. * * @return array an array representation for event in MS Graph */ public function calendarRangeToEvent(CalendarRange $calendarRange): array { return [ 'subject' => $this->translator->trans('remote_calendar.calendar_range_title'), 'start' => [ 'dateTime' => $calendarRange->getStartDate()->setTimezone($this->remoteDateTimeZone) ->format(self::REMOTE_DATE_FORMAT), 'timeZone' => 'UTC', ], 'end' => [ 'dateTime' => $calendarRange->getEndDate()->setTimezone($this->remoteDateTimeZone) ->format(self::REMOTE_DATE_FORMAT), 'timeZone' => 'UTC', ], 'attendees' => [ [ 'emailAddress' => [ 'address' => $calendarRange->getUser()->getEmailCanonical(), 'name' => $calendarRange->getUser()->getLabel(), ], ], ], 'isReminderOn' => false, 'location' => $this->locationConverter->locationToRemote($calendarRange->getLocation()), ]; } public function calendarToEvent(Calendar $calendar): array { $result = array_merge( [ 'subject' => '[Chill] '. implode( ', ', $calendar->getPersons()->map(fn (Person $p) => $this->personRender->renderString($p, []))->toArray() ), 'start' => [ 'dateTime' => $calendar->getStartDate()->setTimezone($this->remoteDateTimeZone) ->format(self::REMOTE_DATE_FORMAT), 'timeZone' => 'UTC', ], 'end' => [ 'dateTime' => $calendar->getEndDate()->setTimezone($this->remoteDateTimeZone) ->format(self::REMOTE_DATE_FORMAT), 'timeZone' => 'UTC', ], 'allowNewTimeProposals' => false, 'transactionId' => 'calendar_'.$calendar->getId(), 'body' => [ 'contentType' => 'text', 'content' => $this->engine->render( '@ChillCalendar/MSGraph/calendar_event_body.html.twig', ['calendar' => $calendar] ), ], 'responseRequested' => true, 'isReminderOn' => false, ], $this->calendarToEventAttendeesOnly($calendar) ); if ($calendar->hasLocation()) { $result['location'] = $this->locationConverter->locationToRemote($calendar->getLocation()); } return $result; } public function calendarToEventAttendeesOnly(Calendar $calendar): array { return [ 'attendees' => $calendar->getInvites()->map( fn (Invite $i) => $this->buildInviteToAttendee($i) )->toArray(), ]; } public function convertAvailabilityToRemoteEvent(array $event): RemoteEvent { $startDate = \DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['start']['dateTime'], $this->remoteDateTimeZone) ->setTimezone($this->defaultDateTimeZone); $endDate = \DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['end']['dateTime'], $this->remoteDateTimeZone) ->setTimezone($this->defaultDateTimeZone); return new RemoteEvent( uniqid('generated_'), $this->translator->trans('remote_ms_graph.freebusy_statuses.'.$event['status']), '', $startDate, $endDate ); } 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 = \DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['start']['dateTime'], $this->remoteDateTimeZone) ->setTimezone($this->defaultDateTimeZone); $endDate = \DateTimeImmutable::createFromFormat(self::REMOTE_DATE_FORMAT, $event['end']['dateTime'], $this->remoteDateTimeZone) ->setTimezone($this->defaultDateTimeZone); return new RemoteEvent( $event['id'], $event['subject'], '', $startDate, $endDate, $event['isAllDay'] ); } public function getLastModifiedDate(array $event): \DateTimeImmutable { $date = \DateTimeImmutable::createFromFormat(self::REMOTE_DATETIMEZONE_FORMAT, $event['lastModifiedDateTime']); if (false === $date) { $date = \DateTimeImmutable::createFromFormat(self::REMOTE_DATETIMEZONE_FORMAT_ALT, $event['lastModifiedDateTime']); } if (false === $date) { $this->logger->error(self::class.' Could not convert lastModifiedDate', [ 'actual' => $event['lastModifiedDateTime'], 'format' => self::REMOTE_DATETIMEZONE_FORMAT, 'format_alt' => self::REMOTE_DATETIMEZONE_FORMAT_ALT, ]); throw new \RuntimeException(sprintf('could not convert lastModifiedDate: %s, expected format: %s', $event['lastModifiedDateTime'], self::REMOTE_DATETIMEZONE_FORMAT.' and '.self::REMOTE_DATETIMEZONE_FORMAT_ALT)); } return $date; } /** * Return a string which format a DateTime to string. To be used in POST requests,. */ public static function getRemoteDateTimeSimpleFormat(): string { return 'Y-m-d\TH:i:s'; } public static function getRemoteTimeZone(): \DateTimeZone { return new \DateTimeZone('UTC'); } private function buildInviteToAttendee(Invite $invite): array { return [ 'emailAddress' => [ 'address' => $invite->getUser()->getEmail(), 'name' => $invite->getUser()->getLabel(), ], 'type' => 'Required', ]; } }