mirror of
https://github.com/EGroupware/egroupware.git
synced 2024-12-24 23:59:39 +01:00
* Calendar: fix generating/importing exceptions on recurring events using explicit RDATEs instead of a RRULE
also correctly recognize Windows timezone names without "Standard Time" postfix like "Romance" instead of "Romance Standard Time" for "Europe/Paris"
This commit is contained in:
parent
cc98141e86
commit
2bfcc20856
@ -128,7 +128,8 @@ class calendar_bo
|
|||||||
MCAL_RECUR_WEEKLY => 'Weekly',
|
MCAL_RECUR_WEEKLY => 'Weekly',
|
||||||
MCAL_RECUR_MONTHLY_WDAY => 'Monthly (by day)',
|
MCAL_RECUR_MONTHLY_WDAY => 'Monthly (by day)',
|
||||||
MCAL_RECUR_MONTHLY_MDAY => 'Monthly (by date)',
|
MCAL_RECUR_MONTHLY_MDAY => 'Monthly (by date)',
|
||||||
MCAL_RECUR_YEARLY => 'Yearly'
|
MCAL_RECUR_YEARLY => 'Yearly',
|
||||||
|
MCAL_RECUR_RDATE/*calendar_rrule::PERIOD*/ => 'Explicit dates',
|
||||||
);
|
);
|
||||||
/**
|
/**
|
||||||
* @var array recur_days translates MCAL recur-days to verbose labels
|
* @var array recur_days translates MCAL recur-days to verbose labels
|
||||||
@ -946,7 +947,7 @@ class calendar_bo
|
|||||||
foreach($events as $event)
|
foreach($events as $event)
|
||||||
{
|
{
|
||||||
// PERIOD
|
// PERIOD
|
||||||
$is_exception = $event['recur_type'] != calendar_rrule::PERIOD && in_array(Api\DateTime::to($event['start'], true), $exceptions);
|
$is_exception = in_array(Api\DateTime::to($event['start'], true), $exceptions);
|
||||||
$start = $this->date2ts($event['start'],true);
|
$start = $this->date2ts($event['start'],true);
|
||||||
if ($event['whole_day'])
|
if ($event['whole_day'])
|
||||||
{
|
{
|
||||||
@ -1024,10 +1025,11 @@ class calendar_bo
|
|||||||
$event[$ts] = $this->date2usertime((int)$event[$ts],$date_format);
|
$event[$ts] = $this->date2usertime((int)$event[$ts],$date_format);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// same with the recur exceptions
|
// same with the recur exceptions and rdates
|
||||||
if (isset($event['recur_exception']) && is_array($event['recur_exception']))
|
foreach(['recur_exception', 'recur_rdates'] as $name)
|
||||||
{
|
{
|
||||||
foreach($event['recur_exception'] as &$date)
|
if (is_array($event[$name] ?? null)) continue;
|
||||||
|
foreach($event[$name] as &$date)
|
||||||
{
|
{
|
||||||
if ($event['whole_day'] && $date_format != 'server')
|
if ($event['whole_day'] && $date_format != 'server')
|
||||||
{
|
{
|
||||||
@ -1139,7 +1141,6 @@ class calendar_bo
|
|||||||
* @param mixed $start start-date
|
* @param mixed $start start-date
|
||||||
* @param mixed $end end-date
|
* @param mixed $end end-date
|
||||||
* @param array $events where the repetions get inserted
|
* @param array $events where the repetions get inserted
|
||||||
* @param array $recur_exceptions with date (in Ymd) as key (and True as values), seems not to be used anymore
|
|
||||||
*/
|
*/
|
||||||
function insert_all_recurrences($event,$_start,$end,&$events)
|
function insert_all_recurrences($event,$_start,$end,&$events)
|
||||||
{
|
{
|
||||||
@ -1165,20 +1166,15 @@ class calendar_bo
|
|||||||
new Api\DateTime($event['recur_enddate'], calendar_timezones::DateTimeZone($event['tzid']));
|
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 exceptions, as we need to add them as recurrence too, but marked as exception
|
||||||
// (Period needs them though)
|
|
||||||
if($event['recur_type'] != calendar_rrule::PERIOD)
|
|
||||||
{
|
|
||||||
unset($event['recur_exception']);
|
unset($event['recur_exception']);
|
||||||
}
|
|
||||||
// loop over all recurrences and insert them, if they are after $start
|
// 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
|
$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
|
// For whole day events, just stay in server time
|
||||||
$event['whole_day'] ? Api\DateTime::$server_timezone->getName() : Api\DateTime::$user_timezone->getName()
|
$event['whole_day'] ? Api\DateTime::$server_timezone->getName() : Api\DateTime::$user_timezone->getName()
|
||||||
);
|
);
|
||||||
if($event['recur_type'] == calendar_rrule::PERIOD)
|
unset($event['recur_rdates']);
|
||||||
{
|
$event['recur_type'] = MCAL_RECUR_NONE;
|
||||||
unset($event['recur_exception']);
|
|
||||||
}
|
|
||||||
foreach($rrule as $time)
|
foreach($rrule as $time)
|
||||||
{
|
{
|
||||||
// $time is in timezone of event, convert it to usertime used here
|
// $time is in timezone of event, convert it to usertime used here
|
||||||
@ -1194,7 +1190,7 @@ class calendar_bo
|
|||||||
if (($ts = $this->date2ts($time)) < $start-$event_length)
|
if (($ts = $this->date2ts($time)) < $start-$event_length)
|
||||||
{
|
{
|
||||||
//echo "<p>".$time." --> ignored as $ts < $start-$event_length</p>\n";
|
//echo "<p>".$time." --> ignored as $ts < $start-$event_length</p>\n";
|
||||||
continue; // to early or original event (returned by interator too)
|
continue; // to early or original event (returned by iterator too)
|
||||||
}
|
}
|
||||||
|
|
||||||
$ts_end = $ts + $event_length;
|
$ts_end = $ts + $event_length;
|
||||||
@ -1230,7 +1226,7 @@ class calendar_bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds one repetion of $event for $date_ymd to the $events array, after adjusting its start- and end-time
|
* Adds one repetition of $event for $date_ymd to the $events array, after adjusting its start- and end-time
|
||||||
*
|
*
|
||||||
* @param array $events array in which the event gets inserted
|
* @param array $events array in which the event gets inserted
|
||||||
* @param array $event event to insert, it has start- and end-date of the first recurrence, not of $date_ymd
|
* @param array $event event to insert, it has start- and end-date of the first recurrence, not of $date_ymd
|
||||||
|
@ -1404,7 +1404,7 @@ class calendar_boupdate extends calendar_bo
|
|||||||
$this->check_reset_statuses($event, $old_event);
|
$this->check_reset_statuses($event, $old_event);
|
||||||
|
|
||||||
// set recur-enddate/range-end to real end-date of last recurrence
|
// set recur-enddate/range-end to real end-date of last recurrence
|
||||||
if (!empty($event['recur_type']) && $event['recur_enddate'] && $event['start'])
|
if (!empty($event['recur_type']) && (!empty($event['recur_enddate']) || $event['recur_type'] == calendar_rrule::PERIOD) && $event['start'])
|
||||||
{
|
{
|
||||||
$event['recur_enddate'] = new Api\DateTime($event['recur_enddate'], calendar_timezones::DateTimeZone($event['tzid']));
|
$event['recur_enddate'] = new Api\DateTime($event['recur_enddate'], calendar_timezones::DateTimeZone($event['tzid']));
|
||||||
$event['recur_enddate']->setTime(23,59,59);
|
$event['recur_enddate']->setTime(23,59,59);
|
||||||
@ -1485,10 +1485,11 @@ class calendar_boupdate extends calendar_bo
|
|||||||
{
|
{
|
||||||
$event['tz_id'] = calendar_timezones::tz2id($event['tzid'] = Api\DateTime::$user_timezone->getName());
|
$event['tz_id'] = calendar_timezones::tz2id($event['tzid'] = Api\DateTime::$user_timezone->getName());
|
||||||
}
|
}
|
||||||
// same with the recur exceptions
|
// same with the recur exceptions and rdates
|
||||||
if (isset($event['recur_exception']) && is_array($event['recur_exception']))
|
foreach(['recur_exception', 'recur_rdates'] as $name)
|
||||||
{
|
{
|
||||||
foreach($event['recur_exception'] as &$date)
|
if (!is_array($event[$name] ?? null)) continue;
|
||||||
|
foreach($event[$name] as &$date)
|
||||||
{
|
{
|
||||||
if ($event['whole_day'])
|
if ($event['whole_day'])
|
||||||
{
|
{
|
||||||
@ -2400,9 +2401,9 @@ class calendar_boupdate extends calendar_bo
|
|||||||
*
|
*
|
||||||
* @param array $event the vCalendar data we try to find
|
* @param array $event the vCalendar data we try to find
|
||||||
* @param string filter='exact' exact -> find the matching entry
|
* @param string filter='exact' exact -> find the matching entry
|
||||||
* check -> check (consitency) for identical matches
|
* check -> check (consistency) for identical matches
|
||||||
* relax -> be more tolerant
|
* relax -> be more tolerant
|
||||||
* master -> try to find a releated series master
|
* master -> try to find a related series master
|
||||||
* @return array calendar_ids of matching entries
|
* @return array calendar_ids of matching entries
|
||||||
*/
|
*/
|
||||||
function find_event($event, $filter='exact')
|
function find_event($event, $filter='exact')
|
||||||
@ -3120,12 +3121,12 @@ class calendar_boupdate extends calendar_bo
|
|||||||
// we convert here from server-time to timestamps in user-time!
|
// we convert here from server-time to timestamps in user-time!
|
||||||
if (isset($event[$ts])) $event[$ts] = $event[$ts] ? $this->date2usertime($event[$ts]) : 0;
|
if (isset($event[$ts])) $event[$ts] = $event[$ts] ? $this->date2usertime($event[$ts]) : 0;
|
||||||
}
|
}
|
||||||
// same with the recur exceptions
|
// same with the recur exceptions and rdates
|
||||||
if (isset($event['recur_exception']) && is_array($event['recur_exception']))
|
foreach(['recur_exception', 'recur_rdates'] as $name)
|
||||||
{
|
{
|
||||||
foreach($event['recur_exception'] as $n => $date)
|
foreach($event[$name] ?? [] as $n => $date)
|
||||||
{
|
{
|
||||||
$event['recur_exception'][$n] = $this->date2usertime($date);
|
$event[$name][$n] = $this->date2usertime($date);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// same with the alarms
|
// same with the alarms
|
||||||
@ -3137,6 +3138,7 @@ class calendar_boupdate extends calendar_bo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete events that are more than $age years old
|
* Delete events that are more than $age years old
|
||||||
*
|
*
|
||||||
|
@ -2760,10 +2760,10 @@ class calendar_ical extends calendar_boupdate
|
|||||||
if($attributes['params']['VALUE'] == 'PERIOD')
|
if($attributes['params']['VALUE'] == 'PERIOD')
|
||||||
{
|
{
|
||||||
$vcardData['recur_type'] = calendar_rrule::PERIOD;
|
$vcardData['recur_type'] = calendar_rrule::PERIOD;
|
||||||
$vcardData['recur_exception'] = [];
|
$vcardData['recur_rdates'] = [];
|
||||||
foreach($attributes['values'] as $date)
|
foreach($attributes['values'] as $date)
|
||||||
{
|
{
|
||||||
$vcardData['recur_exception'][] = mktime(
|
$vcardData['recur_rdates'][] = mktime(
|
||||||
$hour,
|
$hour,
|
||||||
$minutes,
|
$minutes,
|
||||||
$seconds,
|
$seconds,
|
||||||
@ -3180,7 +3180,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
$event['priority'] = 2; // default
|
$event['priority'] = 2; // default
|
||||||
$event['alarm'] = $alarms;
|
$event['alarm'] = $alarms;
|
||||||
|
|
||||||
// now that we know what the vard provides,
|
// now that we know what the ical provides,
|
||||||
// we merge that data with the information we have about the device
|
// we merge that data with the information we have about the device
|
||||||
while (($fieldName = array_shift($supportedFields)))
|
while (($fieldName = array_shift($supportedFields)))
|
||||||
{
|
{
|
||||||
@ -3191,6 +3191,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
case 'recur_data':
|
case 'recur_data':
|
||||||
case 'recur_exception':
|
case 'recur_exception':
|
||||||
case 'recur_count':
|
case 'recur_count':
|
||||||
|
case 'recur_rdates':
|
||||||
case 'whole_day':
|
case 'whole_day':
|
||||||
// not handled here
|
// not handled here
|
||||||
break;
|
break;
|
||||||
@ -3200,7 +3201,7 @@ class calendar_ical extends calendar_boupdate
|
|||||||
if ($event['recur_type'] != MCAL_RECUR_NONE)
|
if ($event['recur_type'] != MCAL_RECUR_NONE)
|
||||||
{
|
{
|
||||||
$event['reference'] = 0;
|
$event['reference'] = 0;
|
||||||
foreach (array('recur_interval','recur_enddate','recur_data','recur_exception','recur_count') as $r)
|
foreach (array('recur_interval','recur_enddate','recur_data','recur_exception','recur_count','recur_rdates') as $r)
|
||||||
{
|
{
|
||||||
if (isset($vcardData[$r]))
|
if (isset($vcardData[$r]))
|
||||||
{
|
{
|
||||||
|
@ -45,29 +45,28 @@ class calendar_rrule implements Iterator
|
|||||||
*/
|
*/
|
||||||
const WEEKLY = 2;
|
const WEEKLY = 2;
|
||||||
/**
|
/**
|
||||||
* Monthly recurrance iCal: monthly_bymonthday
|
* Monthly recurrence iCal: monthly_bymonthday
|
||||||
*/
|
*/
|
||||||
const MONTHLY_MDAY = 3;
|
const MONTHLY_MDAY = 3;
|
||||||
/**
|
/**
|
||||||
* Monthly recurrance iCal: BYDAY (by weekday, eg. 1st Friday of month)
|
* Monthly recurrence iCal: BYDAY (by weekday, eg. 1st Friday of month)
|
||||||
*/
|
*/
|
||||||
const MONTHLY_WDAY = 4;
|
const MONTHLY_WDAY = 4;
|
||||||
/**
|
/**
|
||||||
* Yearly recurrance
|
* Yearly recurrence
|
||||||
*/
|
*/
|
||||||
const YEARLY = 5;
|
const YEARLY = 5;
|
||||||
/**
|
/**
|
||||||
* Hourly recurrance
|
* Hourly recurrence
|
||||||
*/
|
*/
|
||||||
const HOURLY = 8;
|
const HOURLY = 8;
|
||||||
/**
|
/**
|
||||||
* Minutely recurrance
|
* Minutely recurrence
|
||||||
*/
|
*/
|
||||||
const MINUTELY = 7;
|
const MINUTELY = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* By date or period
|
* RDATE: date or period (a list of dates, instead of a RRULE)
|
||||||
* (a list of dates)
|
|
||||||
*/
|
*/
|
||||||
const PERIOD = 9;
|
const PERIOD = 9;
|
||||||
|
|
||||||
@ -226,9 +225,9 @@ class calendar_rrule implements Iterator
|
|||||||
public $time;
|
public $time;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Current "position" / time
|
* Current "position" / time or null, if invalid (out of explicit RDATEs)
|
||||||
*
|
*
|
||||||
* @var Api\DateTime
|
* @var Api\DateTime|null
|
||||||
*/
|
*/
|
||||||
public $current;
|
public $current;
|
||||||
|
|
||||||
@ -257,9 +256,10 @@ class calendar_rrule implements Iterator
|
|||||||
* @param int $interval =1 1, 2, ...
|
* @param int $interval =1 1, 2, ...
|
||||||
* @param DateTime $enddate =null enddate or null for no enddate (in which case we user '+5 year' on $time)
|
* @param DateTime $enddate =null enddate or null for no enddate (in which case we user '+5 year' on $time)
|
||||||
* @param int $weekdays =0 self::SUNDAY=1|self::MONDAY=2|...|self::SATURDAY=64
|
* @param int $weekdays =0 self::SUNDAY=1|self::MONDAY=2|...|self::SATURDAY=64
|
||||||
* @param array $exceptions =null DateTime objects with exceptions
|
* @param DateTime[] $exceptions =null DateTime objects with exceptions
|
||||||
|
* @param DateTime[] $rdates =null DateTime objects with rdates (for type self::PERIOD)
|
||||||
*/
|
*/
|
||||||
public function __construct(DateTime $time,$type,$interval=1,DateTime $enddate=null,$weekdays=0,array $exceptions=null)
|
public function __construct(DateTime $time,$type,$interval=1,DateTime $enddate=null,$weekdays=0,array $exceptions=null,array $rdates=null)
|
||||||
{
|
{
|
||||||
switch($GLOBALS['egw_info']['user']['preferences']['calendar']['weekdaystarts'])
|
switch($GLOBALS['egw_info']['user']['preferences']['calendar']['weekdaystarts'])
|
||||||
{
|
{
|
||||||
@ -319,16 +319,15 @@ class calendar_rrule implements Iterator
|
|||||||
$this->enddate = $enddate;
|
$this->enddate = $enddate;
|
||||||
if($type == self::PERIOD)
|
if($type == self::PERIOD)
|
||||||
{
|
{
|
||||||
foreach($exceptions as $exception)
|
foreach($rdates as $rdate)
|
||||||
{
|
{
|
||||||
$exception->setTimezone($this->time->getTimezone());
|
$rdate->setTimezone($this->time->getTimezone());
|
||||||
$this->period[] = $exception;
|
$this->period[] = $rdate;
|
||||||
}
|
}
|
||||||
$enddate = clone(count($this->period) ? end($this->period) : $this->time);
|
$enddate = clone(count($this->period) ? end($this->period) : $this->time);
|
||||||
// Make sure to include the last date as valid
|
// Make sure to include the last date as valid
|
||||||
$enddate->modify('+1 second');
|
$enddate->modify('+1 second');
|
||||||
reset($this->period);
|
reset($this->period);
|
||||||
unset($exceptions);
|
|
||||||
}
|
}
|
||||||
// no recurrence --> current date is enddate
|
// no recurrence --> current date is enddate
|
||||||
if ($type == self::NONE)
|
if ($type == self::NONE)
|
||||||
@ -413,11 +412,11 @@ class calendar_rrule implements Iterator
|
|||||||
/**
|
/**
|
||||||
* Return the current element
|
* Return the current element
|
||||||
*
|
*
|
||||||
* @return Api\DateTime
|
* @return ?Api\DateTime
|
||||||
*/
|
*/
|
||||||
public function current(): Api\DateTime
|
public function current(): ?Api\DateTime
|
||||||
{
|
{
|
||||||
return clone $this->current;
|
return $this->current ? clone $this->current : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -427,7 +426,7 @@ class calendar_rrule implements Iterator
|
|||||||
*/
|
*/
|
||||||
public function key(): int
|
public function key(): int
|
||||||
{
|
{
|
||||||
return (int)$this->current->format('Ymd');
|
return $this->current ? (int)$this->current->format('Ymd') : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -498,14 +497,15 @@ class calendar_rrule implements Iterator
|
|||||||
$this->current->modify($this->interval.' minute');
|
$this->current->modify($this->interval.' minute');
|
||||||
break;
|
break;
|
||||||
case self::PERIOD:
|
case self::PERIOD:
|
||||||
$index = array_search($this->current, $this->period);
|
if (($next = next($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->setDate($next->format('Y'), $next->format('m'), $next->format('d'));
|
||||||
$this->current->setTime($next->format('H'), $next->format('i'), $next->format('s'), 0);
|
$this->current->setTime($next->format('H'), $next->format('i'), $next->format('s'), 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$this->current = null;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -522,7 +522,7 @@ class calendar_rrule implements Iterator
|
|||||||
{
|
{
|
||||||
$this->next_no_exception();
|
$this->next_no_exception();
|
||||||
}
|
}
|
||||||
while($this->exceptions && in_array($this->current->format('Ymd'),$this->exceptions));
|
while($this->current && $this->exceptions && in_array($this->current->format('Ymd'),$this->exceptions));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -595,6 +595,10 @@ class calendar_rrule implements Iterator
|
|||||||
*/
|
*/
|
||||||
public function rewind(): void
|
public function rewind(): void
|
||||||
{
|
{
|
||||||
|
if ($this->type == self::PERIOD)
|
||||||
|
{
|
||||||
|
reset($this->period);
|
||||||
|
}
|
||||||
$this->current = clone $this->time;
|
$this->current = clone $this->time;
|
||||||
while ($this->valid() &&
|
while ($this->valid() &&
|
||||||
$this->exceptions &&
|
$this->exceptions &&
|
||||||
@ -612,6 +616,10 @@ class calendar_rrule implements Iterator
|
|||||||
*/
|
*/
|
||||||
public function validDate(bool $use_just_date=null): bool
|
public function validDate(bool $use_just_date=null): bool
|
||||||
{
|
{
|
||||||
|
if (!$this->current)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if ($use_just_date)
|
if ($use_just_date)
|
||||||
{
|
{
|
||||||
return $this->current->format('Ymd') <= $this->enddate_ymd;
|
return $this->current->format('Ymd') <= $this->enddate_ymd;
|
||||||
@ -626,7 +634,7 @@ class calendar_rrule implements Iterator
|
|||||||
*/
|
*/
|
||||||
public function valid(): bool
|
public function valid(): bool
|
||||||
{
|
{
|
||||||
return $this->current->format('ts') < $this->enddate_ts;
|
return $this->current && $this->current->format('ts') < $this->enddate_ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -853,10 +861,17 @@ class calendar_rrule implements Iterator
|
|||||||
{
|
{
|
||||||
foreach($event['recur_exception'] as $exception)
|
foreach($event['recur_exception'] as $exception)
|
||||||
{
|
{
|
||||||
$exceptions[] = is_a($exception,'DateTime') ? $exception : new Api\DateTime($exception,$timestamp_tz);
|
$exceptions[] = is_a($exception,'DateTime') ? $exception : new Api\DateTime($exception, $timestamp_tz);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return new calendar_rrule($time,$event['recur_type'],$event['recur_interval'],$enddate??null,$event['recur_data'],$exceptions??null);
|
if (is_array($event['recur_rdates']))
|
||||||
|
{
|
||||||
|
foreach($event['recur_rdates'] as $rdate)
|
||||||
|
{
|
||||||
|
$rdates[] = is_a($rdate,'DateTime') ? $rdate : new Api\DateTime($rdate, $timestamp_tz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new calendar_rrule($time,$event['recur_type'],$event['recur_interval'],$enddate??null,$event['recur_data'],$exceptions??null,$rdates??null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -955,6 +970,7 @@ class calendar_rrule implements Iterator
|
|||||||
'recur_enddate' => $this->enddate ? $this->enddate->format('ts') : null,
|
'recur_enddate' => $this->enddate ? $this->enddate->format('ts') : null,
|
||||||
'recur_data' => $this->weekdays,
|
'recur_data' => $this->weekdays,
|
||||||
'recur_exception' => $this->exceptions,
|
'recur_exception' => $this->exceptions,
|
||||||
|
'recur_rdates' => $this->period,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,7 @@ if(!extension_loaded('mcal'))
|
|||||||
define('MCAL_M_WEEKEND',65);
|
define('MCAL_M_WEEKEND',65);
|
||||||
define('MCAL_M_ALLDAYS',127);
|
define('MCAL_M_ALLDAYS',127);
|
||||||
}
|
}
|
||||||
|
define('MCAL_RECUR_RDATE',9);
|
||||||
|
|
||||||
define('REJECTED',0);
|
define('REJECTED',0);
|
||||||
define('NO_RESPONSE',1);
|
define('NO_RESPONSE',1);
|
||||||
@ -311,7 +312,7 @@ class calendar_so
|
|||||||
* All times (start, end and modified) are returned as timesstamps in servertime!
|
* All times (start, end and modified) are returned as timesstamps in servertime!
|
||||||
*
|
*
|
||||||
* @param int|array|string $ids id or array of id's of the entries to read, or string with a single uid
|
* @param int|array|string $ids id or array of id's of the entries to read, or string with a single uid
|
||||||
* @param int $recur_date =0 if set read the next recurrence at or after the timestamp, default 0 = read the initital one
|
* @param int $recur_date =0 if set read the next recurrence at or after the timestamp, default 0 = read the initial one
|
||||||
* @param boolean $read_recurrence =false true: read the exception, not the series master (only for recur_date && $ids='<uid>'!)
|
* @param boolean $read_recurrence =false true: read the exception, not the series master (only for recur_date && $ids='<uid>'!)
|
||||||
* @return array|boolean array with cal_id => event array pairs or false if entry not found
|
* @return array|boolean array with cal_id => event array pairs or false if entry not found
|
||||||
*/
|
*/
|
||||||
@ -426,13 +427,22 @@ class calendar_so
|
|||||||
}
|
}
|
||||||
if (!(int)$recur_date && !empty($event['recur_type']))
|
if (!(int)$recur_date && !empty($event['recur_type']))
|
||||||
{
|
{
|
||||||
foreach($this->db->select($this->dates_table, 'cal_id,cal_start', array(
|
foreach($this->db->select($this->dates_table, 'cal_id,cal_start,recur_exception', [
|
||||||
'cal_id' => $ids,
|
'cal_id' => $ids,
|
||||||
|
]+($event['recur_type'] == MCAL_RECUR_RDATE ? [] : [
|
||||||
'recur_exception' => true,
|
'recur_exception' => true,
|
||||||
), __LINE__, __FILE__, false, 'ORDER BY cal_id,cal_start', 'calendar') as $row)
|
]), __LINE__, __FILE__, false, 'ORDER BY cal_id,cal_start', 'calendar') as $row)
|
||||||
|
{
|
||||||
|
if ($row['recur_exception'])
|
||||||
{
|
{
|
||||||
$events[$row['cal_id']]['recur_exception'][] = $row['cal_start'];
|
$events[$row['cal_id']]['recur_exception'][] = $row['cal_start'];
|
||||||
}
|
}
|
||||||
|
// rdates are both, exceptions and regular dates!
|
||||||
|
if ($event['recur_type'] == MCAL_RECUR_RDATE)
|
||||||
|
{
|
||||||
|
$events[$row['cal_id']]['recur_rdates'][] = $row['cal_start'];
|
||||||
|
}
|
||||||
|
}
|
||||||
break; // as above select read all exceptions (and I dont think too short uid problem still exists)
|
break; // as above select read all exceptions (and I dont think too short uid problem still exists)
|
||||||
}
|
}
|
||||||
// make sure we fetch only real exceptions (deleted occurrences of a series should not show up)
|
// make sure we fetch only real exceptions (deleted occurrences of a series should not show up)
|
||||||
@ -1496,7 +1506,7 @@ ORDER BY cal_user_type, cal_usre_id
|
|||||||
|
|
||||||
if ($cal_id)
|
if ($cal_id)
|
||||||
{
|
{
|
||||||
// query old recurrance information, before updating main table, where recur_endate is now stored
|
// query old recurrence information, before updating main table, where recur_endate is now stored
|
||||||
if (!empty($event['recur_type']))
|
if (!empty($event['recur_type']))
|
||||||
{
|
{
|
||||||
$old_repeats = $this->db->select($this->repeats_table, "$this->repeats_table.*,range_end AS recur_enddate",
|
$old_repeats = $this->db->select($this->repeats_table, "$this->repeats_table.*,range_end AS recur_enddate",
|
||||||
@ -1610,7 +1620,7 @@ ORDER BY cal_user_type, cal_usre_id
|
|||||||
}
|
}
|
||||||
|
|
||||||
$event['recur_exception'] = is_array($event['recur_exception']) ? $event['recur_exception'] : array();
|
$event['recur_exception'] = is_array($event['recur_exception']) ? $event['recur_exception'] : array();
|
||||||
if (!empty($event['recur_exception']))
|
if (count($event['recur_exception']) > 1)
|
||||||
{
|
{
|
||||||
sort($event['recur_exception']);
|
sort($event['recur_exception']);
|
||||||
}
|
}
|
||||||
@ -1707,7 +1717,7 @@ ORDER BY cal_user_type, cal_usre_id
|
|||||||
// truncate recurrences by given exceptions
|
// truncate recurrences by given exceptions
|
||||||
if (count($event['recur_exception']))
|
if (count($event['recur_exception']))
|
||||||
{
|
{
|
||||||
// added and existing exceptions: delete the execeptions from the user table, it could be the first time
|
// added and existing exceptions: delete the exceptions from the user table, it could be the first time
|
||||||
$this->db->delete($this->user_table,array('cal_id' => $cal_id,'cal_recur_date' => $event['recur_exception']),__LINE__,__FILE__,'calendar');
|
$this->db->delete($this->user_table,array('cal_id' => $cal_id,'cal_recur_date' => $event['recur_exception']),__LINE__,__FILE__,'calendar');
|
||||||
// update recur_exception flag based on current exceptions
|
// update recur_exception flag based on current exceptions
|
||||||
$this->db->update($this->dates_table, 'recur_exception='.$this->db->expression($this->dates_table,array(
|
$this->db->update($this->dates_table, 'recur_exception='.$this->db->expression($this->dates_table,array(
|
||||||
|
@ -113,6 +113,11 @@ class calendar_timezones
|
|||||||
self::$tz_cache[$id] = Api\Db::strip_array_keys($data,'tz_');
|
self::$tz_cache[$id] = Api\Db::strip_array_keys($data,'tz_');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// check for a Windows timezone without "Standard Time" postfix
|
||||||
|
if (!isset($id) && strpos($tzid, '/') === false)
|
||||||
|
{
|
||||||
|
$id = self::tz2id($tzid.' Standard Time');
|
||||||
|
}
|
||||||
if (isset($id) && $what != 'id')
|
if (isset($id) && $what != 'id')
|
||||||
{
|
{
|
||||||
return self::id2tz($id,$what);
|
return self::id2tz($id,$what);
|
||||||
|
Loading…
Reference in New Issue
Block a user