public function testExportRecurId()
 {
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     $nextOccurance = Calendar_Model_Rrule::computeNextOccurrence($this->_testEvent, $exceptions, $this->_testEvent->dtend);
     $exporter = new Calendar_Export_Ical();
     $ics = $exporter->eventToIcal($nextOccurance);
     // assert recurid
     $this->assertEquals(1, preg_match("/RECURRENCE-ID;TZID=Europe\\/Berlin:20101231T130000\r\n/", $ics), 'RECURRENCE-ID broken');
 }
 public function testComputeNextOccurrenceWithNegativeWhich()
 {
     $event = new Calendar_Model_Event(array('uid' => Tinebase_Record_Abstract::generateUID(), 'summary' => 'weekly', 'dtstart' => '2013-10-11 08:00:00', 'dtend' => '2013-10-11 10:00:00', 'rrule' => 'FREQ=WEEKLY;BYDAY=FR;INTERVAL=1', 'originator_tz' => 'Europe/Berlin'));
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     // NOTE: ongoing event is considered as previous/next
     $from = new Tinebase_DateTime('2013-11-01 07:59:59');
     $previousOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, $from, -1);
     $this->assertEquals('2013-10-25 08:00:00', $previousOccurrence->dtstart->toString());
     // DST switch
     $from = new Tinebase_DateTime('2013-11-08 08:59:59');
     $previousOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, $from, -1);
     $this->assertEquals('2013-11-01 09:00:00', $previousOccurrence->dtstart->toString());
 }
 /**
  * sets rrule until helper field
  *
  * @return void
  */
 public function setRruleUntil()
 {
     if (empty($this->rrule)) {
         $this->rrule_until = NULL;
     } else {
         $rrule = $this->rrule;
         if (!$this->rrule instanceof Calendar_Model_Rrule) {
             $rrule = new Calendar_Model_Rrule(array());
             $rrule->setFromString($this->rrule);
             $this->rrule = $rrule;
         }
         if (isset($rrule->count)) {
             $this->rrule_until = NULL;
             $exdates = $this->exdate;
             $this->exdate = NULL;
             $lastOccurrence = Calendar_Model_Rrule::computeNextOccurrence($this, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $this->dtend, $rrule->count - 1);
             $this->rrule_until = $lastOccurrence->dtend;
             $this->exdate = $exdates;
         } else {
             // set until to end of day in organizers timezone.
             // NOTE: this is in contrast to the iCal spec which says until should be the
             //       dtstart of the last occurence. But as the client with the name of the
             //       spec sets it to the end of the day, we do it also.
             if ($rrule->until instanceof Tinebase_DateTime && !$this->is_all_day_event) {
                 $rrule->until->setTimezone($this->originator_tz);
                 // NOTE: subSecond cause some clients send 00:00:00 for midnight
                 $rrule->until->subSecond(1)->setTime(23, 59, 59);
                 $rrule->until->setTimezone('UTC');
             }
             $this->rrule_until = $rrule->until;
         }
     }
     if ($this->rrule_until && $this->rrule_until->getTimeStamp() - $this->dtstart->getTimeStamp() < -1) {
         throw new Tinebase_Exception_Record_Validation('rrule until must not be before dtstart');
     }
 }
