From c6f5a8233bf1a52841a7bfd2123e1d3f838413d8 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Thu, 6 Nov 2014 17:09:49 +0100 Subject: [PATCH] Fix handling of RSVP flags --- plugins/calendar/calendar.php | 27 +++++++++++++++---- .../lib/libcalendaring_itip.php | 12 +++++---- plugins/libcalendaring/libvcalendar.php | 3 ++- plugins/libkolab/lib/kolab_format_xcal.php | 9 ++++--- plugins/tasklist/tasklist.php | 20 ++++++++++++-- 5 files changed, 55 insertions(+), 16 deletions(-) diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 910affb5..e3597124 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -1642,7 +1642,9 @@ class calendar extends rcube_plugin foreach ((array)$event['attendees'] as $i => $attendee) { if ($attendee['role'] == 'ORGANIZER') { $organizer = $attendee; - break; + } + if ($attendee['status'] == 'DELEGATED' && $attendee['rsvp'] == false) { + $event['attendees'][$i]['noreply'] = true; } } @@ -1895,7 +1897,7 @@ class calendar extends rcube_plugin // compose multipart message using PEAR:Mail_Mime $method = $action == 'remove' ? 'CANCEL' : 'REQUEST'; - $message = $itip->compose_itip_message($event, $method); + $message = $itip->compose_itip_message($event, $method, $event['sequence'] > $old['sequence']); // list existing attendees from $old event $old_attendees = array(); @@ -1915,7 +1917,11 @@ class calendar extends rcube_plugin // skip if notification is disabled for this attendee if ($attendee['noreply'] && $itip_notify & 2) continue; - + + // skip if this attendee has delegated and set RSVP=FALSE + if ($attendee['status'] == 'DELEGATED' && $attendee['rsvp'] === false) + continue; + // which template to use for mail text $is_new = !in_array($attendee['email'], $old_attendees); $is_rsvp = $is_new || $event['sequence'] > $old['sequence']; @@ -2639,7 +2645,8 @@ class calendar extends rcube_plugin else if ($attendee['email'] && in_array(strtolower($attendee['email']), $emails)) { $event['attendees'][$i]['status'] = strtoupper($status); if (!in_array($event['attendees'][$i]['status'], array('NEEDS-ACTION','DELEGATED'))) - unset($event['attendees'][$i]['rsvp']); // remove RSVP attribute + $event['attendees'][$i]['rsvp'] = false; // unset RSVP attribute + $metadata['attendee'] = $attendee['email']; $metadata['rsvp'] = $attendee['role'] != 'NON-PARTICIPANT'; $reply_sender = $attendee['email']; @@ -2696,7 +2703,17 @@ class calendar extends rcube_plugin $existing['attendees'][] = $attendee; } } - + + // if delegatee has declined, set delegator's RSVP=True + if ($event_attendee && $event_attendee['status'] == 'DECLINED' && $event_attendee['delegated-from']) { + foreach ($existing['attendees'] as $i => $attendee) { + if ($attendee['email'] == $event_attendee['delegated-from']) { + $existing['attendees'][$i]['rsvp'] = true; + break; + } + } + } + // found matching attendee entry in both existing and new events if ($existing_attendee >= 0 && $event_attendee) { $existing['attendees'][$existing_attendee] = $event_attendee; diff --git a/plugins/libcalendaring/lib/libcalendaring_itip.php b/plugins/libcalendaring/lib/libcalendaring_itip.php index 95242498..bd83f163 100644 --- a/plugins/libcalendaring/lib/libcalendaring_itip.php +++ b/plugins/libcalendaring/lib/libcalendaring_itip.php @@ -90,6 +90,7 @@ class libcalendaring_itip * @param string Mail subject * @param string Mail body text label * @param object Mail_mime object with message data + * @param boolean Request RSVP * @return boolean True on success, false on failure */ public function send_itip_message($event, $method, $recipient, $subject, $bodytext, $message = null, $rsvp = true) @@ -98,7 +99,7 @@ class libcalendaring_itip $this->sender['name'] = $this->sender['email']; if (!$message) - $message = $this->compose_itip_message($event, $method); + $message = $this->compose_itip_message($event, $method, $rsvp); $mailto = rcube_idn_to_ascii($recipient['email']); @@ -192,9 +193,10 @@ class libcalendaring_itip * * @param array Event object to send * @param string iTip method (REQUEST|REPLY|CANCEL) + * @param boolean Request RSVP * @return object Mail_mime object with message data */ - public function compose_itip_message($event, $method) + public function compose_itip_message($event, $method, $rsvp = true) { $from = rcube_idn_to_ascii($this->sender['email']); $from_utf = rcube_utils::idn_to_utf8($from); @@ -228,11 +230,11 @@ class libcalendaring_itip $event['attendees'] = $reply_attendees; } } - // set RSVP=TRUE for every attendee if not set + // set RSVP for every attendee else if ($method == 'REQUEST') { foreach ($event['attendees'] as $i => $attendee) { - if (!isset($attendee['rsvp'])) { - $event['attendees'][$i]['rsvp']= true; + if ($attendee['status'] != 'DELEGATED') { + $event['attendees'][$i]['rsvp']= $rsvp ? true : null; } } } diff --git a/plugins/libcalendaring/libvcalendar.php b/plugins/libcalendaring/libvcalendar.php index 1e10ddcb..062ee7e7 100644 --- a/plugins/libcalendaring/libvcalendar.php +++ b/plugins/libcalendaring/libvcalendar.php @@ -1072,7 +1072,8 @@ class libvcalendar implements Iterator $event['organizer'] = $attendee; } else if (!empty($attendee['email'])) { - $attendee['rsvp'] = $attendee['rsvp'] ? 'TRUE' : null; + if (isset($attendee['rsvp'])) + $attendee['rsvp'] = $attendee['rsvp'] ? 'TRUE' : 'FALSE'; $ve->add('ATTENDEE', 'mailto:' . $attendee['email'], array_filter(self::map_keys($attendee, $this->attendee_keymap))); } } diff --git a/plugins/libkolab/lib/kolab_format_xcal.php b/plugins/libkolab/lib/kolab_format_xcal.php index 08f27d02..ad545050 100644 --- a/plugins/libkolab/lib/kolab_format_xcal.php +++ b/plugins/libkolab/lib/kolab_format_xcal.php @@ -364,14 +364,17 @@ abstract class kolab_format_xcal extends kolab_format $cr = new ContactReference(ContactReference::EmailReference, $attendee['email']); $cr->setName($attendee['name']); + // set attendee RSVP if missing + if (!isset($attendee['rsvp'])) { + $object['attendees'][$i]['rsvp'] = $attendee['rsvp'] = true; + } + $att = new Attendee; $att->setContact($cr); $att->setPartStat($this->part_status_map[$attendee['status']]); $att->setRole($this->role_map[$attendee['role']] ? $this->role_map[$attendee['role']] : kolabformat::Required); $att->setCutype($this->cutype_map[$attendee['cutype']] ? $this->cutype_map[$attendee['cutype']] : kolabformat::CutypeIndividual); - $att->setRSVP((bool)$attendee['rsvp'] || $reschedule); - - $object['attendees'][$i]['rsvp'] = $attendee['rsvp'] || $reschedule; + $att->setRSVP((bool)$attendee['rsvp']); if (!empty($attendee['delegated-from'])) { $vdelegators = new vectorcontactref; diff --git a/plugins/tasklist/tasklist.php b/plugins/tasklist/tasklist.php index 71e64312..3f23c599 100644 --- a/plugins/tasklist/tasklist.php +++ b/plugins/tasklist/tasklist.php @@ -757,7 +757,7 @@ class tasklist extends rcube_plugin // compose multipart message using PEAR:Mail_Mime $method = $action == 'delete' ? 'CANCEL' : 'REQUEST'; $object = $this->to_libcal($task); - $message = $itip->compose_itip_message($object, $method); + $message = $itip->compose_itip_message($object, $method, $task['sequence'] > $old['sequence']); // list existing attendees from the $old task $old_attendees = array(); @@ -779,6 +779,12 @@ class tasklist extends rcube_plugin if ($attendee['noreply'] && $itip_notify & 2) { continue; } + + // skip if this attendee has delegated and set RSVP=FALSE + if ($attendee['status'] == 'DELEGATED' && $attendee['rsvp'] === false) { + continue; + } + // which template to use for mail text $is_new = !in_array($attendee['email'], $old_attendees); $is_rsvp = $is_new || $task['sequence'] > $old['sequence']; @@ -1776,7 +1782,7 @@ class tasklist extends rcube_plugin $task['attendees'][$i]['status'] = strtoupper($status); if (!in_array($task['attendees'][$i]['status'], array('NEEDS-ACTION','DELEGATED'))) { - unset($task['attendees'][$i]['rsvp']); // remove RSVP attribute + $task['attendees'][$i]['rsvp'] = false; // unset RSVP attribute } } } @@ -1833,6 +1839,16 @@ class tasklist extends rcube_plugin } } + // if delegatee has declined, set delegator's RSVP=True + if ($task_attendee && $task_attendee['status'] == 'DECLINED' && $task_attendee['delegated-from']) { + foreach ($existing['attendees'] as $i => $attendee) { + if ($attendee['email'] == $task_attendee['delegated-from']) { + $existing['attendees'][$i]['rsvp'] = true; + break; + } + } + } + // found matching attendee entry in both existing and new events if ($existing_attendee >= 0 && $task_attendee) { $existing['attendees'][$existing_attendee] = $task_attendee;