T2531: Support SCHEDULE-AGENT in iTip

This property is used when scheduling method on the original and updated
event via CalDAV (iRony) using SCHEDULING-AGENT=CLIENT. CANCEL invitations
are supposed to be sent to attendees only if the initial scheduling was not
done with SCHEDULING-AGENT=CLIENT.

https://tools.ietf.org/html/rfc6638#section-3.2.1.2
This commit is contained in:
Aleksander Machniak 2017-07-04 14:27:19 +00:00
parent 94dd9965a7
commit 0c02d0d45c

View file

@ -45,11 +45,13 @@ class libvcalendar implements Iterator
'delegated-from' => 'DELEGATED-FROM',
'delegated-to' => 'DELEGATED-TO',
'schedule-status' => 'SCHEDULE-STATUS',
'schedule-agent' => 'SCHEDULE-AGENT',
'sent-by' => 'SENT-BY',
);
private $organizer_keymap = array(
'name' => 'CN',
'schedule-status' => 'SCHEDULE-STATUS',
'schedule-agent' => 'SCHEDULE-AGENT',
'sent-by' => 'SENT-BY',
);
private $iteratorkey = 0;
@ -549,6 +551,10 @@ class libvcalendar implements Iterator
$attendee['role'] = 'ORGANIZER';
$attendee['status'] = 'ACCEPTED';
$event['organizer'] = $attendee;
if (array_key_exists('schedule-agent', $attendee)) {
$schedule_agent = $attendee['schedule-agent'];
}
}
else if ($attendee['email'] != $event['organizer']['email']) {
$event['attendees'][] = $attendee;
@ -708,6 +714,12 @@ class libvcalendar implements Iterator
$event['end'] = clone $event['start'];
}
// T2531: Remember SCHEDULE-AGENT in custom property to properly
// support event updates via CalDAV when SCHEDULE-AGENT=CLIENT is used
if (isset($schedule_agent)) {
$event['x-custom'][] = array('SCHEDULE-AGENT', $schedule_agent);
}
// minimal validation
if (empty($event['uid']) || ($event['_type'] == 'event' && empty($event['start']) != empty($event['end']))) {
throw new VObject\ParseException('Object validation failed: missing mandatory object properties');
@ -1164,6 +1176,13 @@ class libvcalendar implements Iterator
$ve->add($va);
}
// Find SCHEDULE-AGENT
foreach ((array)$event['x-custom'] as $prop) {
if ($prop[0] === 'SCHEDULE-AGENT') {
$schedule_agent = $prop[1];
}
}
foreach ((array)$event['attendees'] as $attendee) {
if ($attendee['role'] == 'ORGANIZER') {
if (empty($event['organizer']))
@ -1172,14 +1191,26 @@ class libvcalendar implements Iterator
else if (!empty($attendee['email'])) {
if (isset($attendee['rsvp']))
$attendee['rsvp'] = $attendee['rsvp'] ? 'TRUE' : null;
$ve->add('ATTENDEE', 'mailto:' . $attendee['email'],
array_filter(self::map_keys($attendee, $this->attendee_keymap)));
$mailto = $attendee['email'];
$attendee = array_filter(self::map_keys($attendee, $this->attendee_keymap));
if ($schedule_agent !== null && !isset($attendee['SCHEDULE-AGENT'])) {
$attendee['SCHEDULE-AGENT'] = $schedule_agent;
}
$ve->add('ATTENDEE', 'mailto:' . $mailto, $attendee);
}
}
if ($event['organizer']) {
$ve->add('ORGANIZER', 'mailto:' . $event['organizer']['email'],
array_filter(self::map_keys($event['organizer'], $this->organizer_keymap)));
$organizer = array_filter(self::map_keys($event['organizer'], $this->organizer_keymap));
if ($schedule_agent !== null && !isset($organizer['SCHEDULE-AGENT'])) {
$organizer['SCHEDULE-AGENT'] = $schedule_agent;
}
$ve->add('ORGANIZER', 'mailto:' . $event['organizer']['email'], $organizer);
}
foreach ((array)$event['url'] as $url) {