Esempio n. 4
0
 public function testGetRecurExceptions()
 {
     $persitentException = $this->testCreateRecurException();
     $baseEvent = $this->_controller->getRecurBaseEvent($persitentException);
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     $nextOccurance = Calendar_Model_Rrule::computeNextOccurrence($baseEvent, $exceptions, $baseEvent->dtstart);
     $this->_controller->createRecurException($nextOccurance, TRUE);
     $exceptions = $this->_controller->getRecurExceptions($persitentException, TRUE);
     $dtstarts = $exceptions->dtstart;
     $this->assertTrue(in_array($nextOccurance->dtstart, $dtstarts), 'deleted instance missing');
     $this->assertTrue(in_array($persitentException->dtstart, $dtstarts), 'exception instance missing');
 }
 /**
  * (non-PHPdoc)
  * @see Syncroton_Data_IDataCalendar::setAttendeeStatus()
  */
 public function setAttendeeStatus(Syncroton_Model_MeetingResponse $response)
 {
     $event = $instance = $this->_contentController->get($response->requestId);
     $method = 'attenderStatusUpdate';
     if ($response->instanceId instanceof DateTime) {
         $instance = $event->exdate->filter('recurid', $event->uid . '-' . $response->instanceId->format(Tinebase_Record_Abstract::ISO8601LONG))->getFirstRecord();
         if (!$instance) {
             $exceptions = $event->exdate;
             $event->exdate = $exceptions->getOriginalDtStart();
             $instance = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, new Tinebase_DateTime($response->instanceId));
         }
         $method = 'attenderStatusCreateRecurException';
     }
     $attendee = Calendar_Model_Attender::getOwnAttender($instance->attendee);
     if (!$attendee) {
         throw new Syncroton_Exception_Status_MeetingResponse("party crushing not allowed", Syncroton_Exception_Status_MeetingResponse::INVALID_REQUEST);
     }
     $attendee->status = $this->_meetingResponseAttendeeStatusMapping[$response->userResponse];
     Calendar_Controller_Event::getInstance()->{$method}($instance, $attendee, $attendee->status_authkey);
     // return id of calendar event
     return $response->requestId;
 }
 /**
  * testAcceptInvitationForRecurringEventException
  * 
  * @see 0009022: can not accept invitation to recurring event exception
  * @see 0009510: is it allowed to have no main vevent in ics?
  */
 public function testAcceptInvitationForRecurringEventException()
 {
     Tinebase_Container::getInstance()->setGrants($this->objects['initialContainer'], new Tinebase_Record_RecordSet('Tinebase_Model_Grants', array($this->_getAllCalendarGrants(), array('account_id' => 0, 'account_type' => 'anyone', Tinebase_Model_Grants::GRANT_READ => true, Tinebase_Model_Grants::GRANT_ADD => false, Tinebase_Model_Grants::GRANT_EDIT => false, Tinebase_Model_Grants::GRANT_DELETE => false, Tinebase_Model_Grants::GRANT_FREEBUSY => true, Tinebase_Model_Grants::GRANT_ADMIN => false))), true);
     $persistentEvent = Calendar_Controller_Event::getInstance()->create(new Calendar_Model_Event(array('container_id' => $this->objects['initialContainer']->getId(), 'rrule' => 'FREQ=WEEKLY;BYDAY=WE', 'dtstart' => new Tinebase_DateTime('20131016T120000'), 'dtend' => new Tinebase_DateTime('20131016T130000'), 'summary' => 'Meeting', 'attendee' => new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(array('user_id' => Tinebase_Core::getUser()->contact_id, 'user_type' => Calendar_Model_Attender::USERTYPE_USER, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'status_authkey' => 'e4546f26cb37f69baf59135e7bd379bf94bba429'))), 'uid' => '3ef8b44333aea7c01aa5a9308e2cb014807c60b3')));
     // add pwulf as attender to create exception
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     $exception = Calendar_Model_Rrule::computeNextOccurrence($persistentEvent, $exceptions, new Tinebase_DateTime('20131017T140000'));
     $exception->attendee->addRecord(new Calendar_Model_Attender(array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $this->_getPersonasContacts('pwulf')->getId())));
     $persistentException = Calendar_Controller_Event::getInstance()->createRecurException($exception);
     $persistentEvent = Calendar_Controller_Event::getInstance()->get($persistentEvent->getId());
     // pwulf tries to accept invitation
     Tinebase_Core::set(Tinebase_Core::USER, Tinebase_User::getInstance()->getFullUserByLoginName('pwulf'));
     $_SERVER['HTTP_USER_AGENT'] = 'Mac OS X/10.8.5 (12F45) CalendarAgent/57';
     // this ics only has an exdate vevent
     $vcalendarStream = self::getVCalendar(dirname(__FILE__) . '/../../Import/files/accept_exdate_invite.ics');
     $event = new Calendar_Frontend_WebDAV_Event($this->objects['initialContainer'], $persistentEvent);
     $event->put($vcalendarStream);
     $exdateWebDAVEvent = $event->getRecord()->exdate[0];
     $this->_assertCurrentUserAttender($exdateWebDAVEvent);
     $exdateCalEvent = Calendar_Controller_Event::getInstance()->get($persistentException->getId());
     $this->_assertCurrentUserAttender($exdateCalEvent);
 }
 /**
  * testSetAlarmOfRecurSeriesException
  */
 public function testSetAlarmOfRecurSeriesException()
 {
     $event = $this->_getEvent();
     $event->rrule = 'FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR;INTERVAL=1';
     $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(new Tinebase_Model_Alarm(array('minutes_before' => 30), TRUE)));
     $persistentEvent = $this->_controller->create($event);
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     $exception = Calendar_Model_Rrule::computeNextOccurrence($persistentEvent, $exceptions, new Tinebase_DateTime());
     $exception->dtstart->subHour(6);
     $exception->dtend->subHour(6);
     $persistentException = $this->_controller->createRecurException($exception);
     $baseEvent = $this->_controller->getRecurBaseEvent($persistentException);
     $this->_controller->getAlarms($baseEvent);
     $exceptions = $this->_controller->getRecurExceptions($persistentException);
     $nextOccurance = Calendar_Model_Rrule::computeNextOccurrence($baseEvent, $exceptions, Tinebase_DateTime::now());
     $nextAlarmEventStart = new Tinebase_DateTime(substr($baseEvent->alarms->getFirstRecord()->getOption('recurid'), -19));
     $this->assertTrue($nextOccurance->dtstart->equals($nextAlarmEventStart), 'next alarm got not adjusted');
     $alarmTime = clone $persistentException->dtstart;
     $alarmTime->subMinute(30);
     $this->assertTrue($alarmTime->equals($persistentException->alarms->getFirstRecord()->alarm_time), 'alarmtime of persistent exception is not correnct/set');
 }
