Consider a change in recurrence rule significant for rescheduling (#4366)

This commit is contained in:
Thomas Bruederli 2015-02-15 16:33:39 +01:00
parent f09948eefe
commit 12591358e6
6 changed files with 65 additions and 32 deletions

View file

@ -993,7 +993,7 @@ class calendar extends rcube_plugin
if ($success = $this->driver->edit_rsvp($event, $status)) {
$noreply = rcube_utils::get_input_value('noreply', rcube_utils::INPUT_GPC);
$noreply = intval($noreply) || $status == 'needs-action' || $itip_sending === 0;
$reload = $event['calendar'] != $ev['calendar'] ? 2 : 1;
$reload = $event['calendar'] != $ev['calendar'] || $event['recurrence'] ? 2 : 1;
$organizer = null;
$emails = $this->get_user_emails();
@ -1131,8 +1131,6 @@ class calendar extends rcube_plugin
// make sure we have the complete record
$event = $action == 'remove' ? $old : $this->driver->get_event($event);
// TODO: on change of a recurring (main) event, also send updates to differing attendess of recurrence exceptions
// only notify if data really changed (TODO: do diff check on client already)
if (!$old || $action == 'remove' || self::event_diff($event, $old)) {
$sent = $this->notify_attendees($event, $old, $action, $event['_comment']);
@ -1990,6 +1988,8 @@ class calendar extends rcube_plugin
$sent = -100;
}
// TODO: on change of a recurring (main) event, also send updates to differing attendess of recurrence exceptions
// send CANCEL message to removed attendees
foreach ((array)$old['attendees'] as $attendee) {
if ($attendee['ROLE'] == 'ORGANIZER' || !$attendee['email'] || in_array(strtolower($attendee['email']), $current))
@ -2215,7 +2215,7 @@ class calendar extends rcube_plugin
public static function event_diff($a, $b)
{
$diff = array();
$ignore = array('changed' => 1, 'attachments' => 1, 'recurrence' => 1, '_notify' => 1, '_owner' => 1);
$ignore = array('changed' => 1, 'attachments' => 1, '_notify' => 1, '_owner' => 1, '_savemode' => 1);
foreach (array_unique(array_merge(array_keys($a), array_keys($b))) as $key) {
if (!$ignore[$key] && $a[$key] != $b[$key])
$diff[] = $key;

View file

@ -1035,26 +1035,13 @@ class kolab_driver extends calendar_driver
*/
public function check_scheduling(&$event, $old, $update = true)
{
$reschedule = false;
// skip this check when importing iCal/iTip events
if (isset($event['sequence']) || !empty($event['_method'])) {
return $reschedule;
return false;
}
// iterate through the list of properties considered 'significant' for scheduling
foreach (kolab_format_event::$scheduling_properties as $prop) {
$a = $old[$prop];
$b = $event[$prop];
if ($event['allday'] && ($prop == 'start' || $prop == 'end') && $a instanceof DateTime && $b instanceof DateTime) {
$a = $a->format('Y-m-d');
$b = $b->format('Y-m-d');
}
if ($a != $b) {
$reschedule = true;
break;
}
}
$reschedule = kolab_format_event::check_rescheduling($event, $old);
// reset all attendee status to needs-action (#4360)
if ($update && $reschedule && is_array($event['attendees'])) {

View file

@ -41,7 +41,7 @@ $config['kolab_messages_cache_bypass'] = 0;
// These event properties contribute to a significant revision to the calendar component
// and if changed will increment the sequence number relevant for scheduling according to RFC 5545
$config['kolab_event_scheduling_properties'] = array('start', 'end', 'allday', 'location', 'status', 'cancelled');
$config['kolab_event_scheduling_properties'] = array('start', 'end', 'allday', 'recurrence', 'location', 'status', 'cancelled');
// These task properties contribute to a significant revision to the calendar component
// and if changed will increment the sequence number relevant for scheduling according to RFC 5545

View file

@ -26,7 +26,7 @@ class kolab_format_event extends kolab_format_xcal
{
public $CTYPEv2 = 'application/x-vnd.kolab.event';
public static $scheduling_properties = array('start', 'end', 'allday', 'location', 'status', 'cancelled');
public static $scheduling_properties = array('start', 'end', 'allday', 'recurrence', 'location', 'status', 'cancelled');
protected $objclass = 'Event';
protected $read_func = 'readEvent';
@ -100,6 +100,7 @@ class kolab_format_event extends kolab_format_xcal
foreach((array)$object['recurrence']['EXCEPTIONS'] as $i => $exception) {
$exevent = new kolab_format_event;
$exevent->set(($compacted = $this->compact_exception($exception, $object))); // only save differing values
console('COMPACTED', $compacted);
// get value for recurrence-id
if (!empty($exception['recurrence_date']) && is_a($exception['recurrence_date'], 'DateTime')) {
@ -274,4 +275,13 @@ class kolab_format_event extends kolab_format_xcal
return $exception;
}
/**
* Identify changes considered relevant for scheduling
*
* @see kolab_format_xcal::check_rescheduling()
*/
public static function check_rescheduling($object, $old, $checks = null)
{
return parent::check_rescheduling($object, $old, $checks ?: self::$scheduling_properties);
}
}

View file

@ -126,4 +126,14 @@ class kolab_format_task extends kolab_format_xcal
return $tags;
}
/**
* Identify changes considered relevant for scheduling
*
* @see kolab_format_xcal::check_rescheduling()
*/
public static function check_rescheduling($object, $old, $checks = null)
{
return parent::check_rescheduling($object, $old, $checks ?: self::$scheduling_properties);
}
}

View file

@ -321,17 +321,8 @@ abstract class kolab_format_xcal extends kolab_format
// increment sequence when updating properties relevant for scheduling.
// RFC 5545: "It is incremented [...] each time the Organizer makes a significant revision to the calendar component."
foreach (self::$scheduling_properties as $prop) {
$a = $old[$prop];
$b = $object[$prop];
if ($object['allday'] && ($prop == 'start' || $prop == 'end') && $a instanceof DateTime && $b instanceof DateTime) {
$a = $a->format('Y-m-d');
$b = $b->format('Y-m-d');
}
if ($a != $b) {
if (self::check_rescheduling($object, $old)) {
$object['sequence']++;
break;
}
}
}
}
@ -637,4 +628,39 @@ abstract class kolab_format_xcal extends kolab_format
return $tags;
}
/**
* Identify changes considered relevant for scheduling
*
* @param array Hash array with NEW object properties
* @param array Hash array with OLD object properties
* @param array List of object properties to check for changes
*
* @return boolean True if changes affect scheduling, False otherwise
*/
public static function check_rescheduling($object, $old, $checks = null)
{
$reschedule = false;
foreach ($checks ?: self::$scheduling_properties as $prop) {
$a = $old[$prop];
$b = $object[$prop];
if ($object['allday'] && ($prop == 'start' || $prop == 'end') && $a instanceof DateTime && $b instanceof DateTime) {
$a = $a->format('Y-m-d');
$b = $b->format('Y-m-d');
}
if ($prop == 'recurrence') {
unset($a['EXCEPTIONS']);
unset($b['EXCEPTIONS']);
$a = array_filter($a);
$b = array_filter($b);
}
if ($a != $b) {
$reschedule = true;
break;
}
}
return $reschedule;
}
}