private function add_rrule($rrule_string) { $rules = explode(';', $rrule_string); $this->recur = TRUE; if ($this->occurrences === NULL) { $this->occurrences = Array(); } // read attributes from rrule_string $limit_type = ''; $limit = ''; $incrementors = Array( 'SECONDLY' => 'increment_second', 'MINUTELY' => 'increment_minute', 'HOURLY' => 'increment_hour', 'DAILY' => 'increment_day', 'WEEKLY' => 'increment_week', 'MONTHLY' => 'increment_month', 'YEARLY' => 'increment_year', ); $occurs_by_list = Array(); foreach ($rules as $rule) { $namevalue = explode('=', $rule); $rulename = $namevalue[0]; $rulevalue = $namevalue[1]; switch ($rulename) { case 'FREQ': // always present $this->incrementor = $incrementors[$rulevalue]; break; case 'INTERVAL': $this->interval = $rulevalue; case 'UNTIL': $limit_type = 'UNTIL'; $this->until = ICalendar::ical2unix($rulevalue); break; case 'COUNT': $limit_type = 'COUNT'; $limit = $rulevalue; break; case (substr($rulename, 0, 2) == 'BY'): $occurs_by_list[$rulename] = explode(',', $rulevalue); break; } } // finished reading attributes from rrule_string $occursByTypes = Array( 'BYMONTH' => Array('func' => 'increment_month', 'format' => 'n'), 'BYWEEKNO' => Array('func' => 'increment_week', 'format' => 'W'), 'BYYEARDAY' => Array('func' => 'increment_day', 'format' => 'z'), 'BYMONTHDAY' => Array('func'=> 'increment_day', 'format' => 'j'), 'BYDAY' => Array('func' => 'increment_day', 'format' => 'w'), 'BYHOUR' => Array('func' => 'increment_hour', 'format' => 'G'), 'BYMINUTE' => Array('func' => 'increment_minute', 'format' => 'i'), 'BYSECOND' => Array('func' => 'increment_second', 'format' => 's'), ); // create the first occurrence set $occur_unit = Array($this->range->get_start()); foreach ($occursByTypes as $byfreq => $attribs) { // we loop through occurByTypes so we can be sure to // act on each "by frequency" rule in order of decreasing grain size if (array_key_exists($byfreq, $occurs_by_list)) { $new_occur_unit = Array(); // every "when" within the "by frequency" // e.g. MO,TU,WE for BYDAY // needs to be a separate element of the occurrence set foreach($occurs_by_list[$byfreq] as $when) { $occurs_when = ($byfreq == 'BYDAY') ? ICalendar::$dayIndex[$when] : $when; // if the set of occurrences already has multiple elements // they will be multiplied // e.g. MO,TU for BYDAY and 1,2,3 for BYMONTH // yields 6 elements in the occurence set foreach ($occur_unit as $start) { $count = 0; // for debugging below while (intval(date($attribs['format'], $start)) != $occurs_when) { $start = call_user_func($attribs['func'], $start); // haven't seen this happen yet but who knows if ($count > 366) { throw new ICalendarException("maximum loop count exceeded"); } $count += 1; } $new_occur_unit[] = $start; } } $occur_unit = $new_occur_unit; } } // BYSETPOS limits us to particular indices of the occurrence set if (array_key_exists('BYSETPOS', $occurs_by_list)) { $new_occur_unit = Array(); $setposlist = $occurs_by_list['BYSETPOS']; foreach ($setposlist as $setpos) { if ($setpos < 0) { $setpos = count($occur_unit) + $setpos; } else { $setpos = $setpos - 1; } $new_occur_unit[] = $occur_unit[$setpos]; } $occur_unit = $new_occur_unit; } $this->occurrences = $occur_unit; // duplicate the occurrence set for COUNT limits // this is approximate if ($limit_type == 'COUNT') { $num_increments = $limit / count($this_occurrences); $end = end($occur_unit); while ($num_increments > 0) { $end = $this->incrementor($end); $num_increments -= 1; } $this->until = $end; } }