Add support for 'every last friday (in june)' recurrence rules

This commit is contained in:
Thomas 2011-06-30 22:49:20 +02:00
parent de45b996b4
commit 04f649c6fd

View file

@ -5233,6 +5233,20 @@ class Horde_Date_Recurrence {
*/
var $recurData = null;
/**
* BYDAY recurrence number
*
* @var integer
*/
var $recurNthDay = 0;
/**
* BYMONTH recurrence data
*
* @var array
*/
var $recurMonths = array();
/**
* All the exceptions from recurrence for this event.
*
@ -5292,6 +5306,44 @@ class Horde_Date_Recurrence {
return $this->recurData;
}
/**
* Specifies the months for yearly (weekday) recurrence
*
* @param array $months List of months (integers) this event recurs on.
*/
function setRecurByMonth($months)
{
$this->recurMonths = $months;
}
/**
* Returns a list of months this yearly event recurs on
*
* @return array List of months (integers) this event recurs on.
*/
function getRecurByMonth()
{
return $this->recurMonths;
}
/**
*
* @param integer $nthDay The nth weekday of month to repeat events on
*/
function setRecurNthWeekday($nthDay)
{
$this->recurNthDay = $nthDay;
}
/**
*
* @return integer The nth weekday of month to repeat events.
*/
function getRecurNthWeekday()
{
return $this->recurNthDay;
}
/**
* Returns whether this event has a specific recurrence type.
*
@ -5657,8 +5709,13 @@ class Horde_Date_Recurrence {
$estart = new Horde_Date($this->start);
// What day of the week, and week of the month, do we recur on?
if ($this->recurNthDay != 0) {
$nth = $this->recurNthDay < 0 ? 'last' : $this->recurNthDay;
$weekday = log($this->recurData, 2);
} else {
$nth = ceil($this->start->mday / 7);
$weekday = $estart->dayOfWeek();
}
// Adjust $estart to be the first candidate.
$offset = ($after->month - $estart->month) + ($after->year - $estart->year) * 12;
@ -5678,7 +5735,11 @@ class Horde_Date_Recurrence {
$estart->correct();
$next = new Horde_Date($estart);
if ($this->recurNthDay) {
list($next->mday, $next->month, $next->year) = explode('/', Date_Calc::nWeekdayOfMonth($nth, $weekday, $estart->month, $estart->year, '%e/%m/%Y'));
} else {
$next->setNthWeekday($weekday, $nth);
}
if ($next->compareDateTime($after) < 0) {
// We haven't made it past $after yet, try again.
@ -5773,8 +5834,18 @@ class Horde_Date_Recurrence {
$estart = new Horde_Date($this->start);
// What day of the week, and week of the month, do we recur on?
if ($this->recurNthDay != 0) {
$nth = $this->recurNthDay < 0 ? 'last' : $this->recurNthDay;
$weekday = log($this->recurData, 2);
} else {
$nth = ceil($this->start->mday / 7);
$weekday = $estart->dayOfWeek();
}
// set month from recurrence rule (FEXME: support more than one month)
if ($this->recurMonths) {
$estart->month = $this->recurMonths[0];
}
// Adjust $estart to be the first candidate.
$offset = floor(($after->year - $estart->year + $this->recurInterval - 1) / $this->recurInterval) * $this->recurInterval;
@ -5793,7 +5864,11 @@ class Horde_Date_Recurrence {
$estart->correct();
$next = new Horde_Date($estart);
if ($this->recurNthDay) {
list($next->mday, $next->month, $next->year) = explode('/', Date_Calc::nWeekdayOfMonth($nth, $weekday, $estart->month, $estart->year, '%e/%m/%Y'));
} else {
$next->setNthWeekday($weekday, $nth);
}
if ($next->compareDateTime($after) < 0) {
// We haven't made it past $after yet, try again.
@ -6159,6 +6234,14 @@ class Horde_Date_Recurrence {
// Always default the recurInterval to 1.
$this->setRecurInterval(isset($rdata['INTERVAL']) ? $rdata['INTERVAL'] : 1);
$maskdays = array('SU' => HORDE_DATE_MASK_SUNDAY,
'MO' => HORDE_DATE_MASK_MONDAY,
'TU' => HORDE_DATE_MASK_TUESDAY,
'WE' => HORDE_DATE_MASK_WEDNESDAY,
'TH' => HORDE_DATE_MASK_THURSDAY,
'FR' => HORDE_DATE_MASK_FRIDAY,
'SA' => HORDE_DATE_MASK_SATURDAY);
switch (strtoupper($rdata['FREQ'])) {
case 'DAILY':
$this->setRecurType(HORDE_DATE_RECUR_DAILY);
@ -6167,13 +6250,6 @@ class Horde_Date_Recurrence {
case 'WEEKLY':
$this->setRecurType(HORDE_DATE_RECUR_WEEKLY);
if (isset($rdata['BYDAY'])) {
$maskdays = array('SU' => HORDE_DATE_MASK_SUNDAY,
'MO' => HORDE_DATE_MASK_MONDAY,
'TU' => HORDE_DATE_MASK_TUESDAY,
'WE' => HORDE_DATE_MASK_WEDNESDAY,
'TH' => HORDE_DATE_MASK_THURSDAY,
'FR' => HORDE_DATE_MASK_FRIDAY,
'SA' => HORDE_DATE_MASK_SATURDAY);
$days = explode(',', $rdata['BYDAY']);
$mask = 0;
foreach ($days as $day) {
@ -6198,6 +6274,10 @@ class Horde_Date_Recurrence {
case 'MONTHLY':
if (isset($rdata['BYDAY'])) {
$this->setRecurType(HORDE_DATE_RECUR_MONTHLY_WEEKDAY);
if (preg_match('/(-?[1-4])([A-Z]+)/', $rdata['BYDAY'], $m)) {
$this->setRecurOnDay($maskdays[$m[2]]);
$this->setRecurNthWeekday($m[1]);
}
} else {
$this->setRecurType(HORDE_DATE_RECUR_MONTHLY_DATE);
}
@ -6208,6 +6288,14 @@ class Horde_Date_Recurrence {
$this->setRecurType(HORDE_DATE_RECUR_YEARLY_DAY);
} elseif (isset($rdata['BYDAY'])) {
$this->setRecurType(HORDE_DATE_RECUR_YEARLY_WEEKDAY);
if (preg_match('/(-?[1-4])([A-Z]+)/', $rdata['BYDAY'], $m)) {
$this->setRecurOnDay($maskdays[$m[2]]);
$this->setRecurNthWeekday($m[1]);
}
if ($rdata['BYMONTH']) {
$months = explode(',', $rdata['BYMONTH']);
$this->setRecurByMonth($months);
}
} else {
$this->setRecurType(HORDE_DATE_RECUR_YEARLY_DATE);
}
@ -6271,13 +6359,19 @@ class Horde_Date_Recurrence {
break;
case HORDE_DATE_RECUR_MONTHLY_WEEKDAY:
if ($this->recurNthDay != 0) {
$nth_weekday = $this->recurNthDay;
$day_of_week = log($this->recurData, 2);
} else {
$day_of_week = $this->start->dayOfWeek();
$nth_weekday = (int)($this->start->mday / 7);
if (($this->start->mday % 7) > 0) {
$nth_weekday++;
}
}
$vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
$rrule = 'FREQ=MONTHLY;INTERVAL=' . $this->recurInterval
. ';BYDAY=' . $nth_weekday . $vcaldays[$this->start->dayOfWeek()];
. ';BYDAY=' . $nth_weekday . $vcaldays[$day_of_week];
break;
case HORDE_DATE_RECUR_YEARLY_DATE:
@ -6290,16 +6384,23 @@ class Horde_Date_Recurrence {
break;
case HORDE_DATE_RECUR_YEARLY_WEEKDAY:
if ($this->recurNthDay != 0) {
$nth_weekday = $this->recurNthDay;
$day_of_week = log($this->recurData, 2);
} else {
$day_of_week = $this->start->dayOfWeek();
$nth_weekday = (int)($this->start->mday / 7);
if (($this->start->mday % 7) > 0) {
$nth_weekday++;
}
}
$months = !empty($this->recurMonths) ? join(',', $this->recurMonths) : $this->start->month;
$vcaldays = array('SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA');
$rrule = 'FREQ=YEARLY;INTERVAL=' . $this->recurInterval
. ';BYDAY='
. $nth_weekday
. $vcaldays[$this->start->dayOfWeek()]
. ';BYMONTH=' . $this->start->month;
. $vcaldays[$day_of_week]
. ';BYMONTH=' . $months;
break;
}