function GetAdder() { $CI =& get_instance(); /// @todo make standard functions and views for recurrence interface $form_id = 'caladd_'; $length_ranges = array('summary' => array(3, 255), 'description' => array(NULL, 1 << 24 - 1)); $input = array('name' => '', 'summary' => '', 'description' => '', 'start' => strtotime('+3hour'), 'end' => strtotime('+4hour'), 'allday' => FALSE, 'time_associated' => TRUE, 'eventcategory' => -1); $summary = $CI->input->post($form_id . 'summary'); if (FALSE !== $summary) { // Get the data $failed_validation = FALSE; $input['summary'] = $summary; $input['start'] = $CI->input->post($form_id . 'start'); $input['end'] = $CI->input->post($form_id . 'end'); $input['allday'] = FALSE !== $CI->input->post($form_id . 'allday'); $input['location'] = $CI->input->post($form_id . 'location'); $input['category'] = $CI->input->post($form_id . 'category'); $input['description'] = $CI->input->post($form_id . 'description'); $input['frequency'] = $CI->input->post($form_id . 'frequency'); // Simple derived data $input['time_associated'] = !$input['allday']; $input['name'] = $input['summary']; // Validate numbers foreach (array('start', 'end') as $ts_name) { if (is_numeric($input[$ts_name])) { $input[$ts_name] = (int) $input[$ts_name]; } else { $this->messages->AddMessage('error', 'Invalid ' . $ts_name . ' timestamp.'); } } // Validate strings foreach ($length_ranges as $field => $range) { if (FALSE !== $input[$field]) { $len = strlen($input[$field]); if (NULL !== $range[0] && $len < $range[0]) { $failed_validation = TRUE; $CI->messages->AddMessage('error', 'The specified ' . $field . ' was not long enough. It must be at least ' . $range[0] . ' characters long.'); } if (NULL !== $range[1] && $len > $range[1]) { $failed_validation = TRUE; $CI->messages->AddMessage('error', 'The specified ' . $field . ' was too long. It must be at most ' . $range[1] . ' characters long.'); } } } // Validate category if (!array_key_exists($input['category'], $this->mCategories)) { var_dump($input['category']); var_dump($this->mCategories); $failed_validation = TRUE; $CI->messages->AddMessage('error', 'You did not specify a valid event category'); } else { $input['eventcategory'] = $input['category']; $input['category'] = $this->mCategories[$input['category']]['id']; } // Validate recurrence based on frequency if ('none' !== $input['frequency']) { // Read interval $input['interval'] = $CI->input->post($form_id . 'interval'); // Validate interval if (!is_numeric($input['interval']) || $input['interval'] < 1) { $failed_validation = TRUE; $CI->messages->AddMessage('error', 'You specified an invalid interval'); } else { $input['interval'] = (int) $input['interval']; } if ('daily' === $input['frequency']) { } elseif ('weekly' === $input['frequency']) { $input['onday'] = $CI->input->post($form_id . 'onday'); } elseif ('yearly' === $input['frequency']) { } } if (!$failed_validation) { $start = $input['start']; $end = $input['end']; if ($end < $start) { $CI->messages->AddMessage('error', 'You specified the end time before the start time.'); $failed_validation = TRUE; } else { if (!$input['time_associated']) { $end = strtotime('1day', $end); } $input['recur'] = new RecurrenceSet(); $input['recur']->SetStartEnd($start, $end); // daily if ('daily' === $input['frequency']) { $rrule = new CalendarRecurRule(); $rrule->SetFrequency('daily'); $rrule->SetInterval($input['interval']); $input['recur']->AddRRules($rrule); } elseif ('weekly' === $input['frequency']) { $rrule = new CalendarRecurRule(); $rrule->SetFrequency('weekly'); $rrule->SetInterval($input['interval']); static $onday_translate = array('mon' => 'MO', 'tue' => 'TU', 'wed' => 'WE', 'thu' => 'TH', 'fri' => 'FR', 'sat' => 'SA', 'sun' => 'SU'); foreach ($input['onday'] as $day => $on) { $short_day = strtoupper(substr($day, 0, 2)); if (array_key_exists($short_day, CalendarRecurRule::$sWeekdays)) { $rrule->SetByDay(CalendarRecurRule::$sWeekdays[$short_day]); } } $input['recur']->AddRRules($rrule); } elseif ('yearly' === $input['frequency']) { $rrule = new CalendarRecurRule(); $rrule->SetFrequency('yearly'); $rrule->SetInterval($input['interval']); $input['recur']->AddRRules($rrule); } try { $results = $CI->events_model->EventCreate($input); $CI->messages->AddMessage('success', 'Event created successfully.'); } catch (Exception $e) { $CI->messages->AddMessage('error', $e->getMessage()); } } } } $input['target'] = $CI->uri->uri_string(); $data = array('EventCategories' => $this->mCategories, 'AddForm' => $input); return new FramesView('calendar/simpleadd', $data); }
/** * @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; }