mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-11-07 08:34:42 +01:00
Calendar: iCal can import events that use RDATE:VALUE=PERIOD
This commit is contained in:
parent
66a1fd2670
commit
0d87e1ab2b
@ -945,7 +945,8 @@ class calendar_bo
|
||||
}
|
||||
foreach($events as $event)
|
||||
{
|
||||
$is_exception = in_array(Api\DateTime::to($event['start'], true), $exceptions);
|
||||
// PERIOD
|
||||
$is_exception = $event['recur_type'] != calendar_rrule::PERIOD && in_array(Api\DateTime::to($event['start'], true), $exceptions);
|
||||
$start = $this->date2ts($event['start'],true);
|
||||
if ($event['whole_day'])
|
||||
{
|
||||
@ -1164,12 +1165,20 @@ class calendar_bo
|
||||
new Api\DateTime($event['recur_enddate'], calendar_timezones::DateTimeZone($event['tzid']));
|
||||
|
||||
// unset exceptions, as we need to add them as recurrence too, but marked as exception
|
||||
unset($event['recur_exception']);
|
||||
// (Period needs them though)
|
||||
if($event['recur_type'] != calendar_rrule::PERIOD)
|
||||
{
|
||||
unset($event['recur_exception']);
|
||||
}
|
||||
// loop over all recurrences and insert them, if they are after $start
|
||||
$rrule = calendar_rrule::event2rrule($event, !$event['whole_day'], // true = we operate in usertime, like the rest of calendar_bo
|
||||
// For whole day events, just stay in server time
|
||||
$event['whole_day'] ? Api\DateTime::$server_timezone->getName() : Api\DateTime::$user_timezone->getName()
|
||||
);
|
||||
if($event['recur_type'] == calendar_rrule::PERIOD)
|
||||
{
|
||||
unset($event['recur_exception']);
|
||||
}
|
||||
foreach($rrule as $time)
|
||||
{
|
||||
// $time is in timezone of event, convert it to usertime used here
|
||||
|
@ -2748,6 +2748,27 @@ class calendar_ical extends calendar_boupdate
|
||||
$vcardData += calendar_rrule::parseRrule($attributes['value'], false, $vcardData);
|
||||
if (!empty($vcardData['recur_enddate'])) self::check_fix_endate ($vcardData);
|
||||
break;
|
||||
case 'RDATE':
|
||||
$hour = date('H', $vcardData['start']);
|
||||
$minutes = date('i', $vcardData['start']);
|
||||
$seconds = date('s', $vcardData['start']);
|
||||
if($attributes['params']['VALUE'] == 'PERIOD')
|
||||
{
|
||||
$vcardData['recur_type'] = calendar_rrule::PERIOD;
|
||||
$vcardData['recur_exception'] = [];
|
||||
foreach($attributes['values'] as $date)
|
||||
{
|
||||
$vcardData['recur_exception'][] = mktime(
|
||||
$hour,
|
||||
$minutes,
|
||||
$seconds,
|
||||
$date['month'],
|
||||
$date['mday'],
|
||||
$date['year']
|
||||
);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'EXDATE': // current Horde_Icalendar returns dates, no timestamps
|
||||
if ($attributes['values'])
|
||||
{
|
||||
|
@ -65,6 +65,12 @@ class calendar_rrule implements Iterator
|
||||
*/
|
||||
const MINUTELY = 7;
|
||||
|
||||
/**
|
||||
* By date or period
|
||||
* (a list of dates)
|
||||
*/
|
||||
const PERIOD = 9;
|
||||
|
||||
/**
|
||||
* Translate recure types to labels
|
||||
*
|
||||
@ -77,6 +83,7 @@ class calendar_rrule implements Iterator
|
||||
self::MONTHLY_WDAY => 'Monthly (by day)',
|
||||
self::MONTHLY_MDAY => 'Monthly (by date)',
|
||||
self::YEARLY => 'Yearly',
|
||||
self::PERIOD => 'By date or period'
|
||||
);
|
||||
|
||||
/**
|
||||
@ -90,6 +97,7 @@ class calendar_rrule implements Iterator
|
||||
self::YEARLY => 'YEARLY',
|
||||
self::HOURLY => 'HOURLY',
|
||||
self::MINUTELY => 'MINUTELY',
|
||||
self::PERIOD => 'PERIOD'
|
||||
);
|
||||
|
||||
/**
|
||||
@ -135,6 +143,12 @@ class calendar_rrule implements Iterator
|
||||
*/
|
||||
public $monthly_bymonthday;
|
||||
|
||||
/**
|
||||
* Period list
|
||||
* @var
|
||||
*/
|
||||
public $period = [];
|
||||
|
||||
/**
|
||||
* Enddate of recurring event or null, if not ending
|
||||
*
|
||||
@ -261,7 +275,8 @@ class calendar_rrule implements Iterator
|
||||
|
||||
$this->time = $time instanceof Api\DateTime ? $time : new Api\DateTime($time);
|
||||
|
||||
if (!in_array($type,array(self::NONE, self::DAILY, self::WEEKLY, self::MONTHLY_MDAY, self::MONTHLY_WDAY, self::YEARLY, self::HOURLY, self::MINUTELY)))
|
||||
if(!in_array($type, array(self::NONE, self::DAILY, self::WEEKLY, self::MONTHLY_MDAY, self::MONTHLY_WDAY,
|
||||
self::YEARLY, self::HOURLY, self::MINUTELY, self::PERIOD)))
|
||||
{
|
||||
throw new Api\Exception\WrongParameter(__METHOD__."($time,$type,$interval,$enddate,$weekdays,...) type $type is NOT valid!");
|
||||
}
|
||||
@ -302,6 +317,19 @@ class calendar_rrule implements Iterator
|
||||
$this->interval = (int)$interval;
|
||||
|
||||
$this->enddate = $enddate;
|
||||
if($type == self::PERIOD)
|
||||
{
|
||||
foreach($exceptions as $exception)
|
||||
{
|
||||
$exception->setTimezone($this->time->getTimezone());
|
||||
$this->period[] = $exception;
|
||||
}
|
||||
$enddate = clone(count($this->period) ? end($this->period) : $this->time);
|
||||
// Make sure to include the last date as valid
|
||||
$enddate->modify('+1 second');
|
||||
reset($this->period);
|
||||
unset($exceptions);
|
||||
}
|
||||
// no recurrence --> current date is enddate
|
||||
if ($type == self::NONE)
|
||||
{
|
||||
@ -469,6 +497,16 @@ class calendar_rrule implements Iterator
|
||||
case self::MINUTELY:
|
||||
$this->current->modify($this->interval.' minute');
|
||||
break;
|
||||
case self::PERIOD:
|
||||
$index = array_search($this->current, $this->period);
|
||||
$next = $this->enddate ?? new Api\DateTime();
|
||||
if($index !== false && $index + 1 < count($this->period))
|
||||
{
|
||||
$next = $this->period[$index + 1];
|
||||
}
|
||||
$this->current->setDate($next->format('Y'), $next->format('m'), $next->format('d'));
|
||||
$this->current->setTime($next->format('H'), $next->format('i'), $next->format('s'), 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Api\Exception\AssertionFailed(__METHOD__."() invalid type #$this->type !");
|
||||
@ -737,6 +775,13 @@ class calendar_rrule implements Iterator
|
||||
$rrule['BYDAY'] = $this->monthly_byday_num .
|
||||
strtoupper(substr($this->time->format('l'),0,2));
|
||||
break;
|
||||
case self::PERIOD:
|
||||
$period = [];
|
||||
foreach($this->period as $date)
|
||||
{
|
||||
$period[] = $date->format("Ymd\THms\Z");
|
||||
}
|
||||
$rrule['PERIOD'] = implode(',', $period);
|
||||
}
|
||||
if ($this->interval > 1)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user