Ejemplo n.º 1
0
 protected function runselftest($default, &$arr_rrule, $expected = array(), $inf = false)
 {
     $rrule = new CalendarRecurRule($arr_rrule);
     $results = array();
     $max = mktime(0, 0, 0, 1, 1, 2020);
     if (NULL === $rrule->GetCount()) {
         $rrule->SetCount(600);
     }
     $rrule->Recur($results, $default, $max);
     if (empty($expected) || array_key_exists('debug', $rrule)) {
         echo '<pre>' . "\n\n";
         foreach ($results as $k => $result) {
             echo $k . ' => ' . $result . ', ';
             if ($k % 10 == 9) {
                 echo "\n";
             }
         }
         echo "\n\n";
         foreach ($results as $result) {
             echo date(DATE_RFC822, $result) . "\n";
         }
         echo "\n\n" . '</pre>';
         return 2;
     }
     foreach ($results as $k => $v) {
         if (!array_key_exists($k, $expected) || $expected[$k] !== $v) {
             return 1;
         }
     }
     foreach ($expected as $k => $v) {
         if (!array_key_exists($k, $results) || $results[$k] !== $v) {
             return 1;
         }
     }
     return 0;
 }
 /**
  * @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);
 }
 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);
 }
 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;
 }