Provide access to exception instances outside of a recurring event context (#4722)

This commit is contained in:
Thomas Bruederli 2015-02-26 11:25:29 +01:00
parent 1c590d3969
commit 31ad93a62e
3 changed files with 83 additions and 12 deletions

View file

@ -96,11 +96,15 @@ class kolab_format_event extends kolab_format_xcal
$status = $this->status_map[$object['status']];
$this->obj->setStatus($status);
// save recurrence exceptions
if (is_array($object['recurrence']) && is_array($object['recurrence']['EXCEPTIONS'])) {
// save (recurrence) exceptions
if (is_array($object['recurrence']) && is_array($object['recurrence']['EXCEPTIONS']) && !isset($object['exceptions'])) {
$object['exceptions'] = $object['recurrence']['EXCEPTIONS'];
}
if (is_array($object['exceptions'])) {
$recurrence_id_format = $object['allday'] ? 'Ymd' : 'Ymd\THis';
$vexceptions = new vectorevent;
foreach((array)$object['recurrence']['EXCEPTIONS'] as $i => $exception) {
foreach ($object['exceptions'] as $i => $exception) {
$exevent = new kolab_format_event;
$exevent->set(($compacted = $this->compact_exception($exception, $object))); // only save differing values
@ -118,11 +122,17 @@ class kolab_format_event extends kolab_format_xcal
$vexceptions->push($exevent->obj);
// write cleaned-up exception data back to memory/cache
$object['recurrence']['EXCEPTIONS'][$i] = $this->expand_exception($exevent->data, $object);
$object['exceptions'][$i] = $this->expand_exception($exevent->data, $object);
}
$this->obj->setExceptions($vexceptions);
// link with recurrence.EXCEPTIONS for compatibility
if (is_array($object['recurrence'])) {
$object['recurrence']['EXCEPTIONS'] = &$object['exceptions'];
}
else if ($object['recurrence_date'] && $object['recurrence_date'] instanceof DateTime) {
}
if ($object['recurrence_date'] && $object['recurrence_date'] instanceof DateTime) {
$this->obj->setRecurrenceID(self::get_datetime($object['recurrence_date'], null, $object['allday']), (bool)$object['thisandfuture']);
}
@ -194,7 +204,7 @@ class kolab_format_event extends kolab_format_xcal
$object['recurrence_date'] = self::php_datetime($this->obj->recurrenceID());
}
// read exception event objects
else if (($exceptions = $this->obj->exceptions()) && is_object($exceptions) && $exceptions->size()) {
if (($exceptions = $this->obj->exceptions()) && is_object($exceptions) && $exceptions->size()) {
$recurrence_exceptions = array();
$recurrence_id_format = $object['allday'] ? 'Ymd' : 'Ymd\THis';
for ($i=0; $i < $exceptions->size(); $i++) {
@ -215,12 +225,53 @@ class kolab_format_event extends kolab_format_xcal
}
}
}
$object['recurrence']['EXCEPTIONS'] = $recurrence_exceptions;
$object['exceptions'] = $recurrence_exceptions;
// also link with recurrence.EXCEPTIONS for compatibility
if (is_array($object['recurrence'])) {
$object['recurrence']['EXCEPTIONS'] = &$object['exceptions'];
}
}
return $this->data = $object;
}
/**
* Getter for a single instance from a recurrence series or stored subcomponents
*
* @param mixed The recurrence-id of the requested instance, either as string or a DateTime object
* @return array Event data as hash array or null if not found
*/
public function get_instance($recurrence_id)
{
$result = null;
$object = $this->to_array();
$recurrence_id_format = $object['allday'] ? 'Ymd' : 'Ymd\THis';
$instance_id = $recurrence_id instanceof DateTime ? $recurrence_id->format($recurrence_id_format) : strval($recurrence_id);
if ($object['recurrence_date'] instanceof DateTime) {
if ($object['recurrence_date']->format($recurrence_id_format) == $instance_id) {
$result = $object;
}
}
if (!$result && is_array($object['exceptions'])) {
foreach ($object['exceptions'] as $exception) {
if ($exception['_instance'] == $instance_id) {
$result = $exception;
$result['isexception'] = 1;
break;
}
}
}
// TODO: compute instances from recurrence rule and return the matching instance
// clone from plugins/calendar/drivers/kolab/kolab_calendar::get_recurring_events()
return $result;
}
/**
* Callback for kolab_storage_cache to get object specific tags to cache
*
@ -262,8 +313,10 @@ class kolab_format_event extends kolab_format_xcal
*/
private function expand_exception($exception, $master)
{
$is_recurring = !empty($master['recurrence']);
foreach ($master as $prop => $value) {
if (empty($exception[$prop]) && !empty($value)) {
if (empty($exception[$prop]) && !empty($value) && ($is_recurring || in_array($prop, array('uid','organizer','_attachments')))) {
$exception[$prop] = $value;
if ($prop == 'recurrence') {
unset($exception[$prop]['EXCEPTIONS']);

View file

@ -597,8 +597,8 @@ abstract class kolab_format_xcal extends kolab_format
$words = rcube_utils::normalize_string($data, true);
// collect words from recurrence exceptions
if (is_array($object['recurrence']) && $object['recurrence']['EXCEPTIONS']) {
foreach((array)$object['recurrence']['EXCEPTIONS'] as $exception) {
if (is_array($object['exceptions'])) {
foreach ($object['exceptions'] as $exception) {
$words = array_merge($words, $this->get_words($exception));
}
}
@ -629,8 +629,8 @@ abstract class kolab_format_xcal extends kolab_format
}
// collect tags from recurrence exceptions
if (is_array($object['recurrence']) && $object['recurrence']['EXCEPTIONS']) {
foreach((array)$object['recurrence']['EXCEPTIONS'] as $exception) {
if (is_array($object['exceptions'])) {
foreach ($object['exceptions'] as $exception) {
$tags = array_merge($tags, $this->get_tags($exception));
}
}

View file

@ -44,6 +44,24 @@ class kolab_storage_cache_event extends kolab_storage_cache
$sql_data['dtend'] = $dtend->format(self::DB_DATE_FORMAT);
}
// extend start/end dates to spawn all exceptions
if (is_array($object['exceptions'])) {
foreach ($object['exceptions'] as $exception) {
if (is_a($exception['start'], 'DateTime')) {
$exstart = $exception['start']->format(self::DB_DATE_FORMAT);
if ($exstart < $sql_data['dtstart']) {
$sql_data['dtstart'] = $exstart;
}
}
if (is_a($exception['end'], 'DateTime')) {
$exend = $exception['end']->format(self::DB_DATE_FORMAT);
if ($exend > $sql_data['dtend']) {
$sql_data['dtend'] = $exend;
}
}
}
}
return $sql_data;
}
}