diff --git a/plugins/calendar/drivers/database/database_driver.php b/plugins/calendar/drivers/database/database_driver.php index d6a44830..5a518f7e 100644 --- a/plugins/calendar/drivers/database/database_driver.php +++ b/plugins/calendar/drivers/database/database_driver.php @@ -363,11 +363,11 @@ class database_driver extends calendar_driver // use start date from master but try to be smart on time or duration changes $old_start_date = $old['start']->format('Y-m-d'); - $old_start_time = $old['start']->format('H:i'); + $old_start_time = $old['allday'] ? '' : $old['start']->format('H:i'); $old_duration = $old['end']->format('U') - $old['start']->format('U'); $new_start_date = $event['start']->format('Y-m-d'); - $new_start_time = $event['start']->format('H:i'); + $new_start_time = $event['allday'] ? '' : $event['start']->format('H:i'); $new_duration = $event['end']->format('U') - $event['start']->format('U'); $diff = $old_start_date != $new_start_date || $old_start_time != $new_start_time || $old_duration != $new_duration; diff --git a/plugins/calendar/drivers/kolab/kolab_calendar.php b/plugins/calendar/drivers/kolab/kolab_calendar.php index 0a3d273e..f2c106e1 100644 --- a/plugins/calendar/drivers/kolab/kolab_calendar.php +++ b/plugins/calendar/drivers/kolab/kolab_calendar.php @@ -181,9 +181,7 @@ class kolab_calendar $this->events[$master_id] = $this->_to_rcube_event($record); if (($master = $this->events[$master_id]) && $master['recurrence']) { - $limit = clone $master['start']; - $limit->add(new DateInterval('P10Y')); - $this->_get_recurring_events($record, $master['start'], $limit, $id); + $this->_get_recurring_events($record, $master['start'], null, $id); } } @@ -248,7 +246,21 @@ class kolab_calendar // list events in requested time window if ($event['start'] <= $end && $event['end'] >= $start) { unset($event['_attendees']); - $events[] = $event; + $add = true; + + // skip the first instance of a recurring event if listed in exdate + if ($virtual && !empty($event['recurrence']['EXDATE'])) { + $event_date = $event['start']->format('Ymd'); + foreach ($event['recurrence']['EXDATE'] as $exdate) { + if ($exdate->format('Ymd') == $event_date) { + $add = false; + break; + } + } + } + + if ($add) + $events[] = $event; } // resolve recurring events @@ -372,8 +384,14 @@ class kolab_calendar /** * Create instances of a recurring event + * + * @param array Hash array with event properties + * @param object DateTime Start date of the recurrence window + * @param object DateTime End date of the recurrence window + * @param string ID of a specific recurring event instance + * @return array List of recurring event instances */ - public function _get_recurring_events($event, $start, $end, $event_id = null) + public function _get_recurring_events($event, $start, $end = null, $event_id = null) { $object = $event['_formatobj']; if (!$object) { @@ -383,6 +401,19 @@ class kolab_calendar if (!is_object($object)) return array(); + // determine a reasonable end date if none given + if (!$end) { + switch ($event['recurrence']['FREQ']) { + case 'YEARLY': $intvl = 'P100Y'; break; + case 'MONTHLY': $intvl = 'P20Y'; break; + default: $intvl = 'P10Y'; break; + } + + $end = clone $event['start']; + $end->add(new DateInterval($intvl)); + } + + // use libkolab to compute recurring events $recurrence = new kolab_date_recurrence($object); $i = 0; @@ -409,9 +440,9 @@ class kolab_calendar else if ($next_event['start'] > $end) // stop loop if out of range break; - // avoid endless recursion loops - if ($i > 1000) - break; + // avoid endless recursion loops + if ($i > 1000) + break; } return $events; @@ -458,6 +489,10 @@ class kolab_calendar if (is_array($record['categories'])) $record['categories'] = $record['categories'][0]; + // remove empty recurrence array + if (empty($record['recurrence'])) + unset($record['recurrence']); + // remove internals unset($record['_mailbox'], $record['_msguid'], $record['_formatobj'], $record['_attachments']); diff --git a/plugins/calendar/drivers/kolab/kolab_driver.php b/plugins/calendar/drivers/kolab/kolab_driver.php index 0d913a36..58548400 100644 --- a/plugins/calendar/drivers/kolab/kolab_driver.php +++ b/plugins/calendar/drivers/kolab/kolab_driver.php @@ -406,10 +406,10 @@ class kolab_driver extends calendar_driver public function remove_event($event, $force = true) { $success = false; - $_savemode = $event['_savemode']; + $savemode = $event['_savemode']; if (($storage = $this->calendars[$event['calendar']]) && ($event = $storage->get_event($event['id']))) { - $event['_savemode'] = $_savemode; + $event['_savemode'] = $savemode; $savemode = 'all'; $master = $event; @@ -424,12 +424,10 @@ class kolab_driver extends calendar_driver switch ($savemode) { case 'current': $_SESSION['calendar_restore_event_data'] = $master; - + // removing the first instance => just move to next occurence if ($master['id'] == $event['id']) { - $limit = clone $event['end']; - $limit->add(new DateInterval('P370D')); - $recurring = reset($storage->_get_recurring_events($event, $event['start'], $limit, $event['id'].'-1')); + $recurring = reset($storage->_get_recurring_events($event, $event['start'], null, $event['id'].'-1')); $master['start'] = $recurring['start']; $master['end'] = $recurring['end']; if ($master['recurrence']['COUNT']) @@ -584,13 +582,24 @@ class kolab_driver extends calendar_driver break; case 'current': - // add exception to master event - $master['recurrence']['EXDATE'][] = $old['start']; + // modifying the first instance => just move to next occurence + if ($master['id'] == $event['id']) { + $recurring = reset($storage->_get_recurring_events($event, $event['start'], null, $event['id'].'-1')); + $master['start'] = $recurring['start']; + $master['end'] = $recurring['end']; + if ($master['recurrence']['COUNT']) + $master['recurrence']['COUNT']--; + } + else { // add exception to master event + $master['recurrence']['EXDATE'][] = $old['start']; + } + $storage->update_event($master); // insert new event for this occurence $event += $old; $event['recurrence'] = array(); + unset($event['recurrence_id']); $event['uid'] = $this->cal->generate_uid(); $success = $storage->insert_event($event); break; @@ -628,11 +637,11 @@ class kolab_driver extends calendar_driver // use start date from master but try to be smart on time or duration changes $old_start_date = $old['start']->format('Y-m-d'); - $old_start_time = $old['start']->format('H:i'); + $old_start_time = $old['allday'] ? '' : $old['start']->format('H:i'); $old_duration = $old['end']->format('U') - $old['start']->format('U'); $new_start_date = $event['start']->format('Y-m-d'); - $new_start_time = $event['start']->format('H:i'); + $new_start_time = $event['allday'] ? '' : $event['start']->format('H:i'); $new_duration = $event['end']->format('U') - $event['start']->format('U'); $diff = $old_start_date != $new_start_date || $old_start_time != $new_start_time || $old_duration != $new_duration;