Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 5 additions & 7 deletions apps/dav/lib/CalDAV/TipBroker.php
Original file line number Diff line number Diff line change
Expand Up @@ -319,13 +319,11 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
}
return $messages;
}
// detect if a new cancelled instance was created
$cancelledNewInstances = [];
// detect if a new cancelled instance was created and send a CANCEL for it
if (isset($oldEventInfo['instances'])) {
$instancesDelta = array_diff_key($eventInfo['instances'], $oldEventInfo['instances']);
foreach ($instancesDelta as $id => $instance) {
if ($instance->STATUS?->getValue() === 'CANCELLED') {
$cancelledNewInstances[] = $id;
foreach ($eventInfo['attendees'] as $attendee) {
$messages[] = $this->generateMessage(
[$id => $instance], $organizerHref, $organizerName, $attendee, $objectId, $objectType, $objectSequence, 'CANCEL', $template
Expand Down Expand Up @@ -366,10 +364,10 @@ protected function parseEventForOrganizer(VCalendar $calendar, array $eventInfo,
// otherwise any created or modified instances will be sent as REQUEST
$instances = array_intersect_key($eventInfo['instances'], array_flip(array_keys($eventInfo['attendees'][$attendee]['instances'])));

// Remove already-cancelled new instances from REQUEST
if (!empty($cancelledNewInstances)) {
$instances = array_diff_key($instances, array_flip($cancelledNewInstances));
}
// Keep newly cancelled instances IN the REQUEST. processMessageRequest replaces all
// components of the attendee's stored object with the ones from the message, so a
// REQUEST that omitted the cancelled instance would drop the CANCELLED override that
// the accompanying CANCEL added and the occurrence would reappear as a normal event.

// Skip if no instances left to send
if (empty($instances)) {
Expand Down
6 changes: 6 additions & 0 deletions apps/dav/tests/unit/CalDAV/TipBrokerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ public function testParseEventForOrganizerCreatedInstanceCancelled(): void {
$this->assertEquals($mutatedCalendar->VEVENT[1]->ATTENDEE[0]->getValue(), $messages[0]->recipient);
$this->assertCount(1, $messages[0]->message->VEVENT);
$this->assertEquals('20240715T080000', $messages[0]->message->VEVENT->{'RECURRENCE-ID'}->getValue());
// the REQUEST keeps the cancelled instance, otherwise processMessageRequest (which replaces
// all components) would drop the CANCELLED override on the attendee's copy (issue #6655)
$this->assertEquals('REQUEST', $messages[1]->method);
$this->assertCount(2, $messages[1]->message->VEVENT);
$this->assertEquals('20240715T080000', $messages[1]->message->VEVENT[1]->{'RECURRENCE-ID'}->getValue());
$this->assertEquals('CANCELLED', $messages[1]->message->VEVENT[1]->STATUS->getValue());

}

Expand Down
Loading