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
5 changes: 5 additions & 0 deletions lib/ITip/Broker.php
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,11 @@ protected function parseEventForAttendee(VCalendar $calendar, array $eventInfo,
// Skip
continue;
}
if ('master' === $instance['id'] && !isset($eventInfo['instances']['master'])) {
// The master event no longer exists in the new object, so
// there is no instance to reply for.
continue;
}

/** @var VEvent $event */
$event = $icalMsg->add('VEVENT', [
Expand Down
70 changes: 70 additions & 0 deletions tests/VObject/ITip/BrokerAttendeeReplyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,76 @@ public function testReplyNoMasterEvent(): void
$this->parse($oldMessage, $newMessage, $expected);
}

/**
* This function tests an attendee updating an event, where the new
* version no longer contains the master event the attendee was part of,
* but only an instance of it.
*
* Some clients add a RECURRENCE-ID to non-recurring events.
*/
public function testReplyMasterEventReplacedByInstance(): void
{
$oldMessage = <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:foobar
SEQUENCE:1
ORGANIZER;CN=Strunk:mailto:strunk@example.org
ATTENDEE;CN=One:mailto:one@example.org
DTSTART:20140724T120000Z
SUMMARY:Daily sprint
END:VEVENT
END:VCALENDAR
ICS;

$newMessage = <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:foobar
SEQUENCE:1
ORGANIZER;CN=Strunk:mailto:strunk@example.org
ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
RECURRENCE-ID:20140724T120000Z
DTSTART:20140724T120000Z
SUMMARY:Daily sprint
END:VEVENT
END:VCALENDAR
ICS;

$expected = [
[
'uid' => 'foobar',
'method' => 'REPLY',
'component' => 'VEVENT',
'sender' => 'mailto:one@example.org',
'senderName' => 'One',
'recipient' => 'mailto:strunk@example.org',
'recipientName' => 'Strunk',
'message' => <<<ICS
BEGIN:VCALENDAR
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:REPLY
BEGIN:VEVENT
UID:foobar
DTSTAMP:**ANY**
SEQUENCE:1
DTSTART:20140724T120000Z
SUMMARY:Daily sprint
RECURRENCE-ID:20140724T120000Z
ORGANIZER;CN=Strunk:mailto:strunk@example.org
ATTENDEE;PARTSTAT=ACCEPTED;CN=One:mailto:one@example.org
END:VEVENT
END:VCALENDAR
ICS,
],
];

$this->parse($oldMessage, $newMessage, $expected);
}

/**
* A party crasher is an attendee that accepted an event, but was not in
* any original invite.
Expand Down
Loading