implement EXDATE exclusions

master
Tanguy Pruvot 2010-10-30 22:44:07 +02:00
rodzic 642115b1cc
commit 5743c6221e
4 zmienionych plików z 47 dodań i 27 usunięć

Wyświetl plik

@ -26,6 +26,7 @@ class SG_iCal_VEvent {
protected $location; protected $location;
public $recurrence; public $recurrence;
public $excluded;
public $freq; //getFrequency() public $freq; //getFrequency()
public $data; public $data;
@ -37,20 +38,28 @@ class SG_iCal_VEvent {
* @param SG_iCalReader $ical * @param SG_iCalReader $ical
*/ */
public function __construct($data, SG_iCal $ical) { public function __construct($data, SG_iCal $ical) {
$this->uid = $data['uid']->getData(); $this->uid = $data['uid']->getData();
unset($data['uid']); unset($data['uid']);
if ( isset($data['rrule']) ) { if ( isset($data['rrule']) ) {
$this->recurrence = new SG_iCal_Recurrence($data['rrule']); $this->recurrence = new SG_iCal_Recurrence($data['rrule']);
unset($data['rrule']); unset($data['rrule']);
//exclusions
if ( isset($data['exdate']) ) {
foreach ($data['exdate'] as $exdate) {
$this->excluded[] = $this->getTimestamp($exdate, $ical);
}
unset($data['exdate']);
}
} }
if( isset($data['dtstart']) ) { if( isset($data['dtstart']) ) {
$this->start = $this->getTimestamp($data['dtstart'], $ical); $this->start = $this->getTimestamp($data['dtstart'], $ical);
unset($data['dtstart']); unset($data['dtstart']);
} }
if( isset($data['dtend']) ) { if( isset($data['dtend']) ) {
$this->end = $this->getTimestamp($data['dtend'], $ical); $this->end = $this->getTimestamp($data['dtend'], $ical);
unset($data['dtend']); unset($data['dtend']);
@ -59,7 +68,7 @@ class SG_iCal_VEvent {
$this->end = $this->start + $dur->getDuration(); $this->end = $this->start + $dur->getDuration();
unset($data['duration']); unset($data['duration']);
} }
//google cal set dtend as end of initial event (duration) //google cal set dtend as end of initial event (duration)
if ( isset($this->recurrence) ) { if ( isset($this->recurrence) ) {
//if there is a recurrence rule //if there is a recurrence rule
@ -70,7 +79,7 @@ class SG_iCal_VEvent {
//ok.. //ok..
} elseif ($count) { } elseif ($count) {
//if count is set, then figure out the last occurrence and set that as the end date //if count is set, then figure out the last occurrence and set that as the end date
$this->freq = new SG_iCal_Freq($this->recurrence->rrule, $start); $this->freq = new SG_iCal_Freq($this->recurrence->rrule, $start, $this->excluded);
$until = $this->freq->lastOccurrence($this->start); $until = $this->freq->lastOccurrence($this->start);
} else { } else {
//forever... limit to 3 years //forever... limit to 3 years
@ -105,7 +114,7 @@ class SG_iCal_VEvent {
public function getFrequency() { public function getFrequency() {
if (! isset($this->freq)) { if (! isset($this->freq)) {
if ( isset($this->recurrence) ) { if ( isset($this->recurrence) ) {
$this->freq = new SG_iCal_Freq($this->recurrence->rrule, $this->start); $this->freq = new SG_iCal_Freq($this->recurrence->rrule, $this->start, $this->excluded);
} }
} }
return $this->freq; return $this->freq;

Wyświetl plik

@ -31,6 +31,7 @@ class SG_iCal_Freq {
protected $rules = array('freq'=>'yearly', 'interval'=>1); protected $rules = array('freq'=>'yearly', 'interval'=>1);
protected $start = 0; protected $start = 0;
protected $freq = ''; protected $freq = '';
protected $excluded;
public $cache; public $cache;
@ -39,8 +40,9 @@ class SG_iCal_Freq {
* @param $rule string * @param $rule string
* @param $start int Unix-timestamp (important : Need to be the start of Event) * @param $start int Unix-timestamp (important : Need to be the start of Event)
*/ */
public function __construct( $rule, $start ) { public function __construct( $rule, $start, $excluded=array()) {
$this->start = $start; $this->start = $start;
$this->excluded = $excluded;
$rules = array(); $rules = array();
foreach( explode(';', $rule) AS $v) { foreach( explode(';', $rule) AS $v) {
@ -53,7 +55,6 @@ class SG_iCal_Freq {
} }
$this->freq = strtolower($this->rules['freq']); $this->freq = strtolower($this->rules['freq']);
foreach( $this->knownRules AS $rule ) { foreach( $this->knownRules AS $rule ) {
if( isset($this->rules['by' . $rule]) ) { if( isset($this->rules['by' . $rule]) ) {
if( $this->isPrerule($rule, $this->freq) ) { if( $this->isPrerule($rule, $this->freq) ) {
@ -68,13 +69,11 @@ class SG_iCal_Freq {
} }
} }
//set until, and cache //set until
if( isset($this->rules['count']) ) { if( isset($this->rules['count']) ) {
$ts = $this->firstOccurrence(); $ts = $this->firstOccurrence();
$this->cache[0] = $ts;
for($i=1; $i<$this->rules['count']; $i++) { for($i=1; $i<$this->rules['count']; $i++) {
$ts = $this->findNext($ts); $ts = $this->findNext($ts);
$this->cache[$i] = $ts;
} }
$this->rules['until'] = $ts; $this->rules['until'] = $ts;
} }
@ -88,10 +87,12 @@ class SG_iCal_Freq {
public function getAllOccurrences() { public function getAllOccurrences() {
if (empty($this->cache)) { if (empty($this->cache)) {
//build cache //build cache
$i=0; $this->cache[0] = $this->start; unset($this->cache);
$this->cache[] = $this->start;
$next = $this->findNext($this->start); $next = $this->findNext($this->start);
while ($next) { while ($next) {
$i++; $this->cache[$i] = $next; //if (!in_array($next, $this->excluded))
$this->cache[] = $next;
$next = $this->findNext($next); $next = $this->findNext($next);
} }
} }
@ -106,7 +107,7 @@ class SG_iCal_Freq {
*/ */
public function previousOccurrence( $offset ) { public function previousOccurrence( $offset ) {
if (!empty($this->cache)) { if (!empty($this->cache)) {
$t2=$this->cache[0]; $t2=$this->start;
foreach($this->cache as $ts) { foreach($this->cache as $ts) {
if ($ts >= $offset) if ($ts >= $offset)
return $t2; return $t2;
@ -151,11 +152,9 @@ class SG_iCal_Freq {
if (!empty($this->cache)) { if (!empty($this->cache)) {
return end($this->cache); return end($this->cache);
} }
$i=0; $this->cache[0] = $this->start;
$ts = $next = $this->findNext($this->start); $ts = $next = $this->findNext($this->start);
while ($next) { while ($next) {
$ts = $next; $ts = $next;
$i++; $this->cache[$i] = $ts;
$next = $this->findNext($ts); $next = $this->findNext($ts);
} }
return $ts; return $ts;
@ -185,7 +184,6 @@ class SG_iCal_Freq {
* @return int * @return int
*/ */
public function findNext($offset) { public function findNext($offset) {
if (!empty($this->cache)) { if (!empty($this->cache)) {
foreach($this->cache as $ts) { foreach($this->cache as $ts) {
if ($ts > $offset) if ($ts > $offset)
@ -214,10 +212,11 @@ class SG_iCal_Freq {
if( $this->simpleMode ) { if( $this->simpleMode ) {
if( $offset < $t ) { if( $offset < $t ) {
return $t; return $t;
} } else {
$next = $this->findStartingPoint( $t, $this->rules['interval'], false ); $next = $this->findStartingPoint( $t, $this->rules['interval'], false );
if( !$this->validDate( $next ) ) { if( !$this->validDate( $next ) ) {
return $this->findNext($next); return $this->findNext($next);
}
} }
return $next; return $next;
} }
@ -250,19 +249,23 @@ class SG_iCal_Freq {
} }
if( $offset < $this->start && $this->start < $t ) { if( $offset < $this->start && $this->start < $t ) {
return $this->start; $ts = $this->start;
} else if( $found && ($t != $offset)) { } else if( $found && ($t != $offset)) {
if( $this->validDate( $t ) ) { if( $this->validDate( $t ) ) {
if($debug) echo 'OK' . "\n"; if($debug) echo 'OK' . "\n";
return $t; $ts = $t;
} else { } else {
if($debug) echo 'Invalid' . "\n"; if($debug) echo 'Invalid' . "\n";
return $this->findNext($t); $ts = $this->findNext($t);
} }
} else { } else {
if($debug) echo 'Not found' . "\n"; if($debug) echo 'Not found' . "\n";
return $this->findNext( $this->findStartingPoint( $offset, $this->rules['interval'] ) ); $ts = $this->findNext( $this->findStartingPoint( $offset, $this->rules['interval'] ) );
} }
if ($ts && in_array($ts, $this->excluded))
return $this->findNext($ts);
return $ts;
} }
/** /**
@ -454,6 +457,10 @@ class SG_iCal_Freq {
if( isset($this->rules['until']) && $t > $this->rules['until'] ) { if( isset($this->rules['until']) && $t > $this->rules['until'] ) {
return false; return false;
} }
if (in_array($t, $this->excluded)) {
return false;
}
if( isset($this->rules['bymonth']) ) { if( isset($this->rules['bymonth']) ) {
$months = explode(',', $this->rules['bymonth']); $months = explode(',', $this->rules['bymonth']);

Wyświetl plik

@ -119,8 +119,13 @@ class SG_iCal_Parser {
if( array_search($s, $sections) !== false ) { if( array_search($s, $sections) !== false ) {
// This section is in the main section // This section is in the main section
if( $section == $s ) { if( $section == $s ) {
// It _is_ the main section // It _is_ the main section else
$current_data[$s][$line->getIdent()] = $line; if ($line->getIdent() != "exdate")
$current_data[$s][$line->getIdent()] = $line;
else {
//exdate could appears more that once
$current_data[$s][$line->getIdent()][] = $line;
}
} else { } else {
// Sub section // Sub section
$current_data[$s][$section][$line->getIdent()] = $line; $current_data[$s][$section][$line->getIdent()] = $line;

Wyświetl plik

@ -42,7 +42,6 @@ class SG_iCal_Recurrence {
'byyearday', 'byyearno', 'bymonth', 'bysetpos' 'byyearday', 'byyearno', 'bymonth', 'bysetpos'
); );
/** /**
* Creates an recurrence object with a passed in line. Parses the line. * Creates an recurrence object with a passed in line. Parses the line.
* @param object $line an SG_iCal_Line object which will be parsed to get the * @param object $line an SG_iCal_Line object which will be parsed to get the