Пример #1
0
 /**
  *
  */
 private function get_recurrence_count($event, $dtstart)
 {
     // use libkolab to compute recurring events
     if (class_exists('kolabcalendaring') && $event['_formatobj']) {
         $recurrence = new kolab_date_recurrence($event['_formatobj']);
     } else {
         // fallback to local recurrence implementation
         require_once $this->cal->home . '/lib/calendar_recurrence.php';
         $recurrence = new calendar_recurrence($this->cal, $event);
     }
     $count = 0;
     while (($next_event = $recurrence->next_instance()) && $next_event['start'] <= $dtstart && $count < 1000) {
         $count++;
     }
     return $count;
 }
Пример #2
0
 /**
  * Create instances of a recurring event
  *
  * @param array  Hash array with event properties
  * @param object DateTime Start date of the recurrence window
  * @param object DateTime End date of the recurrence window
  * @param string ID of a specific recurring event instance
  * @return array List of recurring event instances
  */
 public function get_recurring_events($event, $start, $end = null, $event_id = null)
 {
     $object = $event['_formatobj'];
     if (!$object) {
         $rec = $this->storage->get_object($event['id']);
         $object = $rec['_formatobj'];
     }
     if (!is_object($object)) {
         return array();
     }
     // determine a reasonable end date if none given
     if (!$end) {
         switch ($event['recurrence']['FREQ']) {
             case 'YEARLY':
                 $intvl = 'P100Y';
                 break;
             case 'MONTHLY':
                 $intvl = 'P20Y';
                 break;
             default:
                 $intvl = 'P10Y';
                 break;
         }
         $end = clone $event['start'];
         $end->add(new DateInterval($intvl));
     }
     // add recurrence exceptions to output
     $i = 0;
     $events = array();
     $exdates = array();
     $futuredata = array();
     if (is_array($event['recurrence']['EXCEPTIONS'])) {
         // copy the recurrence rule from the master event (to be used in the UI)
         $recurrence_rule = $event['recurrence'];
         unset($recurrence_rule['EXCEPTIONS'], $recurrence_rule['EXDATE']);
         foreach ($event['recurrence']['EXCEPTIONS'] as $exception) {
             $rec_event = $this->_to_rcube_event($exception);
             $rec_event['id'] = $event['uid'] . '-' . ++$i;
             $rec_event['recurrence_id'] = $event['uid'];
             $rec_event['recurrence'] = $recurrence_rule;
             $rec_event['_instance'] = $i;
             $rec_event['isexception'] = 1;
             $events[] = $rec_event;
             // found the specifically requested instance, exiting...
             if ($rec_event['id'] == $event_id) {
                 $this->events[$rec_event['id']] = $rec_event;
                 return $events;
             }
             // remember this exception's date
             $exdate = $rec_event['start']->format('Y-m-d');
             $exdates[$exdate] = $rec_event['id'];
             if ($rec_event['thisandfuture']) {
                 $futuredata[$exdate] = $rec_event;
             }
         }
     }
     // use libkolab to compute recurring events
     if (class_exists('kolabcalendaring')) {
         $recurrence = new kolab_date_recurrence($object);
     } else {
         // fallback to local recurrence implementation
         require_once $this->cal->home . '/lib/calendar_recurrence.php';
         $recurrence = new calendar_recurrence($this->cal, $event);
     }
     while ($next_event = $recurrence->next_instance()) {
         // skip if there's an exception at this date
         $datestr = $next_event['start']->format('Y-m-d');
         if ($exdates[$datestr]) {
             // use this event data for future recurring instances
             if ($futuredata[$datestr]) {
                 $overlay_data = $futuredata[$datestr];
             }
             continue;
         }
         // add to output if in range
         $rec_id = $event['uid'] . '-' . ++$i;
         if ($next_event['start'] <= $end && $next_event['end'] >= $start || $event_id && $rec_id == $event_id) {
             $rec_event = $this->_to_rcube_event($next_event);
             if ($overlay_data) {
                 // copy data from a 'this-and-future' exception
                 $this->_merge_event_data($rec_event, $overlay_data);
             }
             $rec_event['id'] = $rec_id;
             $rec_event['recurrence_id'] = $event['uid'];
             $rec_event['_instance'] = $i;
             unset($rec_event['_attendees']);
             $events[] = $rec_event;
             if ($rec_id == $event_id) {
                 $this->events[$rec_id] = $rec_event;
                 break;
             }
         } else {
             if ($next_event['start'] > $end) {
                 // stop loop if out of range
                 break;
             }
         }
         // avoid endless recursion loops
         if ($i > 1000) {
             break;
         }
     }
     return $events;
 }
