From ca0dcc1af094a87f5d3c9dcf2a0cb1b06f725418 Mon Sep 17 00:00:00 2001 From: Tanguy Pruvot Date: Sat, 30 Oct 2010 20:54:42 +0200 Subject: [PATCH] implement frequency cache, actually only set in some cases : count recurrence or using lastOccurrence() --- blocks/SG_iCal_VEvent.php | 29 +++++++++++++++++++++++------ demo/index.php | 7 ++++--- helpers/SG_iCal_Freq.php | 36 ++++++++++++++++++++++++++++-------- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/blocks/SG_iCal_VEvent.php b/blocks/SG_iCal_VEvent.php index 02e35ca..7b4fa69 100755 --- a/blocks/SG_iCal_VEvent.php +++ b/blocks/SG_iCal_VEvent.php @@ -15,7 +15,7 @@ */ class SG_iCal_VEvent { const DEFAULT_CONFIRMED = true; - + protected $uid; protected $start; protected $end; @@ -24,10 +24,12 @@ class SG_iCal_VEvent { protected $summary; protected $description; protected $location; - + public $recurrence; + public $freq; //getFrequency() + public $data; - + /** * Constructs a new SG_iCal_VEvent. Needs the SG_iCalReader * supplied so it can query for timezones. @@ -35,6 +37,7 @@ class SG_iCal_VEvent { * @param SG_iCalReader $ical */ public function __construct($data, SG_iCal $ical) { + $this->uid = $data['uid']->getData(); unset($data['uid']); @@ -42,7 +45,7 @@ class SG_iCal_VEvent { $this->recurrence = new SG_iCal_Recurrence($data['rrule']); unset($data['rrule']); } - + if( isset($data['dtstart']) ) { $this->start = $this->getTimestamp($data['dtstart'], $ical); unset($data['dtstart']); @@ -67,8 +70,8 @@ class SG_iCal_VEvent { //ok.. } elseif ($count) { //if count is set, then figure out the last occurrence and set that as the end date - $freq = new SG_iCal_Freq($this->recurrence->rrule, $start); - $until = $freq->lastOccurrence($this->start); + $this->freq = new SG_iCal_Freq($this->recurrence->rrule, $start); + $until = $this->freq->lastOccurrence($this->start); } else { //forever... limit to 3 years $this->recurrence->setUntil('+3 years'); @@ -94,6 +97,20 @@ class SG_iCal_VEvent { $this->data = SG_iCal_Line::Remove_Line($data); } + + /** + * Returns the Event Occurrences Iterator (if recurrence set) + * @return SG_iCal_Freq + */ + public function getFrequency() { + if (! isset($this->freq)) { + if ( isset($this->recurrence) ) { + $this->freq = new SG_iCal_Freq($this->recurrence->rrule, $this->start); + } + } + return $this->freq; + } + /** * Returns the UID of the event * @return string diff --git a/demo/index.php b/demo/index.php index 8551eb4..f6b4f0c 100644 --- a/demo/index.php +++ b/demo/index.php @@ -11,8 +11,8 @@ $ICS = "basic.ics"; $ical = new SG_iCalReader($ICS); $query = new SG_iCal_Query(); -//$evts = $ical->getEvents(); -$evts = $query->Between($ical,strtotime('20100901'),strtotime('20101131')); +$evts = $ical->getEvents(); +//$evts = $query->Between($ical,strtotime('20100901'),strtotime('20101131')); $data = array(); @@ -30,7 +30,8 @@ foreach($evts as $id => $ev) { if (isset($ev->recurrence)) { $count = 1; $start = $ev->getStart(); - $freq = new SG_iCal_Freq($ev->recurrence->rrule, $start); + //$freq = new SG_iCal_Freq($ev->recurrence->rrule, $start); + $freq = $ev->getFrequency(); while (($next = $freq->nextOccurrence($start)) > 0 ) { if (!$next or $count >= 200) break; $count++; diff --git a/helpers/SG_iCal_Freq.php b/helpers/SG_iCal_Freq.php index 4ad9c46..f02071e 100755 --- a/helpers/SG_iCal_Freq.php +++ b/helpers/SG_iCal_Freq.php @@ -31,11 +31,13 @@ class SG_iCal_Freq { protected $rules = array('freq'=>'yearly', 'interval'=>1); protected $start = 0; protected $freq = ''; + + public $cache; /** * Constructs a new Freqency-rule * @param $rule string - * @param $start int Unix-timestamp (important!) + * @param $start int Unix-timestamp (important : Need to be the start of Event) */ public function __construct( $rule, $start ) { $this->start = $start; @@ -65,11 +67,14 @@ class SG_iCal_Freq { $this->rules['bymonthday'] = date('d', $this->start); } } - + + //set until, and cache if( isset($this->rules['count']) ) { $ts = $this->firstOccurrence(); + $this->cache[0] = $ts; for($i=1; $i<$this->rules['count']; $i++) { $ts = $this->findNext($ts); + $this->cache[$i] = $ts; } $this->rules['until'] = $ts; } @@ -82,14 +87,24 @@ class SG_iCal_Freq { * @return int */ public function previousOccurrence( $offset ) { - $t1 = $this->start; - while( ($t2 = $this->findNext($t1)) < $offset) { - if( $t2 == false ){ - break; + if (!empty($this->cache)) { + reset($this->cache); + while( ($t2 = next($this->cache)) < $offset) { + if( $t2 == false ){ + break; + } + $ts = $t2; + } + } else { + $ts = $this->start; + while( ($t2 = $this->findNext($ts)) < $offset) { + if( $t2 == false ){ + break; + } + $ts = $t2; } - $t1 = $t2; } - return $t1; + return $ts; } /** @@ -116,9 +131,14 @@ class SG_iCal_Freq { * @return int timestamp */ public function lastOccurrence() { + if (!empty($this->cache)) { + return end($this->cache); + } + $i=0; $this->cache[0] = $this->start; $ts = $next = $this->findNext($this->start); while ($next) { $ts = $next; + $i++; $this->cache[$i] = $ts; $next = $this->findNext($ts); } return $ts;