Fix VTIMEZONE RRULE issue and be more compliant with standard

This commit is contained in:
Jörg Lehrke 2009-10-19 20:46:23 +00:00
parent 763b58912a
commit a11565ec9c

View File

@ -270,7 +270,7 @@ class calendar_ical extends calendar_boupdate
if (!$serverTZ && $servertime) if (!$serverTZ && $servertime)
{ {
$serverTZ = $this->generate_vtimezone($event['start'], $vcal); $serverTZ = $this->generate_vtimezone($event, $vcal);
} }
if ($this->productManufacturer == 'sonyericsson') if ($this->productManufacturer == 'sonyericsson')
@ -421,9 +421,9 @@ class calendar_ical extends calendar_boupdate
{ {
$rrule['UNTIL'] = '#0'; $rrule['UNTIL'] = '#0';
} }
}
$attributes['RRULE'] = $rrule['FREQ'].' '.$rrule['UNTIL']; else
} else { {
$rrule = array('FREQ' => $this->recur_egw2ical_2_0[$event['recur_type']]); $rrule = array('FREQ' => $this->recur_egw2ical_2_0[$event['recur_type']]);
switch ($event['recur_type']) switch ($event['recur_type'])
{ {
@ -463,15 +463,9 @@ class calendar_ical extends calendar_boupdate
$rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate); $rrule['UNTIL'] = $vcal->_exportDateTime($recur_enddate);
} }
} }
// no idea how to get the Horde parser to produce a standard conformant
// RRULE:FREQ=... (note the double colon after RRULE, we cant use the $parameter array)
// so we create one value manual ;-)
foreach($rrule as $name => $value)
{
$attributes['RRULE'][] = $name . '=' . $value;
}
$attributes['RRULE'] = implode(';',$attributes['RRULE']);
} }
$attributes['RRULE'] = '';
$parameters['RRULE'] = $rrule;
break; break;
case 'EXDATE': case 'EXDATE':
@ -2267,13 +2261,12 @@ class calendar_ical extends calendar_boupdate
/** /**
* generate and insert a VTIMEZONE entry to a vcalendar * generate and insert a VTIMEZONE entry to a vcalendar
* *
* @param int $ts timestamp to evaluate the local timezone and year * @param array $event
* @param array $vevent VEVENT representation of the event * @param array $vcal VCALENDAR entry
* @return string local timezone name (e.g. 'CET/CEST') * @return string local timezone name (e.g. 'CET/CEST')
*/ */
function generate_vtimezone($ts, &$vcal) function generate_vtimezone($event, &$vcal)
{ {
$utc = array('UTC',null,0,0,"",0,0,0,0,0,0,0,0,0,0);
$dayofweek = array('SU','MO','TU','WE','TH','FR','SA'); $dayofweek = array('SU','MO','TU','WE','TH','FR','SA');
$tbl_tz = array( $tbl_tz = array(
array("Afghanistan","Asia/Kabul",270,0,"",0,0,0,0,0,0,0,0,0,0), array("Afghanistan","Asia/Kabul",270,0,"",0,0,0,0,0,0,0,0,0,0),
@ -2313,6 +2306,7 @@ class calendar_ical extends calendar_boupdate
array("Central_Brazilian","America/Manaus",-240,60,"2006",11,0,1,0,0,2,0,2,2,0), array("Central_Brazilian","America/Manaus",-240,60,"2006",11,0,1,0,0,2,0,2,2,0),
array("Central_Brazilian","America/Manaus",-240,60,"2007",11,0,1,0,0,2,0,5,0,0), array("Central_Brazilian","America/Manaus",-240,60,"2007",11,0,1,0,0,2,0,5,0,0),
array("CET/CEST","Europe/Zurich",60,60,"",3,0,5,2,0,10,0,5,3,0), array("CET/CEST","Europe/Zurich",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("CET/CEST","Europe/Vienna",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("MEZ/MESZ","Europe/Berlin",60,60,"",3,0,5,2,0,10,0,5,3,0), array("MEZ/MESZ","Europe/Berlin",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Central_Europe","Europe/Budapest",60,60,"",3,0,5,2,0,10,0,5,3,0), array("Central_Europe","Europe/Budapest",60,60,"",3,0,5,2,0,10,0,5,3,0),
array("Central_European","Europe/Warsaw",60,60,"",3,0,5,2,0,10,0,5,3,0), array("Central_European","Europe/Warsaw",60,60,"",3,0,5,2,0,10,0,5,3,0),
@ -2456,72 +2450,112 @@ class calendar_ical extends calendar_boupdate
array("Yakutsk","Asia/Yakutsk",540,60,"",3,0,5,2,0,10,0,5,3,0), array("Yakutsk","Asia/Yakutsk",540,60,"",3,0,5,2,0,10,0,5,3,0),
); );
$serverTZ = date('e', $ts); $serverTZ = date('e', $event['start']);
$year = date('Y', $ts); $year = date('Y', $event['start']);
$i = 0; $i = 0;
$row =& $utc; $row = false;
do do
{ {
$tbl_tz_row =& $tbl_tz[$i]; $tbl_tz_row =& $tbl_tz[$i];
if ($row[0] != 'UTC' && $row[0] != $tbl_tz_row[0]) break; if ($tbl_tz_row[1] == $serverTZ)
if ($tbl_tz_row[1] == $serverTZ
&& ($tbl_tz_row[4] != "" || $year >= (int) $tbl_tz_row[4]))
{ {
$row =& $tbl_tz[$i]; if ($tbl_tz_row[4] == '' || $year >= (int) $tbl_tz_row[4])
{
$row = $i;
} }
$i++; else if ($row !== false) break;
else if ($tbl_tz_row[4] != '' && $year < (int) $tbl_tz_row[4])
{
// First DST starts at this year
$year = (int) $tbl_tz_row[4];
if (empty($event['recur_enddate'])
|| $year <= date('Y', $event['recur_enddate']))
{
$row = $i;
} }
while (is_array($tbl_tz[$i])); break;
if (preg_match('/(.+)\/(.+)/', $row[0], $matches)) }
}
else if ($row !== false) break;
}
while (is_array($tbl_tz[++$i]));
if ($row === false) return $serverTZ; // UTC or unkown TZ
$tbl_tz_row =& $tbl_tz[$row];
if (preg_match('/(.+)\/(.+)/', $tbl_tz_row[0], $matches))
{ {
$stdname = $matches[1]; $stdname = $matches[1];
$dstname = $matches[2]; $dstname = $matches[2];
} }
else else
{ {
$stdname = $dstname = $row[0]; $stdname = $dstname = $tbl_tz_row[0];
} }
if($row[1]) // UTC does not need a VTIMEZONE component
{
$container = false; $container = false;
$vtimezone = Horde_iCalendar::newComponent('VTIMEZONE', $container); $vtimezone = Horde_iCalendar::newComponent('VTIMEZONE', $container);
$vtimezone->setAttribute('TZID', $row[1]); $vtimezone->setAttribute('TZID', $tbl_tz_row[1]);
$minutes = $row[2] + $row[3]; do {
$value1['ahead'] = ($minutes > 0); if (is_array($tbl_tz[++$row]))
{
$tbl_next_row =& $tbl_tz[$row];
if ($tbl_next_row[1] != $serverTZ) $tbl_next_row = false;
}
else $tbl_next_row = false;
$minutes = $tbl_tz_row[2] + $tbl_tz_row[3];
$value1['ahead'] = ($minutes >= 0);
$minutes = abs($minutes); $minutes = abs($minutes);
$value1['hour'] = (int)$minutes / 60; $value1['hour'] = (int)$minutes / 60;
$value1['minute'] = $minutes % 60; $value1['minute'] = $minutes % 60;
$minutes = $row[2]; $minutes = $tbl_tz_row[2];
$value2['ahead'] = ($minutes > 0); $value2['ahead'] = ($minutes > 0);
$minutes = abs($minutes); $minutes = abs($minutes);
$value2['hour'] = (int)$minutes / 60; $value2['hour'] = (int)$minutes / 60;
$value2['minute'] = $minutes % 60; $value2['minute'] = $minutes % 60;
$daylight = Horde_iCalendar::newComponent('DAYLIGHT', $container); $daylight = Horde_iCalendar::newComponent('DAYLIGHT', $container);
$dtstart = $this->calc_dtstart($row[4], $row[5], $row[6], $row[7], $row[8], $row[9]); $dtstart = $this->calc_dtstart($year, $tbl_tz_row[5],
$tbl_tz_row[6], $tbl_tz_row[7], $tbl_tz_row[8], $tbl_tz_row[9]);
$daylight->setAttribute('DTSTART', $dtstart); $daylight->setAttribute('DTSTART', $dtstart);
$byday = ($row[7] == 5 ? '-1' : $row[7]) . $dayofweek[$row[6]]; $byday = ($tbl_tz_row[7] == 5 ? '-1' : $tbl_tz_row[7]) . $dayofweek[$tbl_tz_row[6]];
$daylight->setAttribute('RRULE', '', array('FREQ' => 'YEARLY', 'BYMONTH' => $row[5], 'BYDAY' => $byday)); $rrule = array('FREQ' => 'YEARLY', 'BYMONTH' => $tbl_tz_row[5], 'BYDAY' => $byday);
if ($tbl_next_row)
{
$rrule['UNTIL'] = $tbl_next_row[4] . '0101T000000Z';
}
$daylight->setAttribute('RRULE', '', $rrule);
$daylight->setAttribute('TZNAME', $dstname); $daylight->setAttribute('TZNAME', $dstname);
$daylight->setAttribute('TZOFFSETFROM', $value2); $daylight->setAttribute('TZOFFSETFROM', $value2);
$daylight->setAttribute('TZOFFSETTO', $value1); $daylight->setAttribute('TZOFFSETTO', $value1);
$standard = Horde_iCalendar::newComponent('STANDARD', $container); $standard = Horde_iCalendar::newComponent('STANDARD', $container);
$dtstart = $this->calc_dtstart($year, $row[10], $row[11], $row[12], $row[13], $row[14]); $dtstart = $this->calc_dtstart($year, $tbl_tz_row[10], $tbl_tz_row[11],
$tbl_tz_row[12], $tbl_tz_row[13], $tbl_tz_row[14]);
$standard->setAttribute('DTSTART', $dtstart); $standard->setAttribute('DTSTART', $dtstart);
$byday = ($row[12] == 5 ? '-1' : $row[12]) . $dayofweek[$row[11]]; $byday = ($tbl_tz_row[12] == 5 ? '-1' : $tbl_tz_row[12]) . $dayofweek[$tbl_tz_row[11]];
$standard->setAttribute('RRULE', '', array('FREQ' => 'YEARLY', 'BYMONTH' => $row[10], 'BYDAY' => $byday)); $rrule['BYMONTH'] = $tbl_tz_row[10];
$rrule['BYDAY'] = $byday;
$standard->setAttribute('RRULE', '', $rrule);
$standard->setAttribute('TZNAME', $stdname); $standard->setAttribute('TZNAME', $stdname);
$standard->setAttribute('TZOFFSETFROM', $value1); $standard->setAttribute('TZOFFSETFROM', $value1);
$standard->setAttribute('TZOFFSETTO', $value2); $standard->setAttribute('TZOFFSETTO', $value2);
$vtimezone->addComponent($daylight); $vtimezone->addComponent($daylight);
$vtimezone->addComponent($standard); $vtimezone->addComponent($standard);
$vcal->addComponent($vtimezone); if ($tbl_next_row)
{
$tbl_tz_row = $tbl_next_row;
$year = (int) $tbl_tz_row[4];
} }
} while ($tbl_next_row && (empty($event['recur_enddate']) ||
$year <= date('Y', $event['recur_enddate'])));
return $row[1]; $vcal->addComponent($vtimezone);
return $serverTZ;
} }
/** /**