diff --git a/plugins/calendar/calendar.php b/plugins/calendar/calendar.php index 775fb56b..bef0d410 100644 --- a/plugins/calendar/calendar.php +++ b/plugins/calendar/calendar.php @@ -509,8 +509,12 @@ class calendar extends rcube_plugin $event = get_input_value('e', RCUBE_INPUT_POST); $success = $reload = $got_msg = false; + // don't notify if modifying a recurring instance (really?) + if ($event['savemode'] && $event['savemode'] != 'all' && $event['notify']) + unset($event['notify']); + // read old event data in order to find changes - if ($event['_notify'] && $action != 'new') + if ($event['notify'] && $action != 'new') $old = $this->driver->get_event($event); switch ($action) { @@ -587,13 +591,13 @@ class calendar extends rcube_plugin } // send out notifications - if ($success && $event['_notify'] && ($event['attendees'] || $old['attendees'])) { + if ($success && $event['notify'] && ($event['attendees'] || $old['attendees'])) { // make sure we have the complete record - $event = $this->driver->get_event($event); + $event = $action == 'remove' ? $old : $this->driver->get_event($event); // only notify if data really changed (TODO: do diff check on client already) - if (!$old || self::event_diff($event, $old)) { - if ($this->notify_attendees($event, $old) < 0) + if (!$old || $action == 'remove' || self::event_diff($event, $old)) { + if ($this->notify_attendees($event, $old, $action) < 0) $this->rc->output->show_message('calendar.errornotifying', 'error'); } } @@ -1261,7 +1265,7 @@ class calendar extends rcube_plugin /** * Send out an invitation/notification to all event attendees */ - private function notify_attendees($event, $old) + private function notify_attendees($event, $old, $action = 'edit') { $sent = 0; $myself = $this->rc->user->get_identity(); @@ -1285,6 +1289,10 @@ class calendar extends rcube_plugin if ($agent = $this->rc->config->get('useragent')) $headers['User-Agent'] = $agent; + if ($action == 'remove') { + $event['cancelled'] = true; + $is_cancelled = true; + } // attach ics file for this event $this->load_ical(); @@ -1316,23 +1324,24 @@ class calendar extends rcube_plugin $headers['To'] = format_email_recipient($mailto, $attendee['name']); $headers['Subject'] = $this->gettext(array( - 'name' => $is_new ? 'invitationsubject' : 'eventupdatesubject', + 'name' => $is_cancelled ? 'eventcancelsubject' : ($is_new ? 'invitationsubject' : 'eventupdatesubject'), 'vars' => array('title' => $event['title']), )); // compose message body $body = $this->gettext(array( - 'name' => $is_new ? 'invitationmailbody' : 'eventupdatemailbody', + 'name' => $is_cancelled ? 'eventcancelmailbody' : ($is_new ? 'invitationmailbody' : 'eventupdatemailbody'), 'vars' => array( 'title' => $event['title'], 'date' => $this->event_date_text($event), 'attendees' => join(', ', $attendees_list), + 'organizer' => $myself['name'], ) )); $message->headers($headers); $message->setTXTBody(rcube_message::format_flowed($body, 79)); - + // finally send the message if (rcmail_deliver_message($message, $from, $mailto, $smtp_error)) $sent++; diff --git a/plugins/calendar/calendar_ui.js b/plugins/calendar/calendar_ui.js index bc1ccd63..469fdf4b 100644 --- a/plugins/calendar/calendar_ui.js +++ b/plugins/calendar/calendar_ui.js @@ -553,7 +553,7 @@ function rcube_calendar_ui(settings) // tell server to send notifications if (data.attendees.length && ((event.id && notify.checked) || (!event.id && invite.checked))) { - data._notify = 1; + data.notify = 1; } // gather recurrence settings @@ -1307,8 +1307,8 @@ function rcube_calendar_ui(settings) // event has attendees, ask whether to notify them if (has_attendees(event)) { html += '
' + - '
'; } @@ -1331,7 +1331,7 @@ function rcube_calendar_ui(settings) $dialog.find('a.button').button().click(function(e){ data.savemode = String(this.href).replace(/.+#/, ''); if ($dialog.find('input.confirm-attendees-donotify').get(0)) - data._notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0; + data.notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0; update_event(action, data); $dialog.dialog("destroy").hide(); return false; @@ -1348,7 +1348,7 @@ function rcube_calendar_ui(settings) buttons.push({ text: rcmail.gettext((action == 'remove' ? 'remove' : 'save'), 'calendar'), click: function() { - data._notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0; + data.notify = $dialog.find('input.confirm-attendees-donotify').get(0).checked ? 1 : 0; update_event(action, data); $(this).dialog("close"); } diff --git a/plugins/calendar/lib/calendar_ical.php b/plugins/calendar/lib/calendar_ical.php index f0410505..653a0f4f 100644 --- a/plugins/calendar/lib/calendar_ical.php +++ b/plugins/calendar/lib/calendar_ical.php @@ -259,8 +259,14 @@ class calendar_ical if ($action) $vevent .= "ACTION:" . self::escpape(strtoupper($action)) . self::EOL; $vevent .= "END:VALARM\n"; } + $vevent .= "TRANSP:" . ($event['free_busy'] == 'free' ? 'TRANSPARENT' : 'OPAQUE') . self::EOL; + if ($event['cancelled']) + $vevent .= "STATUS:CANCELLED" . self::EOL; + else if ($event['free_busy'] == 'tentative') + $vevent .= "STATUS:TENTATIVE" . self::EOL; + // TODO: export attachments $vevent .= "END:VEVENT" . self::EOL; diff --git a/plugins/calendar/localization/en_US.inc b/plugins/calendar/localization/en_US.inc index e3dd99b1..674628d8 100644 --- a/plugins/calendar/localization/en_US.inc +++ b/plugins/calendar/localization/en_US.inc @@ -106,6 +106,7 @@ $labels['availoutofoffice'] = 'Out of Office'; $labels['scheduletime'] = 'Find availability'; $labels['sendinvitations'] = 'Send invitations'; $labels['sendnotifications'] = 'Notify participants about modifications'; +$labels['sendcancellation'] = 'Notify participants about event cancellation'; $labels['onlyworkinghours'] = 'Find availability within my working hours'; $labels['reqallattendees'] = 'Required/all participants'; $labels['prevslot'] = 'Previous Slot'; @@ -115,6 +116,8 @@ $labels['invitationsubject'] = 'You\'ve been invited to "$title"'; $labels['invitationmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nPlease find attached an iCalendar file with all the event details which you can import to your calendar application."; $labels['eventupdatesubject'] = '"$title" has been updated'; $labels['eventupdatemailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nPlease find attached an iCalendar file with the updated event details which you can import to your calendar application."; +$labels['eventcancelsubject'] = '"$title" has been canceled'; +$labels['eventcancelmailbody'] = "*\$title*\n\nWhen: \$date\n\nInvitees: \$attendees\n\nThe event has been cancelled by \$organizer.\n\nPlease find attached an iCalendar file with the updated event details."; // event dialog tabs $labels['tabsummary'] = 'Summary';