Consider a change in recurrence rule significant for rescheduling (#4366)
This commit is contained in:
parent
f09948eefe
commit
12591358e6
6 changed files with 65 additions and 32 deletions
|
@ -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;
|
||||
|
|
|
@ -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'])) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue