Signed-off-by: dartcafe <github@dartcafe.de>
This commit is contained in:
dartcafe 2022-05-02 10:04:45 +02:00
Родитель 9aa69a06fd
Коммит 58b24f9cdc
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: CCE73CEF3035D3C8
2 изменённых файлов: 202 добавлений и 72 удалений

Просмотреть файл

@ -23,37 +23,70 @@
namespace OCA\Polls\Model;
use DateTimeImmutable;
use DateInterval;
use \OCP\Calendar\ICalendar;
use RRule\RRule;
class CalendarEvent implements \JsonSerializable {
public const TYPE_DATE = 'date';
public const TYPE_DATE_TIME = 'dateTime';
private const MAX_OCURRENCIES = 100;
/** @var array */
protected $calDav;
protected $iCal;
/** @var array */
protected $occurrences = null;
/** @var bool */
protected $hasRRule;
/** @var RRule */
protected $rRule = null;
/** @var int */
protected $matchOccurrence = null;
/** @var array */
protected $event;
/** @var DateTimeImmutable */
protected $filterFrom;
/** @var DateTimeImmutable */
protected $filterTo;
/** @var ICalendar */
protected $calendar;
public function __construct(
array $calDav,
ICalendar $calendar
array $iCal,
ICalendar $calendar,
DateTimeImmutable $filterFrom = null,
DateTimeImmutable $filterTo = null
) {
$this->calDav = $calDav;
$this->iCal = $iCal;
$this->calendar = $calendar;
$this->event = $this->calDav['objects'][0];
}
public function getAllDay(): string {
return ($this->getEnd() - $this->getStart() === 86400) ? $this->event['DTSTART'][0]->format('Y-m-d') : '';
$this->event = $this->iCal['objects'][0];
$this->filterFrom = $filterFrom;
$this->filterTo = $filterTo;
$this->hasRRule = isset($this->event['RRULE']);
$this->buildRRule();
$this->calculateOccurrences();
}
// Getters for calendar information
public function getCalendarName(): ?string {
return $this->calendar->getDisplayName();
}
public function setOccurrence(int $index) {
if ($this->occurrences) {
$this->matchOccurrence = $index;
}
}
public function getCalendarKey(): string {
return $this->calendar->getKey();
}
@ -62,8 +95,9 @@ class CalendarEvent implements \JsonSerializable {
return $this->calendar->getDisplayColor();
}
// Getters for commont eventdescription
public function getId(): string {
return $this->calDav['id'];
return $this->iCal['id'];
}
public function getUID(): string {
@ -82,58 +116,127 @@ class CalendarEvent implements \JsonSerializable {
return $this->event['LOCATION'][0] ?? '';
}
public function getStart(): int {
return isset($this->event['DTSTART'][0]) ? $this->event['DTSTART'][0]->getTimestamp() : 0;
// Getters for the event's scheduling information
public function getAllDay(): string {
return $this->getType() === self::TYPE_DATE ? $this->event['DTSTART'][0]->format('Y-m-d') : '';
}
public function getEnd(): int {
return isset($this->event['DTEND'][0])? $this->event['DTEND'][0]->getTimestamp() : 0;
}
public function getHasRRule(): bool {
return isset($this->event['RRULE']);
}
public function getOccurencies(): array {
$occurencies = [];
if ($this->getHasRRule()) {
$rrule = new RRule($this->getRRule());
foreach ($rrule as $occurence) {
$occurencies[] = $occurence->format('r');
if (count($occurencies) > 99) {
return $occurencies;
}
public function getType(): string {
if (isset($this->event['DTSTART'][1]['VALUE'])) {
if (strtoupper($this->event['DTSTART'][1]['VALUE']) === 'DATE') {
return self::TYPE_DATE;
}
}
return $occurencies;
return self::TYPE_DATE_TIME;
}
/**
* @return false|string[]
*
* @psalm-return array<string, string>|false
*/
public function getRRule() {
$rRule = [];
$baseRRule = ['DTSTART' => $this->event['DTSTART'][0]];
if ($this->getHasRRule()) {
preg_match_all("/([^;= ]+)=([^;= ]+)/", $this->event['RRULE'][0], $r);
$rRule = array_combine($r[1], $r[2]);
public function getBaseStart() : ?DateTimeImmutable {
if (isset($this->event['DTSTART'][0])) {
return $this->event['DTSTART'][0];
// return (new DateTimeImmutable())->setTimestamp($this->event['DTSTART'][0]->getTimestamp());
}
return array_merge($baseRRule, $rRule);
return null;
}
public function getBaseEnd() : ?DateTimeImmutable {
if (isset($this->event['DTEND'][0])) {
return $this->event['DTEND'][0];
}
return null;
}
public function getStart() : DateTimeImmutable {
if ($this->occurrences != null && $this->matchOccurrence !== null) {
return DateTimeImmutable::createFromMutable($this->occurrences[$this->matchOccurrence]);
}
return $this->getBaseStart();
}
public function getEnd(): ?DateTimeImmutable {
if ($this->getBaseEnd() !== null) {
return $this->getStart()->add($this->getDiff());
}
return null;
}
public function getDiff() : ?DateInterval {
if ($this->getBaseStart() && $this->getBaseEnd()) {
return $this->getBaseStart()->diff($this->getBaseEnd());
// return $this->getBaseEnd()->getTimestamp() - $this->getBaseStart()->getTimestamp();
}
return null;
}
public function getDuration() : int {
if ($this->getBaseStart() && $this->getBaseEnd()) {
return $this->getBaseEnd()->getTimestamp() - $this->getBaseStart()->getTimestamp();
}
return 0;
}
public function getStatus(): string {
// TODO: Understand if the status is the status of the base event or occurrency
// Currently the status is taken from the base event.
return $this->event['STATUS'][0] ?? '';
}
// Getters and functions for recurrence handling
public function getHasRRule(): bool {
return $this->hasRRule;
}
public function getCalDav(): array {
return $this->calDav;
public function getRRule(): ?array {
return $this->rRule;
}
public function getOccurrences() : ?array {
return $this->occurrences;
}
private function buildRRule() : void {
if (!$this->getHasRRule()) {
return;
}
preg_match_all("/([^;= ]+)=([^;= ]+)/", $this->event['RRULE'][0], $r);
$this->rRule = array_combine($r[1], $r[2]);
$this->rRule['DTSTART'] = $this->getBaseStart();
// force limiting occurrences to the filter boundary, if set
if ($this->filterTo) {
$this->rRule['UNTIL'] = $this->filterTo;
}
}
private function calculateOccurrences(): void {
if (!$this->getHasRRule()) {
return;
}
$rRule = new RRule($this->rRule);
foreach ($rRule as $occurrence) {
if ($this->filterFrom
&& (($occurrence->getTimestamp() + $this->getDuration()) < $this->filterFrom->getTimestamp())) {
// skip occurrences before filter span
continue;
}
if ($this->filterTo && $occurrence->getTimestamp() > $this->filterTo->getTimestamp()) {
// skip occurrences after filter span
return;
}
$this->occurrences[] = $occurrence;
// prevent endles loop, if no until is set
if (count($this->occurrences) > self::MAX_OCURRENCIES - 1) {
return;
}
}
}
public function getICal(): array {
return $this->iCal;
}
public function jsonSerialize(): array {
@ -145,15 +248,22 @@ class CalendarEvent implements \JsonSerializable {
'displayColor' => $this->getDisplayColor(),
'allDay' => $this->getAllDay(),
'description' => $this->getDescription(),
'end' => $this->getEnd(),
'start' => $this->getStart()->getTimestamp(),
'location' => $this->getLocation(),
'start' => $this->getStart(),
'end' => $this->getEnd()->getTimestamp(),
'status' => $this->getStatus(),
'summary' => $this->getSummary(),
'calDav' => $this->getCalDav(),
'hasRRule' => $this->getHasRRule(),
'rRule' => $this->getRRule(),
'occurencies' => $this->getOccurencies(),
// 'duration' => $this->getDuration(),
// 'iCal' => $this->getICal(),
// 'hasRRule' => $this->getHasRRule(),
// 'rRule' => $this->getRRule(),
// 'type' => $this->getType(),
// 'timezone' => $this->getBaseStart()->getTimeZone(),
// 'occurrences' => $this->getOccurrences(),
// 'times' => [
// 'start' => $this->getStart(),
// 'end' => $this->getEnd(),
// ],
];
}
}

Просмотреть файл

@ -25,6 +25,7 @@
namespace OCA\Polls\Service;
use DateTime;
use DateTimeImmutable;
use OCP\Calendar\ICalendar;
use OCP\Calendar\IManager as CalendarManager;
use OCP\Util;
@ -42,6 +43,9 @@ class CalendarService {
/** @var ICalendar[] */
private $calendars;
/** @var array */
private $calendarMapKeys;
/** @var PreferencesService */
private $preferencesService;
@ -82,6 +86,7 @@ class CalendarService {
}
$this->calendars = $this->calendarManager->getCalendarsForPrincipal($principalUri);
// $this->calendars[] = 'ncyagstde-2';
return $this->calendars;
}
@ -95,15 +100,17 @@ class CalendarService {
public function getEvents(DateTime $from, DateTime $to): array {
if (Util::getVersion()[0] < 24) {
// deprecated since NC24
\OC::$server->getLogger()->error('calling legacy version');
\OC::$server->getLogger()->debug('calling legacy version');
return $this->getEventsLegcy($from, $to);
}
$from = DateTimeImmutable::createFromMutable($from);
$to = DateTimeImmutable::createFromMutable($to);
// use from NC24 on
$events = [];
$query = $this->calendarManager->newQuery($this->currentUser->getPrincipalUri());
$query->setTimerangeStart(\DateTimeImmutable::createFromMutable($from));
$query->setTimerangeEnd(\DateTimeImmutable::createFromMutable($to));
$query->setTimerangeStart($from);
$query->setTimerangeEnd($to);
foreach ($this->calendars as $calendar) {
if (in_array($calendar->getKey(), json_decode($this->preferences->getPreferences())->checkCalendars)) {
@ -119,14 +126,15 @@ class CalendarService {
continue;
}
$calendarEvent = new CalendarEvent($event, $calendar);
// since we get back recurring events of other days, just make sure this event
// matches the search pattern
// TODO: identify possible time zone issues, when handling all day events
if (($from->getTimestamp() < $calendarEvent->getEnd())
&& ($to->getTimestamp() > $calendarEvent->getStart())) {
$calendarEvent = new CalendarEvent($event, $calendar, $from, $to);
if ($calendarEvent->getOccurrences()) {
for ($index = 0; $index < count($calendarEvent->getOccurrences()); $index++) {
$calendarEvent->setOccurrence($index);
array_push($events, $calendarEvent);
}
} else {
array_push($events, $calendarEvent);
}
array_push($events, $calendarEvent);
}
return $events;
}
@ -163,7 +171,7 @@ class CalendarService {
$foundEvents = $calendar->search('', ['SUMMARY'], ['timerange' => ['start' => $from, 'end' => $to]]);
// \OC::$server->getLogger()->error('foundEvents: ' . json_encode($foundEvents));
foreach ($foundEvents as $event) {
$calendarEvent = new CalendarEvent($event, $calendar);
$calendarEvent = new CalendarEvent($event, $calendar, $from, $to);
// since we get back recurring events of other days, just make sure this event
// matches the search pattern
// TODO: identify possible time zone issues, when handling all day events
@ -187,12 +195,24 @@ class CalendarService {
public function getCalendars(): array {
$calendars = [];
foreach ($this->calendars as $calendar) {
$calendars[] = [
'name' => $calendar->getDisplayName(),
'key' => $calendar->getKey(),
'displayColor' => $calendar->getDisplayColor(),
'permissions' => $calendar->getPermissions(),
];
if (Util::getVersion()[0] < 24) {
$calendars[] = [
'key' => $calendar->getKey(),
'calendarUri' => '', // since NC23
'name' => $calendar->getDisplayName(),
'displayColor' => $calendar->getDisplayColor(),
'permissions' => $calendar->getPermissions(),
];
} else {
$calendars[] = [
'key' => $calendar->getKey(),
'calendarUri' => $calendar->getUri(), // since NC23
'name' => $calendar->getDisplayName(),
'displayColor' => $calendar->getDisplayColor(),
'permissions' => $calendar->getPermissions(),
'calendar' => $calendar,
];
}
}
return $calendars;
}