Пример #3
0
 /**
  * Create instances of a recurring event
  *
  * @param array  Hash array with event properties
  * @param object DateTime Start date of the recurrence window
  * @param object DateTime End date of the recurrence window
  * @return array List of recurring event instances
  */
 public function get_recurring_events($event, $start, $end = null)
 {
     $events = array();
     if ($event['recurrence']) {
         // include library class
         require_once dirname(__FILE__) . '/../lib/calendar_recurrence.php';
         $rcmail = rcmail::get_instance();
         $recurrence = new calendar_recurrence($rcmail->plugins->get_plugin('calendar'), $event);
         // determine a reasonable end date if none given
         if (!$end) {
             switch ($event['recurrence']['FREQ']) {
                 case 'YEARLY':
                     $intvl = 'P100Y';
                     break;
                 case 'MONTHLY':
                     $intvl = 'P20Y';
                     break;
                 default:
                     $intvl = 'P10Y';
                     break;
             }
             $end = clone $event['start'];
             $end->add(new DateInterval($intvl));
         }
         $i = 0;
         while ($next_event = $recurrence->next_instance()) {
             $next_event['uid'] = $event['uid'] . '-' . ++$i;
             // add to output if in range
             if ($next_event['start'] <= $end && $next_event['end'] >= $start) {
                 $next_event['id'] = $next_event['uid'];
                 $next_event['recurrence_id'] = $event['uid'];
                 $next_event['_instance'] = $i;
                 $events[] = $next_event;
             } else {
                 if ($next_event['start'] > $end) {
                     // stop loop if out of range
                     break;
                 }
             }
             // avoid endless recursion loops
             if ($i > 1000) {
                 break;
             }
         }
     }
     return $events;
 }
 /**
  * Insert "fake" entries for recurring occurences of this event
  */
 private function _update_recurring($event)
 {
     if (empty($this->calendars)) {
         return;
     }
     if (!empty($event['recurrence'])) {
         $exdata = array();
         $exceptions = $this->_load_exceptions($event);
         foreach ($exceptions as $exception) {
             $exdate = substr($exception['_instance'], 0, 8);
             $exdata[$exdate] = $exception;
         }
     }
     // clear existing recurrence copies
     $this->rc->db->query("DELETE FROM " . $this->db_events . "\n       WHERE recurrence_id=?\n       AND isexception=0\n       AND calendar_id IN (" . $this->calendar_ids . ")", $event['id']);
     // create new fake entries
     if (!empty($event['recurrence'])) {
         // include library class
         require_once $this->cal->home . '/lib/calendar_recurrence.php';
         $recurrence = new calendar_recurrence($this->cal, $event);
         $count = 0;
         $event['allday'] = $event['all_day'];
         $duration = $event['start']->diff($event['end']);
         $recurrence_id_format = libcalendaring::recurrence_id_format($event);
         while ($next_start = $recurrence->next_start()) {
             $instance = $next_start->format($recurrence_id_format);
             $datestr = substr($instance, 0, 8);
             // skip exceptions
             // TODO: merge updated data from master event
             if ($exdata[$datestr]) {
                 continue;
             }
             $next_start->setTimezone($this->server_timezone);
             $next_end = clone $next_start;
             $next_end->add($duration);
             $notify_at = $this->_get_notification(array('alarms' => $event['alarms'], 'start' => $next_start, 'end' => $next_end, 'status' => $event['status']));
             $query = $this->rc->db->query(sprintf("INSERT INTO " . $this->db_events . "\n           (calendar_id, recurrence_id, created, changed, uid, instance, %s, %s, all_day, sequence, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, alarms, attendees, notifyat)\n            SELECT calendar_id, ?, %s, %s, uid, ?, ?, ?, all_day, sequence, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, alarms, attendees, ?\n            FROM  " . $this->db_events . " WHERE event_id=? AND calendar_id IN (" . $this->calendar_ids . ")", $this->rc->db->quote_identifier('start'), $this->rc->db->quote_identifier('end'), $this->rc->db->now(), $this->rc->db->now()), $event['id'], $instance, $next_start->format(self::DB_DATE_FORMAT), $next_end->format(self::DB_DATE_FORMAT), $notify_at, $event['id']);
             if (!$this->rc->db->affected_rows($query)) {
                 break;
             }
             // stop adding events for inifinite recurrence after 20 years
             if (++$count > 999 || !$recurrence->recurEnd && !$recurrence->recurCount && $next_start->format('Y') > date('Y') + 20) {
                 break;
             }
         }
         // remove all exceptions after recurrence end
         if ($next_end && !empty($exceptions)) {
             $this->rc->db->query("DELETE FROM " . $this->db_events . "\n           WHERE `recurrence_id`=?\n           AND `isexception`=1\n           AND `start` > ?\n           AND `calendar_id` IN (" . $this->calendar_ids . ")", $event['id'], $next_end->format(self::DB_DATE_FORMAT));
         }
     }
 }
