Skip to content

Commit

Permalink
fix: RDATE and EXDATE property instances
Browse files Browse the repository at this point in the history
Signed-off-by: SebastianKrupinski <[email protected]>
  • Loading branch information
SebastianKrupinski authored and backportbot[bot] committed Nov 15, 2024
1 parent aba18ba commit 2e807c9
Show file tree
Hide file tree
Showing 4 changed files with 496 additions and 48 deletions.
12 changes: 10 additions & 2 deletions apps/dav/lib/CalDAV/EventReader.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,12 @@ public function __construct(VCalendar|VEvent|array|string $input, ?string $uid =
}
// evaluate if RDATE exist and construct iterator
if (isset($this->baseEvent->RDATE)) {
$dates = [];
foreach ($this->baseEvent->RDATE as $entry) {
$dates[] = $entry->getValue();
}
$this->rdateIterator = new EventReaderRDate(
$this->baseEvent->RDATE->getValue(),
implode(',', $dates),
$this->baseEventStartDate
);
}
Expand All @@ -214,8 +218,12 @@ public function __construct(VCalendar|VEvent|array|string $input, ?string $uid =
}
// evaluate if EXDATE exist and construct iterator
if (isset($this->baseEvent->EXDATE)) {
$dates = [];
foreach ($this->baseEvent->EXDATE as $entry) {
$dates[] = $entry->getValue();
}
$this->edateIterator = new EventReaderRDate(
$this->baseEvent->EXDATE->getValue(),
implode(',', $dates),
$this->baseEventStartDate
);
}
Expand Down
78 changes: 39 additions & 39 deletions apps/dav/lib/CalDAV/Schedule/IMipService.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public function buildBodyData(VEvent $vEvent, ?VEvent $oldVEvent): array {

$data['meeting_when_html'] = $oldMeetingWhen !== $data['meeting_when'] ? sprintf("<span style='text-decoration: line-through'>%s</span><br />%s", $oldMeetingWhen, $data['meeting_when']) : $data['meeting_when'];
}
// generate occuring next string
// generate occurring next string
if ($eventReaderCurrent->recurs()) {
$data['meeting_occurring'] = $this->generateOccurringString($eventReaderCurrent);
}
Expand All @@ -173,7 +173,7 @@ public function buildBodyData(VEvent $vEvent, ?VEvent $oldVEvent): array {
}

/**
* genarates a when string based on if a event has an recurrence or not
* generates a when string based on if a event has an recurrence or not
*
* @since 30.0.0
*
Expand All @@ -189,7 +189,7 @@ public function generateWhenString(EventReader $er): string {
}

/**
* genarates a when string for a non recurring event
* generates a when string for a non recurring event
*
* @since 30.0.0
*
Expand All @@ -198,8 +198,8 @@ public function generateWhenString(EventReader $er): string {
* @return string
*/
public function generateWhenStringSingular(EventReader $er): string {
// calculate time differnce from now to start of event
$occuring = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate()));
// calculate time difference from now to start of event
$occurring = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate()));

Check notice

Code scanning / Psalm

PossiblyNullArgument Note