Esempio n. 8
0
 /**
  * sets rrule until helper field
  *
  * @return void
  */
 public function setRruleUntil()
 {
     if (empty($this->rrule)) {
         $this->rrule_until = NULL;
     } else {
         $rrule = $this->rrule;
         if (!$this->rrule instanceof Calendar_Model_Rrule) {
             $rrule = new Calendar_Model_Rrule(array());
             $rrule->setFromString($this->rrule);
         }
         if (isset($rrule->count)) {
             $this->rrule_until = NULL;
             $exdates = $this->exdate;
             $this->exdate = NULL;
             $lastOccurrence = Calendar_Model_Rrule::computeNextOccurrence($this, new Tinebase_Record_RecordSet('Calendar_Model_Event'), $this->dtend, $rrule->count - 1);
             $this->rrule_until = $lastOccurrence->dtend;
             $this->exdate = $exdates;
         } else {
             $this->rrule_until = $rrule->until;
         }
     }
 }
 /**
  * event handler for group updates
  * 
  * @param Tinebase_Model_Group $_group
  * @return void
  */
 public function onUpdateGroup($_groupId)
 {
     $doContainerACLChecks = $this->doContainerACLChecks(FALSE);
     $filter = new Calendar_Model_EventFilter(array(array('field' => 'attender', 'operator' => 'equals', 'value' => array('user_type' => Calendar_Model_Attender::USERTYPE_GROUP, 'user_id' => $_groupId)), array('field' => 'period', 'operator' => 'within', 'value' => array('from' => Tinebase_DateTime::now()->get(Tinebase_Record_Abstract::ISO8601LONG), 'until' => Tinebase_DateTime::now()->addYear(100)->get(Tinebase_Record_Abstract::ISO8601LONG)))));
     $events = $this->search($filter, new Tinebase_Model_Pagination(), FALSE, FALSE);
     foreach ($events as $event) {
         try {
             if (!$event->rrule) {
                 // update non recurring futrue events
                 Calendar_Model_Attender::resolveGroupMembers($event->attendee);
                 $this->update($event);
             } else {
                 // update thisandfuture for recurring events
                 $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $this->getRecurExceptions($event), Tinebase_DateTime::now());
                 Calendar_Model_Attender::resolveGroupMembers($nextOccurrence->attendee);
                 if ($nextOccurrence->dtstart != $event->dtstart) {
                     $this->createRecurException($nextOccurrence, FALSE, TRUE);
                 } else {
                     $this->update($nextOccurrence);
                 }
             }
         } catch (Exception $e) {
             Tinebase_Core::getLogger()->NOTICE(__METHOD__ . '::' . __LINE__ . " could not update attendee");
         }
     }
     $this->doContainerACLChecks($doContainerACLChecks);
 }
