forked from extern/egroupware
Use new rrule iterator class for RRULE generation
This commit is contained in:
parent
47b2216554
commit
db25947a38
@ -24,16 +24,6 @@ class calendar_ical extends calendar_boupdate
|
||||
*/
|
||||
var $supportedFields;
|
||||
|
||||
var $recur_days_1_0 = array(
|
||||
MCAL_M_MONDAY => 'MO',
|
||||
MCAL_M_TUESDAY => 'TU',
|
||||
MCAL_M_WEDNESDAY => 'WE',
|
||||
MCAL_M_THURSDAY => 'TH',
|
||||
MCAL_M_FRIDAY => 'FR',
|
||||
MCAL_M_SATURDAY => 'SA',
|
||||
MCAL_M_SUNDAY => 'SU',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $status_egw2ical conversation of the participant status egw => ical
|
||||
*/
|
||||
@ -74,28 +64,6 @@ class calendar_ical extends calendar_boupdate
|
||||
4 => 3, 3 => 3, 2 => 3, 1 => 3, // high
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $recur_egw2ical_2_0 converstaion of egw recur-type => ical FREQ
|
||||
*/
|
||||
var $recur_egw2ical_2_0 = array(
|
||||
MCAL_RECUR_DAILY => 'DAILY',
|
||||
MCAL_RECUR_WEEKLY => 'WEEKLY',
|
||||
MCAL_RECUR_MONTHLY_MDAY => 'MONTHLY', // BYMONHTDAY={1..31}
|
||||
MCAL_RECUR_MONTHLY_WDAY => 'MONTHLY', // BYDAY={1..5}{MO..SO}
|
||||
MCAL_RECUR_YEARLY => 'YEARLY',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $recur_egw2ical_1_0 converstaion of egw recur-type => ical FREQ
|
||||
*/
|
||||
var $recur_egw2ical_1_0 = array(
|
||||
MCAL_RECUR_DAILY => 'D',
|
||||
MCAL_RECUR_WEEKLY => 'W',
|
||||
MCAL_RECUR_MONTHLY_MDAY => 'MD', // BYMONHTDAY={1..31}
|
||||
MCAL_RECUR_MONTHLY_WDAY => 'MP', // BYDAY={1..5}{MO..SO}
|
||||
MCAL_RECUR_YEARLY => 'YM',
|
||||
);
|
||||
|
||||
/**
|
||||
* manufacturer and name of the sync-client
|
||||
*
|
||||
@ -390,74 +358,14 @@ class calendar_ical extends calendar_boupdate
|
||||
|
||||
case 'RRULE':
|
||||
if ($event['recur_type'] == MCAL_RECUR_NONE) break; // no recuring event
|
||||
$rriter = calendar_rrule::event2rrule($event,true); // true = we operate in usertime, like the rest of calendar_bo
|
||||
$rrule = $rriter->generate_rrule($version);
|
||||
if ($version == '1.0')
|
||||
{
|
||||
$interval = ($event['recur_interval'] > 1) ? $event['recur_interval'] : 1;
|
||||
$rrule = array('FREQ' => $this->recur_egw2ical_1_0[$event['recur_type']].$interval);
|
||||
switch ($event['recur_type'])
|
||||
{
|
||||
case MCAL_RECUR_WEEKLY:
|
||||
$days = array();
|
||||
foreach ($this->recur_days_1_0 as $id => $day)
|
||||
{
|
||||
if ($event['recur_data'] & $id) $days[] = strtoupper(substr($day,0,2));
|
||||
}
|
||||
$rrule['BYDAY'] = implode(' ',$days);
|
||||
$rrule['FREQ'] = $rrule['FREQ'].' '.$rrule['BYDAY'];
|
||||
break;
|
||||
|
||||
case MCAL_RECUR_MONTHLY_MDAY: // date of the month: BYMONTDAY={1..31}
|
||||
break;
|
||||
|
||||
case MCAL_RECUR_MONTHLY_WDAY: // weekday of the month: BDAY={1..5}{MO..SO}
|
||||
$rrule['BYDAY'] = (1 + (int) ((date('d',$event['start'])-1) / 7)).'+ '.
|
||||
strtoupper(substr(date('l',$event['start']),0,2));
|
||||
$rrule['FREQ'] = $rrule['FREQ'].' '.$rrule['BYDAY'];
|
||||
break;
|
||||
}
|
||||
|
||||
if ($event['recur_enddate'])
|
||||
{
|
||||
$rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate);
|
||||
}
|
||||
else
|
||||
{
|
||||
$rrule['UNTIL'] = '#0';
|
||||
}
|
||||
$attributes['RRULE'] = $rrule['FREQ'].' '.$rrule['UNTIL'];
|
||||
}
|
||||
else // $version == '2.0'
|
||||
{
|
||||
$rrule = array('FREQ' => $this->recur_egw2ical_2_0[$event['recur_type']]);
|
||||
switch ($event['recur_type'])
|
||||
{
|
||||
case MCAL_RECUR_WEEKLY:
|
||||
$days = array();
|
||||
foreach ($this->recur_days as $id => $day)
|
||||
{
|
||||
if ($event['recur_data'] & $id) $days[] = strtoupper(substr($day,0,2));
|
||||
}
|
||||
$rrule['BYDAY'] = implode(',',$days);
|
||||
break;
|
||||
|
||||
case MCAL_RECUR_MONTHLY_MDAY: // date of the month: BYMONTDAY={1..31}
|
||||
$rrule['BYMONTHDAY'] = (int) date('d',$event['start']);
|
||||
break;
|
||||
|
||||
case MCAL_RECUR_MONTHLY_WDAY: // weekday of the month: BDAY={1..5}{MO..SO}
|
||||
$rrule['BYDAY'] = (1 + (int) ((date('d',$event['start'])-1) / 7)).
|
||||
strtoupper(substr(date('l',$event['start']),0,2));
|
||||
break;
|
||||
}
|
||||
if ($event['recur_interval'] > 1)
|
||||
{
|
||||
$rrule['INTERVAL'] = $event['recur_interval'];
|
||||
}
|
||||
if ($event['recur_enddate'])
|
||||
{
|
||||
// UNTIL should be a UTC timestamp
|
||||
$rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate);
|
||||
}
|
||||
$attributes['RRULE'] = '';
|
||||
$parameters['RRULE'] = $rrule;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* eGroupWare - Calendar recurance rules
|
||||
* eGroupWare - Calendar recurrence rules
|
||||
*
|
||||
* @link http://www.egroupware.org
|
||||
* @package calendar
|
||||
@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Recurance rule iterator
|
||||
* Recurrence rule iterator
|
||||
*
|
||||
* The constructor accepts times only as DateTime (or decendents like egw_date) to work timezone-correct.
|
||||
* The timezone of the event is determined by timezone of the startime, other times get converted to that timezone.
|
||||
@ -23,7 +23,7 @@
|
||||
*
|
||||
* There's an interactive test-form, if the class get's called directly: http://localhost/egroupware/calendar/inc/class.calendar_rrule.inc.php
|
||||
*
|
||||
* @todo Integrate iCal import and export, so all recurence code resides just in this class
|
||||
* @todo Integrate iCal import and export, so all recurrence code resides just in this class
|
||||
* @todo Implement COUNT, can be stored in enddate assuming counts are far smaller then timestamps (eg. < 1000 is a count)
|
||||
* @todo Implement WKST (week start day), currently WKST=SU is used (this is not stored in current DB schema, it's a user preference)
|
||||
*/
|
||||
@ -67,6 +67,28 @@ class calendar_rrule implements Iterator
|
||||
self::YEARLY => 'Yearly'
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $recur_egw2ical_2_0 converstaion of egw recur-type => ical FREQ
|
||||
*/
|
||||
static private $recur_egw2ical_2_0 = array(
|
||||
self::DAILY => 'DAILY',
|
||||
self::WEEKLY => 'WEEKLY',
|
||||
self::MONTHLY_WDAY => 'MONTHLY', // BYDAY={1..7, -1}{MO..SO, last workday}
|
||||
self::MONTHLY_MDAY => 'MONTHLY', // BYMONHTDAY={1..31, -1 for last day of month}
|
||||
self::YEARLY => 'YEARLY',
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array $recur_egw2ical_1_0 converstaion of egw recur-type => ical FREQ
|
||||
*/
|
||||
static private $recur_egw2ical_1_0 = array(
|
||||
self::DAILY => 'D',
|
||||
self::WEEKLY => 'W',
|
||||
self::MONTHLY_WDAY => 'MP', // BYDAY={1..7,-1}{MO..SO, last workday}
|
||||
self::MONTHLY_MDAY => 'MD', // BYMONHTDAY={1..31,-1}
|
||||
self::YEARLY => 'YM',
|
||||
);
|
||||
|
||||
/**
|
||||
* RRule type: NONE, DAILY, WEEKLY, MONTHLY_MDAY, MONTHLY_WDAY, YEARLY
|
||||
*
|
||||
@ -82,7 +104,7 @@ class calendar_rrule implements Iterator
|
||||
public $interval = 1;
|
||||
|
||||
/**
|
||||
* Number for monthly byday: 1, ..., 5, -1=last weekday of month
|
||||
* Number for monthly byday: 1, ..., 5, -1=last workday of month
|
||||
*
|
||||
* EGroupware Calendar does NOT explicitly store it, it's only implicitly defined by series start date
|
||||
*
|
||||
@ -163,6 +185,14 @@ class calendar_rrule implements Iterator
|
||||
*/
|
||||
public $current;
|
||||
|
||||
/**
|
||||
* Last day of the week according to user preferences
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $lastdayofweek;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -178,6 +208,19 @@ class calendar_rrule implements Iterator
|
||||
*/
|
||||
public function __construct(DateTime $time,$type,$interval=1,DateTime $enddate=null,$weekdays=0,array $exceptions=null)
|
||||
{
|
||||
$weekdaystarts = $GLOBALS['egw_info']['user']['preferences']['calendar']['weekdaystarts'];
|
||||
switch($weekdaystarts)
|
||||
{
|
||||
case 'Sunday':
|
||||
$this->lastdayofweek = self::SATURDAY;
|
||||
break;
|
||||
case 'Saturday':
|
||||
$this->lastdayofweek = self::FRIDAY;
|
||||
break;
|
||||
default: // Monday
|
||||
$this->lastdayofweek = self::SUNDAY;
|
||||
}
|
||||
|
||||
$this->time = $time;
|
||||
|
||||
if (!in_array($type,array(self::NONE, self::DAILY, self::WEEKLY, self::MONTHLY_MDAY, self::MONTHLY_WDAY, self::YEARLY)))
|
||||
@ -306,8 +349,8 @@ class calendar_rrule implements Iterator
|
||||
do
|
||||
{
|
||||
// interval in weekly means event runs on valid days eg. each 2. week
|
||||
// --> on saturday we have to additionally advance interval-1 weeks
|
||||
if ($this->interval > 1 && self::getWeekday($this->current) == self::SATURDAY)
|
||||
// --> on the last day of the week we have to additionally advance interval-1 weeks
|
||||
if ($this->interval > 1 && self::getWeekday($this->current) == $this->lastdayofweek)
|
||||
{
|
||||
$this->current->modify(($this->interval-1).' week');
|
||||
}
|
||||
@ -466,6 +509,96 @@ class calendar_rrule implements Iterator
|
||||
return $str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a VEVENT RRULE
|
||||
* @param string $version='1.0' could be '2.0', too
|
||||
*/
|
||||
public function generate_rrule($version='1.0')
|
||||
{
|
||||
static $utc;
|
||||
$repeat_days = array();
|
||||
$rrule = array();
|
||||
|
||||
if (is_null($utc))
|
||||
{
|
||||
$utc = calendar_timezones::DateTimeZone('UTC');
|
||||
}
|
||||
|
||||
if ($this->type == self::NONE) return false; // no recuring event
|
||||
|
||||
if ($version == '1.0')
|
||||
{
|
||||
$rrule['FREQ'] = self::$recur_egw2ical_1_0[$this->type] . $this->interval;
|
||||
switch ($this->type)
|
||||
{
|
||||
case self::WEEKLY:
|
||||
foreach (self::$days as $mask => $label)
|
||||
{
|
||||
if ($this->weekdays & $mask)
|
||||
{
|
||||
$repeat_days[] = strtoupper(substr($label,0,2));
|
||||
}
|
||||
}
|
||||
$rrule['BYDAY'] = implode(' ', $repeat_days);
|
||||
$rrule['FREQ'] = $rrule['FREQ'].' '.$rrule['BYDAY'];
|
||||
break;
|
||||
|
||||
case self::MONTHLY_MDAY: // date of the month: BYMONTDAY={1..31}
|
||||
break;
|
||||
|
||||
case self::MONTHLY_WDAY: // weekday of the month: BDAY={1..5}{MO..SO}
|
||||
$rrule['BYDAY'] = $this->monthly_byday_num .
|
||||
strtoupper(substr($this->time->format('l'),0,2));
|
||||
$rrule['FREQ'] = $rrule['FREQ'].' '.$rrule['BYDAY'];
|
||||
break;
|
||||
}
|
||||
|
||||
if (!$this->enddate)
|
||||
{
|
||||
$rrule['UNTIL'] = '#0';
|
||||
}
|
||||
}
|
||||
else // $version == '2.0'
|
||||
{
|
||||
$rrule['FREQ'] = self::$recur_egw2ical_2_0[$this->type];
|
||||
switch ($this->type)
|
||||
{
|
||||
case self::WEEKLY:
|
||||
foreach (self::$days as $mask => $label)
|
||||
{
|
||||
if ($this->weekdays & $mask)
|
||||
{
|
||||
$repeat_days[] = strtoupper(substr($label,0,2));
|
||||
}
|
||||
}
|
||||
$rrule['BYDAY'] = implode(',', $repeat_days);
|
||||
break;
|
||||
|
||||
case self::MONTHLY_MDAY: // date of the month: BYMONTDAY={1..31}
|
||||
$rrule['BYMONTHDAY'] = $this->monthly_bymonthday;
|
||||
break;
|
||||
|
||||
case MCAL_RECUR_MONTHLY_WDAY: // weekday of the month: BDAY={1..5}{MO..SO}
|
||||
$rrule['BYDAY'] = $this->monthly_byday_num .
|
||||
strtoupper(substr($this->time->format('l'),0,2));
|
||||
break;
|
||||
}
|
||||
if ($this->interval > 1)
|
||||
{
|
||||
$rrule['INTERVAL'] = $this->interval;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->enddate)
|
||||
{
|
||||
$enddate = clone $this->enddate;
|
||||
$enddate->setTimezone($utc);
|
||||
$rrule['UNTIL'] = $enddate->format('Ymd\THis\Z');
|
||||
}
|
||||
|
||||
return $rrule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get instance for a given event array
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user