Argument 1 of DateTime::diff cannot be null, possibly null value provided
// extract start date
$startDate = $this->l10n->l('date', $er->startDateTime(), ['width' => 'full']);
// time of the day
Expand All @@ -214,19 +214,19 @@ public function generateWhenStringSingular(EventReader $er): string {
// Output produced in order:
// In a day/week/month/year on July 1, 2024 for the entire day
// In a day/week/month/year on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)
// In 2 days/weeks/monthss/years on July 1, 2024 for the entire day
// In 2 days/weeks/monthss/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)
return match ([($occuring[0] > 1), !empty($endTime)]) {
[false, false] => $this->l10n->t('In a %1$s on %2$s for the entire day', [$occuring[1], $startDate]),
[false, true] => $this->l10n->t('In a %1$s on %2$s between %3$s - %4$s', [$occuring[1], $startDate, $startTime, $endTime]),
[true, false] => $this->l10n->t('In %1$s %2$s on %3$s for the entire day', [$occuring[0], $occuring[1], $startDate]),
[true, true] => $this->l10n->t('In %1$s %2$s on %3$s between %4$s - %5$s', [$occuring[0], $occuring[1], $startDate, $startTime, $endTime]),
// In 2 days/weeks/months/years on July 1, 2024 for the entire day
// In 2 days/weeks/months/years on July 1, 2024 between 8:00 AM - 9:00 AM (America/Toronto)
return match ([($occurring[0] > 1), !empty($endTime)]) {
[false, false] => $this->l10n->t('In a %1$s on %2$s for the entire day', [$occurring[1], $startDate]),
[false, true] => $this->l10n->t('In a %1$s on %2$s between %3$s - %4$s', [$occurring[1], $startDate, $startTime, $endTime]),

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $startTime, first seen on line 207

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $endTime, first seen on line 209
[true, false] => $this->l10n->t('In %1$s %2$s on %3$s for the entire day', [$occurring[0], $occurring[1], $startDate]),
[true, true] => $this->l10n->t('In %1$s %2$s on %3$s between %4$s - %5$s', [$occurring[0], $occurring[1], $startDate, $startTime, $endTime]),

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $startTime, first seen on line 207

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $endTime, first seen on line 209
default => $this->l10n->t('Could not generate when statement')
};
}

/**
* genarates a when string based on recurrance precision/frequency
* generates a when string based on recurrence precision/frequency
*
* @since 30.0.0
*
Expand All @@ -245,7 +245,7 @@ public function generateWhenStringRecurring(EventReader $er): string {
}

/**
* genarates a when string for a daily precision/frequency
* generates a when string for a daily precision/frequency
*
* @since 30.0.0
*
Expand Down Expand Up @@ -297,7 +297,7 @@ public function generateWhenStringRecurringDaily(EventReader $er): string {
}

/**
* genarates a when string for a weekly precision/frequency
* generates a when string for a weekly precision/frequency
*
* @since 30.0.0
*
Expand Down Expand Up @@ -351,7 +351,7 @@ public function generateWhenStringRecurringWeekly(EventReader $er): string {
}

/**
* genarates a when string for a monthly precision/frequency
* generates a when string for a monthly precision/frequency
*
* @since 30.0.0
*
Expand Down Expand Up @@ -417,7 +417,7 @@ public function generateWhenStringRecurringMonthly(EventReader $er): string {
}

/**
* genarates a when string for a yearly precision/frequency
* generates a when string for a yearly precision/frequency
*
* @since 30.0.0
*
Expand Down Expand Up @@ -485,7 +485,7 @@ public function generateWhenStringRecurringYearly(EventReader $er): string {
}

/**
* genarates a when string for a fixed precision/frequency
* generates a when string for a fixed precision/frequency
*
* @since 30.0.0
*
Expand Down Expand Up @@ -519,7 +519,7 @@ public function generateWhenStringRecurringFixed(EventReader $er): string {
}

/**
* genarates a occurring next string for a recurring event
* generates a occurring next string for a recurring event
*
* @since 30.0.0
*
Expand All @@ -529,26 +529,26 @@ public function generateWhenStringRecurringFixed(EventReader $er): string {
*/
public function generateOccurringString(EventReader $er): string {

// reset to initial occurance
// reset to initial occurrence
$er->recurrenceRewind();
// forward to current date
$er->recurrenceAdvanceTo($this->timeFactory->getDateTime());
// calculate time differnce from now to start of next event occurance and minimize it
$occuranceIn = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate()));
// store next occurance value
$occurance = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']);
// forward one occurance
// calculate time difference from now to start of next event occurrence and minimize it
$occurrenceIn = $this->minimizeInterval($this->timeFactory->getDateTime()->diff($er->recurrenceDate()));

Check notice

Code scanning / Psalm

PossiblyNullArgument Note

Argument 1 of DateTime::diff cannot be null, possibly null value provided
// store next occurrence value
$occurrence = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']);

Check notice

Code scanning / Psalm

PossiblyNullArgument Note

