use matching occurrence
Signed-off-by: dartcafe <github@dartcafe.de>
This commit is contained in:
Родитель
9aa69a06fd
Коммит
58b24f9cdc
|
@ -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 self::TYPE_DATE_TIME;
|
||||
}
|
||||
|
||||
return $occurencies;
|
||||
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 null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 getBaseEnd() : ?DateTimeImmutable {
|
||||
if (isset($this->event['DTEND'][0])) {
|
||||
return $this->event['DTEND'][0];
|
||||
}
|
||||
return array_merge($baseRRule, $rRule);
|
||||
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] ?? '';
|
||||
}
|
||||
|
||||
public function getCalDav(): array {
|
||||
return $this->calDav;
|
||||
// Getters and functions for recurrence handling
|
||||
public function getHasRRule(): bool {
|
||||
return $this->hasRRule;
|
||||
}
|
||||
|
||||
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,15 +126,16 @@ 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);
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (Util::getVersion()[0] < 24) {
|
||||
$calendars[] = [
|
||||
'name' => $calendar->getDisplayName(),
|
||||
'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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче