RRULE expansion now working correctly.

This commit is contained in:
Andrew McMillan 2010-03-13 00:01:57 +13:00
parent aaebf97bee
commit 5ee5c1ff4a
3 changed files with 67 additions and 27 deletions

View File

@ -73,6 +73,7 @@ class RepeatRuleDateTime extends DateTime {
else {
$tzid = $dtz->getName();
}
parent::__construct($date, $dtz);
return $this;
@ -146,6 +147,9 @@ class RepeatRuleDateTime extends DateTime {
return parent::format('s');
}
function epoch() {
return parent::format('U');
}
}

View File

@ -1,28 +1,54 @@
<?php
require_once('PgQuery.php');
/**
* @todo Tidy up namespace handling in the responses.
*/
$responses = array();
$need_expansion = false;
function check_for_expansion( $calendar_data_node ) {
global $need_expansion, $expand_range_start, $expand_range_end;
if ( !class_exists('DateTime') ) return; /** We don't support expansion on PHP5.1 */
$expansion = $calendar_data_node->GetElements('urn:ietf:params:xml:ns:caldav:expand');
if ( isset($expansion[0]) ) {
$need_expansion = true;
$expand_range_start = $expansion[0]->GetAttribute('start');
$expand_range_end = $expansion[0]->GetAttribute('end');
if ( isset($expand_range_start) ) $expand_range_start = new RepeatRuleDateTime($expand_range_start);
if ( isset($expand_range_end) ) $expand_range_end = new RepeatRuleDateTime($expand_range_end);
}
}
/**
* Build the array of properties to include in the report output
*/
$mg_content = $xmltree->GetContent('urn:ietf:params:xml:ns:caldav:calendar-multiget');
$proptype = $mg_content[0]->GetTag();
$qry_content = $xmltree->GetContent('urn:ietf:params:xml:ns:caldav:calendar-multiget');
$proptype = $qry_content[0]->GetTag();
$properties = array();
switch( $proptype ) {
case 'DAV::prop':
$mg_props = $xmltree->GetPath('/urn:ietf:params:xml:ns:caldav:calendar-multiget/DAV::prop/*');
foreach( $mg_props AS $k => $v ) {
$qry_props = $xmltree->GetPath('/urn:ietf:params:xml:ns:caldav:calendar-multiget/'.$proptype.'/*');
foreach( $qry_content[0]->GetElements() AS $k => $v ) {
$propertyname = preg_replace( '/^.*:/', '', $v->GetTag() );
$properties[$propertyname] = 1;
if ( $v->GetTag() == 'urn:ietf:params:xml:ns:caldav:calendar-data' ) check_for_expansion($v);
}
break;
case 'DAV::allprop':
$properties['allprop'] = 1;
if ( $qry_content[1]->GetTag() == 'DAV::include' ) {
foreach( $qry_content[1]->GetElements() AS $k => $v ) {
$include_properties[] = $v->GetTag(); /** $include_properties is referenced in DAVResource where allprop is expanded */
if ( $v->GetTag() == 'urn:ietf:params:xml:ns:caldav:calendar-data' ) check_for_expansion($v);
}
}
break;
default:
@ -60,6 +86,11 @@ if ( isset($c->strict_result_ordering) && $c->strict_result_ordering ) $where .=
$qry = new PgQuery( "SELECT caldav_data.*,calendar_item.* FROM caldav_data INNER JOIN calendar_item USING(dav_id, user_no, dav_name, collection_id) LEFT JOIN collection USING(collection_id)". $where );
if ( $qry->Exec('REPORT',__LINE__,__FILE__) && $qry->rows > 0 ) {
while( $calendar_object = $qry->Fetch() ) {
if ( $need_expansion ) {
$ics = new iCalComponent($calendar_object->caldav_data);
$expanded = expand_event_instances($ics, $expand_range_start, $expand_range_end);
$calendar_object->caldav_data = $expanded->Render();
}
$responses[] = calendar_to_xml( $properties, $calendar_object );
}
}

View File

@ -139,8 +139,8 @@ if ( class_exists('RepeatRule') ) {
function expand_event_instances( $ics, $range_start = null, $range_end = null ) {
$components = $ics->GetComponents();
if ( !isset($range_start) ) { $range_start = new RepeatRuleDateTime($range_start); $range_start->modify('-6 weeks'); }
if ( !isset($range_end) ) { $range_end = new RepeatRuleDateTime($range_end); $range_end->modify('+4 months'); }
if ( !isset($range_start) ) { $range_start = new RepeatRuleDateTime(); $range_start->modify('-6 weeks'); }
if ( !isset($range_end) ) { $range_end = clone($range_start); $range_end->modify('+6 months'); }
$new_components = array();
$result_limit = 1000;
@ -153,13 +153,16 @@ if ( class_exists('RepeatRule') ) {
continue;
}
if ( !isset($dtstart) ) {
$dtstart = new RepeatRuleDateTime( $comp->GetPValue('DTSTART'), $comp->GetPParamValue('DTSTART', 'TZID') );
$tzid = $comp->GetPParamValue('DTSTART', 'TZID');
print( $tzid . "\n");
$dtstart = new RepeatRuleDateTime( $comp->GetPValue('DTSTART'), $tzid );
$instances[$dtstart->UTC()] = $comp;
}
$p = $comp->GetPValue('RECURRENCE-ID');
if ( isset($p) && $p != '' ) {
$range = $comp->GetPParamValue('RECURRENCE-ID', 'RANGE');
$recur_tzid = $comp->GetPParamValue('RECURRENCE-ID', 'TZID');
print( __LINE__ . ' - ' .$recur_tzid . "\n");
$recur_utc = new RepeatRuleDateTime($p,$recur_tzid);
$recur_utc = $recur_utc->UTC();
if ( isset($range) && $range == 'THISANDFUTURE' ) {
@ -185,31 +188,33 @@ if ( class_exists('RepeatRule') ) {
$start_utc = $range_start->UTC();
$end_utc = $range_end->UTC();
foreach( $instances AS $utc => $comp ) {
if ( $utc > $end_utc ) break;
$duration = $comp->GetPValue('DURATION');
if ( !isset($duration) ) {
$dtend = new RepeatRuleDateTime( $comp->GetPValue('DTEND'), $comp->GetPParamValue('DTEND', 'TZID'));
$dtsrt = new RepeatRuleDateTime( $comp->GetPValue('DTSTART'), $comp->GetPParamValue('DTSTART', 'TZID'));
$duration = sprintf( 'PT%dM', intval(($dtend->epoch() - $dtsrt->epoch()) / 60) );
}
if ( $utc < $start_utc ) {
$duration = $comp->GetPValue('DURATION');
if ( !isset($duration) ) {
$dtend = new RepeatRuleDateTime( $comp->GetPValue('DTEND'), $comp->GetPValue('DTEND', 'TZID'));
$dtsrt = new RepeatRuleDateTime( $comp->GetPValue('DTSTART'), $comp->GetPValue('DTSTART', 'TZID'));
$duration = sprintf( '%d minutes', (($dtend->epoch() - $dtsrt->epoch()) / 60) );
}
if ( isset($duration) ) {
if ( isset($last_duration) && $duration == $last_duration) {
if ( $utc < $early_start ) continue;
}
else {
$latest_start = clone($range_start);
$latest_start->modify('-'.$duration);
$early_start = $latest_start->UTC();
$last_duration = $duration;
if ( $utc < $early_start ) continue;
}
if ( isset($last_duration) && $duration == $last_duration) {
if ( $utc < $early_start ) continue;
}
else {
$latest_start = clone($range_start);
$latest_start->modify('-'.$duration);
$early_start = $latest_start->UTC();
$last_duration = $duration;
if ( $utc < $early_start ) continue;
}
continue;
}
if ( $utc > $end_utc ) break;
$new_components[] = $comp;
$component = clone($comp);
$component->ClearProperties('DTSTART');
$component->ClearProperties('DTEND');
$component->AddProperty('DTSTART', $utc );
$component->AddProperty('DURATION', $duration );
$new_components[] = $component;
$in_range = true;
}