Argument 2 of OCP\IL10N::l cannot be null, possibly null value provided
// forward one occurrence
$er->recurrenceAdvance();
// evaluate if occurance is valid
// evaluate if occurrence is valid
if ($er->recurrenceDate() !== null) {
// store following occurance value
$occurance2 = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']);
// forward one occurance
// store following occurrence value
$occurrence2 = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']);

Check notice

Code scanning / Psalm

PossiblyNullArgument Note

Argument 2 of OCP\IL10N::l cannot be null, possibly null value provided
// forward one occurrence
$er->recurrenceAdvance();
// evaluate if occurance is valid
// evaluate if occurrence is valid
if ($er->recurrenceDate()) {
// store following occurance value
$occurance3 = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']);
// store following occurrence value
$occurrence3 = $this->l10n->l('date', $er->recurrenceDate(), ['width' => 'long']);

Check notice

Code scanning / Psalm

PossiblyNullArgument Note

Argument 2 of OCP\IL10N::l cannot be null, possibly null value provided
}
}
// generate localized when string
Expand All @@ -561,13 +561,13 @@ public function generateOccurringString(EventReader $er): string {
// In 2 days/weeks/months/years on July 1, 2024
// In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024
// In 2 days/weeks/months/years on July 1, 2024 then on July 3, 2024 and July 5, 2024
return match ([($occuranceIn[0] > 1), !empty($occurance2), !empty($occurance3)]) {
[false, false, false] => $this->l10n->t('In a %1$s on %2$s', [$occuranceIn[1], $occurance]),
[false, true, false] => $this->l10n->t('In a %1$s on %2$s then on %3$s', [$occuranceIn[1], $occurance, $occurance2]),
[false, true, true] => $this->l10n->t('In a %1$s on %2$s then on %3$s and %4$s', [$occuranceIn[1], $occurance, $occurance2, $occurance3]),
[true, false, false] => $this->l10n->t('In %1$s %2$s on %3$s', [$occuranceIn[0], $occuranceIn[1], $occurance]),
[true, true, false] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s', [$occuranceIn[0], $occuranceIn[1], $occurance, $occurance2]),
[true, true, true] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s and %5$s', [$occuranceIn[0], $occuranceIn[1], $occurance, $occurance2, $occurance3]),
return match ([($occurrenceIn[0] > 1), !empty($occurrence2), !empty($occurrence3)]) {
[false, false, false] => $this->l10n->t('In a %1$s on %2$s', [$occurrenceIn[1], $occurrence]),
[false, true, false] => $this->l10n->t('In a %1$s on %2$s then on %3$s', [$occurrenceIn[1], $occurrence, $occurrence2]),

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $occurrence2, first seen on line 545
[false, true, true] => $this->l10n->t('In a %1$s on %2$s then on %3$s and %4$s', [$occurrenceIn[1], $occurrence, $occurrence2, $occurrence3]),

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $occurrence2, first seen on line 545

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $occurrence3, first seen on line 551
[true, false, false] => $this->l10n->t('In %1$s %2$s on %3$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence]),
[true, true, false] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence, $occurrence2]),

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $occurrence2, first seen on line 545
[true, true, true] => $this->l10n->t('In %1$s %2$s on %3$s then on %4$s and %5$s', [$occurrenceIn[0], $occurrenceIn[1], $occurrence, $occurrence2, $occurrence3]),

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $occurrence2, first seen on line 545

Check notice

Code scanning / Psalm

PossiblyUndefinedVariable Note

Possibly undefined variable $occurrence3, first seen on line 551
default => $this->l10n->t('Could not generate next recurrence statement')
};

Expand Down
27 changes: 27 additions & 0 deletions apps/dav/tests/unit/CalDAV/EventReaderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,15 @@ public function testRecurringConcludes(): void {
// test set by constructor
$this->assertTrue($er->recurringConcludes());

/** test rdate (multiple property instances) recurrance */
$vCalendar = clone $this->vCalendar1a;
$vCalendar->VEVENT[0]->add('RDATE', '20240703');
$vCalendar->VEVENT[0]->add('RDATE', '20240705');
// construct event reader
$er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertTrue($er->recurringConcludes());

/** test rrule and rdate recurrance with rdate as last date */
$vCalendar = clone $this->vCalendar1a;
$vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
Expand Down Expand Up @@ -578,6 +587,15 @@ public function testRecurringConcludesAfter(): void {
// test set by constructor
$this->assertEquals(2, $er->recurringConcludesAfter());

/** test rdate (multiple property instances) recurrance */
$vCalendar = clone $this->vCalendar1a;
$vCalendar->VEVENT[0]->add('RDATE', '20240703');
$vCalendar->VEVENT[0]->add('RDATE', '20240705');
// construct event reader
$er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals(2, $er->recurringConcludesAfter());

/** test rrule and rdate recurrance */
$vCalendar = clone $this->vCalendar1a;
$vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
Expand Down Expand Up @@ -624,6 +642,15 @@ public function testRecurringConcludesOn(): void {
// test set by constructor
$this->assertEquals((new \DateTime('20240705T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());

/** test rdate (multiple property instances) recurrance */
$vCalendar = clone $this->vCalendar1a;
$vCalendar->VEVENT[0]->add('RDATE', '20240703');
$vCalendar->VEVENT[0]->add('RDATE', '20240705');
// construct event reader
$er = new EventReader($vCalendar, $vCalendar->VEVENT[0]->UID->getValue());
// test set by constructor
$this->assertEquals((new \DateTime('20240705T000000', (new DateTimeZone('America/Toronto')))), $er->recurringConcludesOn());

/** test rrule and rdate recurrance with rdate as last date */
$vCalendar = clone $this->vCalendar1a;
$vCalendar->VEVENT[0]->add('RRULE', 'FREQ=WEEKLY;COUNT=6;BYDAY=MO,WE,FR');
Expand Down
Loading

0 comments on commit 2e807c9

Please sign in to comment.