Esempio n. 10
0
 /**
  * migrates given event page
  * 
  * @param array $_eventPage
  * @return void
  */
 public function _migrateEventPage($_eventPage)
 {
     foreach ($_eventPage as $egwEventData) {
         try {
             $event = $this->_getTineEventRecord($egwEventData);
             $event->attendee = $this->_getEventAttendee($egwEventData);
             if ($event->rrule) {
                 $exceptions = $this->_getRecurExceptions($egwEventData['cal_id']);
                 $exceptions->merge($this->_getRecurImplicitExceptions($egwEventData));
                 foreach ($exceptions as $exception) {
                     $exception['exdate'] = NULL;
                     $exception['rrule'] = NULL;
                     $exception->uid = $event->uid;
                     $exception->setRecurId();
                     $exdateKey = array_search($exception->dtstart, $event->exdate);
                     if ($exdateKey !== FALSE) {
                         $this->_log->debug("removing persistent exception at {$exception->dtstart} from exdate of {$event->getId()}");
                         unset($event->exdate[$exdateKey]);
                     }
                     if (count($exception->alarms == 0) && count($event->alarms > 0)) {
                         $exception->alarms = clone $event->alarms;
                     }
                     $this->_saveTineEvent($exception);
                 }
                 $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, $this->_migrationStartTime);
                 $event->alarms->setTime($nextOccurrence->dtstart);
             }
             // save baseevent
             $this->_saveTineEvent($event);
         } catch (Exception $e) {
             $this->_log->err('could not migrate event "' . $egwEventData['cal_id'] . '" cause: ' . $e->getMessage());
         }
     }
 }
Esempio n. 11
0
 /**
  * adopt alarm time to next occurance for recurring events
  *
  * @param Tinebase_Record_Abstract $_record
  * @param Tinebase_Model_Alarm $_alarm
  * @param bool $_nextBy {instance|time} set recurr alarm to next from given instance or next by current time
  * @return void
  * @throws Tinebase_Exception_InvalidArgument
  */
 public function adoptAlarmTime(Tinebase_Record_Abstract $_record, Tinebase_Model_Alarm $_alarm, $_nextBy = 'time')
 {
     if ($_record->rrule) {
         if ($_nextBy == 'time') {
             // NOTE: this also finds instances running right now
             $from = Tinebase_DateTime::now();
         } else {
             $recurid = $_alarm->getOption('recurid');
             $instanceStart = $recurid ? new Tinebase_DateTime(substr($recurid, -19)) : clone $_record->dtstart;
             $eventLength = $_record->dtstart->diff($_record->dtend);
             // make sure we hit the next instance
             $from = $instanceStart->add($eventLength)->addMinute(1);
         }
         // this would break if minutes_before > interval
         //$from->addMinute((int) $_alarm->getOption('minutes_before'));
         // compute next
         $exceptions = $this->getRecurExceptions($_record);
         $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($_record, $exceptions, $from);
         // save recurid so we know for which recurrance the alarm is for
         $_alarm->setOption('recurid', isset($nextOccurrence) ? $nextOccurrence->recurid : NULL);
         $_alarm->sent_status = $nextOccurrence ? Tinebase_Model_Alarm::STATUS_PENDING : Tinebase_Model_Alarm::STATUS_SUCCESS;
         $_alarm->sent_message = $nextOccurrence ? '' : 'Nothing to send, series is over';
         if (!$nextOccurrence) {
             return;
         }
         $eventStart = clone $nextOccurrence->dtstart;
     } else {
         $eventStart = clone $_record->dtstart;
     }
     // save minutes before / compute it for custom alarms
     $_alarm->setOption('minutes_before', $_alarm->minutes_before == Tinebase_Model_Alarm::OPTION_CUSTOM ? ($_record->dtstart->getTimestamp() - $_alarm->alarm_time->getTimestamp()) / 60 : $_alarm->minutes_before);
     $_alarm->setTime($eventStart);
 }
Esempio n. 12
0
 public function testComputeNextOccurrence()
 {
     $event = new Calendar_Model_Event(array('uid' => Tinebase_Record_Abstract::generateUID(), 'summary' => 'weekly', 'dtstart' => '2009-09-09 08:00:00', 'dtend' => '2009-09-09 10:00:00', 'rrule' => 'FREQ=WEEKLY;BYDAY=WE,FR;INTERVAL=1;UNTIL=2009-09-27 10:00:00', 'originator_tz' => 'Europe/Berlin'));
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     $from = new Tinebase_DateTime('2008-01-21 00:00:00');
     $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, $from);
     $this->assertTrue($event === $nextOccurrence, 'given event is next occurrence');
     $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, $nextOccurrence->dtstart);
     $this->assertEquals('2009-09-11 08:00:00', $nextOccurrence->dtstart->toString(Tinebase_Record_Abstract::ISO8601LONG));
     $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($event, $exceptions, $nextOccurrence->dtstart);
     $this->assertEquals('2009-09-16 08:00:00', $nextOccurrence->dtstart->toString(Tinebase_Record_Abstract::ISO8601LONG));
 }