Пример #5
0
 /**
  * Insert "fake" entries for recurring occurences of this event
  */
 private function _update_recurring($event)
 {
     if (empty($this->calendars)) {
         return;
     }
     // clear existing recurrence copies
     $this->rc->db->query("DELETE FROM " . $this->db_events . "\n       WHERE recurrence_id=?\n       AND calendar_id IN (" . $this->calendar_ids . ")", $event['id']);
     // create new fake entries
     if ($event['recurrence']) {
         // include library class
         require_once $this->cal->home . '/lib/calendar_recurrence.php';
         $recurrence = new calendar_recurrence($this->cal, $event);
         $count = 0;
         $duration = $event['start']->diff($event['end']);
         while ($next_start = $recurrence->next_start()) {
             $next_start->setTimezone($this->server_timezone);
             $next_end = clone $next_start;
             $next_end->add($duration);
             $notify_at = $this->_get_notification(array('alarms' => $event['alarms'], 'start' => $next_start, 'end' => $next_end, 'status' => $event['status']));
             $query = $this->rc->db->query(sprintf("INSERT INTO " . $this->db_events . "\n           (calendar_id, recurrence_id, created, changed, uid, %s, %s, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, alarms, attendees, notifyat)\n            SELECT calendar_id, ?, %s, %s, uid, ?, ?, all_day, recurrence, title, description, location, categories, url, free_busy, priority, sensitivity, status, alarms, attendees, ?\n            FROM  " . $this->db_events . " WHERE event_id=? AND calendar_id IN (" . $this->calendar_ids . ")", $this->rc->db->quote_identifier('start'), $this->rc->db->quote_identifier('end'), $this->rc->db->now(), $this->rc->db->now()), $event['id'], $next_start->format(self::DB_DATE_FORMAT), $next_end->format(self::DB_DATE_FORMAT), $notify_at, $event['id']);
             if (!$this->rc->db->affected_rows($query)) {
                 break;
             }
             // stop adding events for inifinite recurrence after 20 years
             if (++$count > 999 || !$recurrence->recurEnd && !$recurrence->recurCount && $next_start->format('Y') > date('Y') + 20) {
                 break;
             }
         }
     }
 }