* Calendar/CalDAV: fixed iCal import of recurring events to convert (not understood) yearly byday to monthly byday with interval 12 and daily byday to weekly byday, also fixed of by one error in enddate

This commit is contained in:
Ralf Becker 2013-02-28 17:00:01 +00:00
parent 6d05cf328c
commit 9e873a7092

View File

@ -2451,6 +2451,24 @@ class calendar_ical extends calendar_boupdate
$vcardData['recur_data'] = 0; $vcardData['recur_data'] = 0;
switch($type) switch($type)
{ {
case 'D': // 1.0
if (preg_match('/D(\d+) #(\d+)/', $recurence, $recurenceMatches))
{
$vcardData['recur_interval'] = $recurenceMatches[1];
$vcardData['recur_count'] = $recurenceMatches[2];
}
elseif (preg_match('/D(\d+) (.*)/', $recurence, $recurenceMatches))
{
$vcardData['recur_interval'] = $recurenceMatches[1];
$vcardData['recur_enddate'] = $this->vCalendar->_parseDateTime(trim($recurenceMatches[2]));
}
else break;
// fall-through
case 'DAILY': // 2.0
$vcardData['recur_type'] = MCAL_RECUR_DAILY;
if (stripos($recurence, 'BYDAY') === false) break;
// hack to handle TYPE=DAILY;BYDAY= as WEEKLY, which is true as long as there's no interval
// fall-through
case 'W': case 'W':
case 'WEEKLY': case 'WEEKLY':
$days = array(); $days = array();
@ -2500,24 +2518,6 @@ class calendar_ical extends calendar_boupdate
} }
break; break;
case 'D': // 1.0
if (preg_match('/D(\d+) #(\d+)/', $recurence, $recurenceMatches))
{
$vcardData['recur_interval'] = $recurenceMatches[1];
$vcardData['recur_count'] = $recurenceMatches[2];
}
elseif (preg_match('/D(\d+) (.*)/', $recurence, $recurenceMatches))
{
$vcardData['recur_interval'] = $recurenceMatches[1];
$vcardData['recur_enddate'] = $this->vCalendar->_parseDateTime(trim($recurenceMatches[2]));
}
else break;
// fall-through
case 'DAILY': // 2.0
$vcardData['recur_type'] = MCAL_RECUR_DAILY;
break;
case 'M': case 'M':
if (preg_match('/MD(\d+)(?: [^ ]+)? #(\d+)/', $recurence, $recurenceMatches)) if (preg_match('/MD(\d+)(?: [^ ]+)? #(\d+)/', $recurence, $recurenceMatches))
{ {
@ -2545,10 +2545,6 @@ class calendar_ical extends calendar_boupdate
} }
} }
break; break;
case 'MONTHLY':
$vcardData['recur_type'] = strpos($recurence,'BYDAY') !== false ?
MCAL_RECUR_MONTHLY_WDAY : MCAL_RECUR_MONTHLY_MDAY;
break;
case 'Y': // 1.0 case 'Y': // 1.0
if (preg_match('/YM(\d+)(?: [^ ]+)? #(\d+)/', $recurence, $recurenceMatches)) if (preg_match('/YM(\d+)(?: [^ ]+)? #(\d+)/', $recurence, $recurenceMatches))
@ -2561,10 +2557,21 @@ class calendar_ical extends calendar_boupdate
$vcardData['recur_interval'] = $recurenceMatches[1]; $vcardData['recur_interval'] = $recurenceMatches[1];
$vcardData['recur_enddate'] = $this->vCalendar->_parseDateTime($recurenceMatches[2]); $vcardData['recur_enddate'] = $this->vCalendar->_parseDateTime($recurenceMatches[2]);
} else break; } else break;
// fall-through // fall-through
case 'YEARLY': // 2.0 case 'YEARLY': // 2.0
$vcardData['recur_type'] = MCAL_RECUR_YEARLY; if (strpos($recurence, 'BYDAY') === false)
{
$vcardData['recur_type'] = MCAL_RECUR_YEARLY;
break;
}
// handle FREQ=YEARLY;BYDAY= as FREQ=MONTHLY;BYDAY= with 12*INTERVAL
$vcardData['recur_interval'] = $vcardData['recur_interval'] ?
12*$vcardData['recur_interval'] : 12;
// fall-through
case 'MONTHLY':
// does currently NOT parse BYDAY or BYMONTH, it has to be specified/identical to DTSTART
$vcardData['recur_type'] = strpos($recurence,'BYDAY') !== false ?
MCAL_RECUR_MONTHLY_WDAY : MCAL_RECUR_MONTHLY_MDAY;
break; break;
} }
break; break;
@ -2930,20 +2937,18 @@ class calendar_ical extends calendar_boupdate
break; break;
} }
} }
if (!empty($event['recur_enddate'])) if ($event['recur_enddate'])
{ {
// reset recure_enddate to 00:00:00 on the last day // reset recure_enddate to 00:00:00 on the last day
$rriter = calendar_rrule::event2rrule($event, false); $rriter = calendar_rrule::event2rrule($event, false);
$rriter->rewind(); $rriter->rewind();
$last = clone $rriter->time; while ($rriter->current < $rriter->enddate)
while ($rriter->current <= $rriter->enddate)
{ {
$last = clone $rriter->current;
$rriter->next_no_exception(); $rriter->next_no_exception();
} }
//$delta = $event['end'] - $event['start']; $last = clone $rriter->current;
//$last->modify('+' . $delta . ' seconds');
$last->setTime(0, 0, 0); $last->setTime(0, 0, 0);
//error_log(__METHOD__."() rrule=$recurence --> ".array2string($rriter)." --> enddate=".array2string($last).'='.egw_time::to($last, ''));
$event['recur_enddate'] = egw_time::to($last, 'server'); $event['recur_enddate'] = egw_time::to($last, 'server');
} }
// translate COUNT into an enddate, as we only store enddates // translate COUNT into an enddate, as we only store enddates