/** * @param $EventId int Id of event. * @return array * - rdates * - rrules * - exdates * - exrules * @todo Optional date limits */ function SelectRecurByEvent($EventId) { static $date_fields = array('event_date_start AS start', 'event_date_time_associated AS time_associated', 'event_date_duration AS duration', 'event_date_exclude AS exclude'); // Get dates $this->db->select(implode(',', $date_fields)); $this->db->from('event_dates'); $this->db->where(array('event_date_event_id' => $EventId)); /// @todo Limit by time using range of selection (min <= date <= max) $dates_query = $this->db->get(); $dates = $dates_query->result_array(); $include_ranges = array(); $exclude_ranges = array(); foreach ($dates as $date) { $start_parts = explode(' ', $date['start']); $start_date = str_replace('-', '', $start_parts[0]); // YYYYMMDD if ($date['time_associated']) { $start_time = str_replace(':', '', $start_parts[1]); // HHMMSS } else { $start_time = NULL; } if (NULL === $date['duration']) { $duration = NULL; } else { $duration = (int) $date['duration']; } if (!$date['exclude']) { // include if (!array_key_exists($start_date, $include_ranges)) { $include_ranges[$start_date] = array(); } $include_ranges[$start_date][$start_time] = $duration; } else { // exclude (never a range) if (!array_key_exists($start_date, $exclude_ranges)) { $exclude_ranges[$start_date] = array(); } $exclude_ranges[$start_date][$start_time] = NULL; } } static $rule_fields = array('event_recur_rule_id AS rule_id', 'event_recur_rule_event_id AS event_id', 'event_recur_rule_exclude AS exclude', 'event_recur_rule_frequency AS frequency', 'UNIX_TIMESTAMP(event_recur_rule_until) AS until', 'event_recur_rule_count AS count', 'event_recur_rule_interval AS recur_interval', 'event_recur_rule_week_start AS week_start', 'event_recur_rule_by_by AS by_by', 'event_recur_rule_by_primary AS by_primary', 'event_recur_rule_by_secondary AS by_secondary'); /// @todo Limit by time using range of selection (until > min) // Get recurrence rules $this->db->select(implode(',', $rule_fields)); $this->db->from('event_recur_rules'); $this->db->join('event_recur_rule_by', 'event_recur_rule_by_event_recur_rule_id = event_recur_rule_id', 'left'); $this->db->where(array('event_recur_rule_event_id' => $EventId)); $rules_query = $this->db->get(); // Turn each rule into an object $rrules = array(); $exrules = array(); $results = $rules_query->result_array(); foreach ($results as $rule_data) { $category_name = $rule_data['exclude'] ? 'exrules' : 'rrules'; // If not already created, do so now $recur_id = (int) $rule_data['rule_id']; if (!array_key_exists($recur_id, ${$category_name})) { $rule = new CalendarRecurRule(); $rule->SetFrequency($rule_data['frequency']); if (NULL !== $rule_data['until']) { $rule->SetUntil((int) $rule_data['until']); } elseif (NULL !== $rule_data['count']) { $rule->SetCount((int) $rule_data['count']); } if (NULL !== $rule_data['recur_interval']) { $rule->SetInterval((int) $rule_data['recur_interval']); } if (NULL !== $rule_data['week_start']) { $rule->SetWkSt(CalendarRecurRule::$sWeekdays[strtoupper($rule_data['week_start'])]); } if ($rule_data['exclude']) { $exrules[$recur_id] = $rule; } else { $rrules[$recur_id] = $rule; } } // If by data included, add it if (NULL !== $rule_data['by_by']) { $primary = (int) $rule_data['by_primary']; $optional = $rule_data['by_secondary']; if (NULL !== $optional) { if ($optional != 0) { $optional = (int) $optional; } else { $optional = NULL; } } if ($rule_data['exclude']) { $rule =& $exrules[$recur_id]; } else { $rule =& $rrules[$recur_id]; } switch ($rule_data['by_by']) { case 'second': $rule->SetBySecond($primary); break; case 'minute': $rule->SetByMinute($primary); break; case 'hour': $rule->SetByHour($primary); break; case 'day': $rule->SetByDay($primary, $optional); break; case 'monthday': $rule->SetByMonthDay($primary); break; case 'yearday': $rule->SetByYearDay($primary); break; case 'weekno': $rule->SetByWeekNo($primary); break; case 'month': $rule->SetByMonth($primary); break; case 'setpos': $rule->SetBySetPos($primary); break; case 'term': $rule->SetByTerm($primary); break; case 'termday': $rule->SetByTermDay($primary); break; case 'termweek': $rule->SetByTermWeek($primary); break; case 'easter': $rule->SetByEaster($primary); break; } } } return array($include_ranges, $rrules, $exclude_ranges, $exrules); }
static function validate_recurrence_rule_data(&$simple, &$errors) { // If no recurrence is enabled, just return NULL if (!isset($simple['enable'])) { return NULL; } // Otherwise, create the recurrence rule. $recur = new CalendarRecurRule(); // Interval if (isset($simple['interval'])) { $interval = $simple['interval']; if (is_numeric($interval)) { $recur->SetInterval((int) $interval); } else { $errors[] = array('field' => 'interval', 'text' => "Non-numeric interval: {$interval}"); } } // Frequency dependent if (isset($simple['freq'])) { switch ($simple['freq']) { case 'daily': $recur->SetFrequency('daily'); break; case 'weekly': $recur->SetFrequency('weekly'); if (isset($simple['weekly_byday']) && is_array($simple['weekly_byday'])) { foreach ($simple['weekly_byday'] as $day => $dummy) { if (is_numeric($day) && $day >= 0 && $day < 7) { $recur->SetByDay($day); } } } break; case 'monthly': $recur->SetFrequency('monthly'); if (isset($simple['monthly_method'])) { switch ($simple['monthly_method']) { case 'monthday': if (isset($simple['monthly_monthday']) && is_array($simple['monthly_monthday'])) { $monthday =& $simple['monthly_monthday']; $monthday_fail = false; if (!isset($monthday['monthday']) || !is_numeric($monthday['monthday'])) { $monthday_fail = true; $errors[] = array('field' => 'monthly_monthday', 'text' => 'Invalid monthly day.'); } elseif ($monthday['monthday'] < -31 || $monthday['monthday'] > 31 || !$monthday['monthday']) { $monthday_fail = true; $errors[] = array('field' => 'monthly_monthday', 'text' => 'Monthly day out of range'); } if (!$monthday_fail) { $recur->SetByMonthDay((int) $monthday['monthday']); } } break; case 'weekday': if (isset($simple['monthly_weekday']) && is_array($simple['monthly_weekday'])) { $weekday =& $simple['monthly_weekday']; $weekday_fail = false; if (!isset($weekday['day'])) { $weekday_fail = true; $errors[] = array('field' => 'monthly_weekday', 'text' => 'Invalid monthly day.'); } else { $days_split = split(',', $weekday['day']); $monthly_weekday_days = array(); foreach ($days_split as $day) { if (!is_numeric($day) || $day < 0 || $day > 6) { $weekday_fail = true; } else { $monthly_weekday_days[] = (int) $day; } } if ($weekday_fail) { $errors[] = array('field' => 'monthly_weekday', 'text' => 'Monthly day(s) out of range'); } } if (!isset($weekday['week']) || !is_numeric($weekday['week'])) { $weekday_fail = true; $errors[] = array('field' => 'monthly_weekday', 'text' => 'Invalid monthly week.'); } elseif ($weekday['week'] < -5 || $weekday['week'] > 5 || !$weekday['week']) { $weekday_fail = true; $errors[] = array('field' => 'monthly_weekday', 'text' => 'Monthly week out of range'); } if (!$weekday_fail) { if (count($monthly_weekday_days) == 1) { $recur->SetByDay($monthly_weekday_days[0], (int) $weekday['week']); } else { foreach ($monthly_weekday_days as $day) { $recur->SetByDay($day); } $recur->SetBySetPos((int) $weekday['week']); } } } break; } } break; case 'yearly': $recur->SetFrequency('yearly'); if (isset($simple['yearly_method'])) { switch ($simple['yearly_method']) { case 'monthday': if (isset($simple['yearly_monthday']) && is_array($simple['yearly_monthday'])) { $monthday =& $simple['yearly_monthday']; $monthday_fail = false; if (!isset($monthday['monthday']) || !is_numeric($monthday['monthday'])) { $monthday_fail = true; $errors[] = array('field' => 'yearly_monthday', 'text' => 'Invalid yearly day.'); } elseif ($monthday['monthday'] < -31 || $monthday['monthday'] > 31 || !$monthday['monthday']) { $monthday_fail = true; $errors[] = array('field' => 'yearly_monthday', 'text' => 'yearly day out of range'); } if (!isset($monthday['month']) || !is_numeric($monthday['month'])) { $monthday_fail = true; $errors[] = array('field' => 'yearly_monthday', 'text' => 'Invalid yearly month.'); } elseif ($monthday['month'] < 1 || $monthday['month'] > 12) { $monthday_fail = true; $errors[] = array('field' => 'yearly_monthday', 'text' => 'yearly month out of range'); } if (!$monthday_fail) { $recur->SetByMonthDay((int) $monthday['monthday']); $recur->SetByMonth((int) $monthday['month']); } } break; case 'weekday': if (isset($simple['yearly_weekday']) && is_array($simple['yearly_weekday'])) { $weekday =& $simple['yearly_weekday']; $weekday_fail = false; if (!isset($weekday['week']) || !is_numeric($weekday['week'])) { $weekday_fail = true; $errors[] = array('field' => 'yearly_weekday', 'text' => 'Invalid yearly week.'); } elseif ($weekday['week'] < -5 || $weekday['week'] > 5 || !$weekday['week']) { $weekday_fail = true; $errors[] = array('field' => 'yearly_weekday', 'text' => 'yearly week out of range'); } if (!isset($weekday['day']) || !is_numeric($weekday['day'])) { $weekday_fail = true; $errors[] = array('field' => 'yearly_weekday', 'text' => 'Invalid yearly day.'); } elseif ($weekday['day'] < 0 || $weekday['day'] > 6) { $weekday_fail = true; $errors[] = array('field' => 'yearly_weekday', 'text' => 'yearly day out of range'); } if (!isset($weekday['month']) || !is_numeric($weekday['month'])) { $weekday_fail = true; $errors[] = array('field' => 'yearly_monthday', 'text' => 'Invalid yearly month.'); } elseif ($weekday['month'] < 1 || $weekday['month'] > 12) { $weekday_fail = true; $errors[] = array('field' => 'yearly_monthday', 'text' => 'yearly month out of range'); } if (!$weekday_fail) { // use monthly with bymonth and byday /// @note jh559: using monthly frequency here doesn't work coz yearly interval would be wrong // $recur->SetFrequency('monthly'); // $recur->SetByMonth((int)$weekday['month']); // $recur->SetByDay((int)$weekday['day'], (int)$weekday['week']); // use yearly with bymonth and bysetpos $recur->SetByDay((int) $weekday['day'], (int) $weekday['week']); $recur->SetByMonth((int) $weekday['month']); //$recur->SetBySetpos((int)$weekday['week']); } } break; case 'yearday': if (isset($simple['yearly_yearday']) && is_array($simple['yearly_yearday'])) { $yearday =& $simple['yearly_yearday']; if (!isset($yearday['yearday']) || !is_numeric($yearday['yearday'])) { $errors[] = array('field' => 'yearly_yearday', 'text' => 'Invalid yearly day of year.'); } elseif ($yearday['yearday'] < -365 || $yearday['yearday'] > 365 || !$yearday['yearday']) { $errors[] = array('field' => 'yearly_weekday', 'text' => 'yearly day of year out of range'); } else { $recur->SetByYearday((int) $yearday['yearday']); } } break; } } break; default: $errors[] = array('field' => 'freq', 'text' => 'Unrecognised frequency'); break; } } else { $errors[] = array('text' => 'Recurrence frequency missing'); } // Range if (isset($simple['range_method'])) { switch ($simple['range_method']) { case 'count': if (isset($simple['count']) && is_numeric($simple['count'])) { if ($simple['count'] > 0) { $recur->SetCount((int) $simple['count']); } else { $recur->SetCount(1); $errors[] = array('field' => 'count', 'text' => 'Occurrence count should be positive and non-zero'); } } else { $recur->SetCount(10); $errors[] = array('field' => 'count', 'text' => 'Non-numeric occurrence count'); } break; case 'until': if (isset($simple['until']) && is_array($simple['until'])) { $until =& $simple['until']; $until_fail = false; if (!isset($until['year']) || !is_numeric($until['year'])) { $until_fail = true; $errors[] = array('field' => 'until', 'text' => 'Invalid until year'); } elseif ($until['year'] < 2000 || $until['year'] > 2100) { $until_fail = true; $errors[] = array('field' => 'until', 'text' => 'Until year out of range'); } if (!isset($until['month']) || !is_numeric($until['month'])) { $until_fail = true; $errors[] = array('field' => 'until', 'text' => 'Invalid until month'); } elseif ($until['month'] < 1 || $until['month'] > 12) { $until_fail = true; $errors[] = array('field' => 'until', 'text' => 'Until month out of range'); } if (!isset($until['monthday']) || !is_numeric($until['monthday'])) { $until_fail = true; $errors[] = array('field' => 'until', 'text' => 'Invalid until day of month'); } elseif ($until['monthday'] < 1 || $until['monthday'] > 31) { $until_fail = true; $errors[] = array('field' => 'until', 'text' => 'Year out of range'); } if (!$until_fail) { $until_date = mktime(23, 59, 59, (int) $until['month'], (int) $until['monthday'], (int) $until['year']); $recur->SetUntil($until_date); } } else { $errors[] = array('field' => 'until', 'text' => 'Invalid until date'); } break; } } return $recur; }