]>
git.datanom.net - webcal.git/blob - caldav/rruleparser.class.php
4 require_once 'caldavresource.class.php';
6 define ('FREQUENCE', 'HOURLY,DAILY,WEEKLY,MONTHLY,YEARLY');
9 * Unsupported: SECONDLY, MINUTELY, YEARLY,
10 * BYSECOND, BYMINUTE, BYSETPOS, WKST
11 * Also preceeding where preceeding is allowed is not
23 function __construct($rrule = NULL, $start = NULL, $end = NULL) {
24 $this->freq
= preg_split("/[\s,]+/", FREQUENCE
);
26 $this->setRule($rrule, $start, $end);
29 function setRule($rrule, $start, $end) {
30 if (!($start && $end))
31 throw new Exception("Missing values for DTSTART and/or DTEND");
32 //print "$start:$end<br/>";
33 //print var_export($rrule, TRUE) . "<br/>";
34 $this->start
= CaldavRessource
::iCal2Timestamp($start);
35 $this->end
= CaldavRessource
::iCal2Timestamp($end);
36 //print CaldavRessource::timestamp2ICal($this->start, TRUE).":".CaldavRessource::timestamp2ICal($this->end, TRUE)."<br/>";
37 $rules = explode(';', $rrule);
39 if (count($rules) < 2) {
40 foreach ($rules as $rule) {
41 $pair = explode('=', $rule);
42 if (count($pair) < 2 ||
!in_array($pair[1], $this->freq
)) {
43 $this->rules
= array();
44 throw new Exception("$rrule: Invalid RRULE");
46 $this->rules
[strtolower($pair[0])] = explode(',', $pair[1]);
50 foreach ($rules as $rule) {
51 $pair = explode('=', $rule);
52 $this->rules
[strtolower($pair[0])] = explode(',', $pair[1]);
55 if ($this->rules
['until'][0] && $this->rules
['count'][0]) {
56 $this->rules
= array();
57 throw new Exception("COUNT and UNTIL cannot be present at the same time");
59 if (!in_array($this->rules
['freq'][0], $this->freq
)) {
61 "[{$this->rules['freq'][0]}] Unsupported FREQ",
63 $this->rules
= array();
67 private function getEnd($freq) {
68 $count = $this->getCount();
69 $until = $this->getUntil();
70 //print "$until<br/>";
72 $int = $this->getInterval();
73 $count = ($int) ?
$int * $count : $count;
75 case 'HOURLY': $str = "+$count hour"; break;
76 case 'DAILY': $str = "+$count day"; break;
77 case 'WEEKLY': $str = "+$count week"; break;
78 case 'MONTHLY': $str = "+$count month"; break;
79 case 'YEARLY': $str = "+$count year"; break;
81 $end = strtotime($str, $this->start
);
82 return ($this->range_end
&& $this->range_end
< $end) ?
83 $this->range_end
: $end;
87 * UNTIL has first occurrence at end time and
88 * last ocurrence ending at start time
90 //print "$until:".$this->start."<br/>";
91 $u_s = explode("T", CaldavRessource
::timestamp2ICal($this->end
));
92 $time_s = (int) substr($u_s[1], 0, 2);
93 $u_e = explode("T", $until);
94 $time_e = (int) substr($u_e[1], 0, 2);
95 $until = ($time_s != $time_e) ?
"{$u_e[0]}T{$u_s[1]}" : $until;
96 //print "$time_s:$time_e:$until<br/>";
97 $end = CaldavRessource
::iCal2Timestamp($until);
98 //print CaldavRessource::timestamp2ICal($end)."<br/>";
99 return ($this->range_end
&& $this->range_end
< $end) ?
100 $this->range_end
: $end;
103 return $this->range_end
;
106 private function except($ts) {
107 $byhour = $this->getByHour();
110 $match = gmdate('G', $ts);
111 foreach ($byhour as $hour) {
119 $byday = $this->getByDay();
122 $match = substr(strtolower(gmdate('D', $ts)), 0, 2);
123 foreach ($byday as $day) {
124 //print "$match:$day\n";
125 if ($match == strtolower($day))
132 $bymonth = $this->getByMonth();
135 $match = gmdate('n', $ts);
136 foreach ($bymonth as $month) {
137 if ($match == $month)
144 $bymonthday = $this->getByMonthDay();
147 $match = gmdate('j', $ts);
148 foreach ($bymonthday as $monthday) {
149 if ($match +
1 == $monthday)
156 $byweekno = $this->getByWeekNo();
159 // Missing to handle Anglo week numbers
160 // (week start on Sunday)
161 $match = gmdate('W', $ts);
162 foreach ($byweekno as $weekno) {
163 if ($match == $weekno)
170 $byyearday = $this->getByYearDay();
173 $match = gmdate('z', $ts);
174 foreach ($byyearday as $yearday) {
175 if ($match == $yearday)
185 private function hourly() {
187 $end = $this->getEnd('HOURLY');
190 * we will maximum handle one month at a time unless
191 * a specific end date specifies otherwise
193 $end = strtotime('+1 month', $this->start
);
195 $int = ($this->getInterval()) ?
$this->getInterval() : 1;
197 for (; $c < $end; $c = strtotime("+$int hour", $c)) {
198 if (! $this->except($c))
199 array_push($res, CaldavRessource
::timestamp2ICal($c));
204 private function daily() {
206 $end = $this->getEnd('DAILY');
209 * we will maximum handle one month at a time unless
210 * a specific end date specifies otherwise
212 $end = strtotime('+1 month', $this->start
);
214 $int = ($this->getInterval()) ?
$this->getInterval() : 1;
216 for (; $c < $end; $c = strtotime("+$int day", $c)) {
217 if (! $this->except($c))
218 array_push($res, CaldavRessource
::timestamp2ICal($c));
223 private function weekly() {
225 $end = $this->getEnd('WEEKLY');
226 //print "start: ".CaldavRessource::timestamp2ICal($this->start)." end: ".CaldavRessource::timestamp2ICal($end)."\n";
229 * we will maximum handle 12 weeks at a time unless
230 * a specific end date specifies otherwise
232 $end = strtotime('+12 week', $this->start
);
234 $int = ($this->getInterval()) ?
$this->getInterval() : 1;
236 for (; $c < $end; $c = strtotime("+$int week", $c)) {
237 //print CaldavRessource::timestamp2ICal($c)."<br/>";
238 if (! $this->except($c))
239 array_push($res, CaldavRessource
::timestamp2ICal($c));
245 private function monthly() {
247 $end = $this->getEnd('MONTHLY');
250 * we will maximum handle 12 months at a time unless
251 * a specific end date specifies otherwise
253 $end = strtotime('+12 month', $this->start
);
255 $int = ($this->getInterval()) ?
$this->getInterval() : 1;
257 for (; $c < $end; $c = strtotime("+$int month", $c)) {
258 if (! $this->except($c))
259 array_push($res, CaldavRessource
::timestamp2ICal($c));
264 private function yearly() {
266 $end = $this->getEnd('YEARLY');
269 * we will maximum handle 12 years at a time unless
270 * a specific end date specifies otherwise
272 $end = strtotime('+12 year', $this->start
);
274 $int = ($this->getInterval()) ?
$this->getInterval() : 1;
276 for (; $c < $end; $c = strtotime("+$int year", $c)) {
277 if (! $this->except($c))
278 array_push($res, CaldavRessource
::timestamp2ICal($c));
283 private function limitRange($dates) {
285 if (!$this->range_start
&& !$this->range_end
) {
288 else if ($this->range_start
&& !$this->range_end
) {
289 $start = CaldavRessource
::timestamp2ICal($this->range_start
);
290 foreach ($dates as $date) {
291 if (CaldavRessource
::datecmp($start, $date) < 0)
292 array_push($res, $date);
296 $start = CaldavRessource
::timestamp2ICal($this->range_start
);
297 $end = CaldavRessource
::timestamp2ICal($this->range_end
);
298 foreach ($dates as $date) {
299 if (CaldavRessource
::datecmp($start, $date) < 0 &&
300 CaldavRessource
::datecmp($end, $date) > 0)
301 array_push($res, $date);
308 return strtoupper($this->rules
['freq'][0]);
311 function getUntil() {
312 return strtoupper($this->rules
['until'][0]);
315 function getCount() {
316 return strtoupper($this->rules
['count'][0]);
319 function getInterval() {
320 return strtoupper($this->rules
['interval'][0]);
323 function getBySecond() {
324 $l = $this->rules
['bysecond'];
327 $list[] = strtoupper($val);
332 function getByMinute() {
333 $l = $this->rules
['byminute'];
336 $list[] = strtoupper($val);
341 function getByHour() {
342 $l = $this->rules
['byhour'];
345 $list[] = strtoupper($val);
350 function getByDay() {
351 $l = $this->rules
['byday'];
354 $list[] = strtoupper($val);
359 function getByMonthDay() {
360 $l = $this->rules
['bymonthday'];
363 $list[] = strtoupper($val);
368 function getByYearDay() {
369 $l = $this->rules
['byyearday'];
372 $list[] = strtoupper($val);
377 function getByWeekNo() {
378 $l = $this->rules
['byweekno'];
381 $list[] = strtoupper($val);
386 function getByMonth() {
387 $l = $this->rules
['bymonth'];
390 $list[] = strtoupper($val);
395 function getBySetPos() {
396 return strtoupper($this->rules
['bysetpos'][0]);
400 return strtoupper($this->rules
['wkst'][0]);
407 function getEventDates($startDate = NULL, $endDate = NULL) {
410 $freq = $this->getFreq();
412 if (! in_array($freq, $this->freq
))
414 if ($startDate && $endDate) {
415 $this->range_start
= CaldavRessource
::iCal2Timestamp($startDate);
416 $this->range_end
= CaldavRessource
::iCal2Timestamp($endDate);
417 if ($this->start
> $this->range_end
)
420 else if ($startDate) {
421 $this->range_start
= CaldavRessource
::iCal2Timestamp($startDate);
422 $this->range_end
= NULL;
425 $this->range_start
= NULL;
426 $this->range_end
= NULL;
429 case 'HOURLY': $dates = $this->hourly(); break;
430 case 'DAILY': $dates = $this->daily(); break;
431 case 'WEEKLY': $dates = $this->weekly(); break;
432 case 'MONTHLY': $dates = $this->monthly(); break;
433 case 'YEARLY': $dates = $this->yearly(); break;
437 return (count($dates) > 0) ?
$this->limitRange($dates) : $dates;
440 function getStartAndEnd() {
441 $res['start'] = $this->start
;
442 $res['end'] = $this->end
;
447 function __toString() {
448 $str = "FREQ=" . $this->getFreq();
449 $until = $this->getUntil();
450 $count = $this->getCount();
452 $str .= ';UNTIL=' . $until;
454 $str .= ';COUNT=' . $count;
455 foreach ($this->rules
as $k => $v) {
456 if ($k == 'freq' ||
$k == 'count' ||
$k == 'until')
458 $str .= ';' . strtoupper($k) . '=';
459 foreach($v as $rule) {
460 if ($str[strlen($str) - 1] != '=')
462 $str .= strtoupper($rule);
This page took 0.110681 seconds and 6 git commands to generate.