/**
  * enforce acl restrictions to alarm options
  * 
  * @param Calendar_Model_Event $_event
  * @param Calendar_Model_Event $_currentEvent
  * @return bool true if alarms have updates
  */
 public static function enforceACL($_event, $_currentEvent = NULL)
 {
     $alarms = $_event->alarms instanceof Tinebase_Record_RecordSet ? $_event->alarms : new Tinebase_Record_RecordSet('Tinebase_Model_Alarm');
     $currentAlarms = $_currentEvent && $_currentEvent->alarms instanceof Tinebase_Record_RecordSet ? $_currentEvent->alarms : new Tinebase_Record_RecordSet('Tinebase_Model_Alarm');
     // 1. assemble attendeeSet curruser has rights for
     // 2. enforcethe rights ;-)
     if ($_currentEvent) {
         $alarms->record_id = $_currentEvent->getId();
     }
 }
 public function testRruleDiff()
 {
     $event = $event = new Calendar_Model_Event(array('dtstart' => new Tinebase_DateTime('2011-11-23 14:25:00'), 'dtend' => new Tinebase_DateTime('2011-11-23 15:25:00'), 'rrule' => 'FREQ=WEEKLY;INTERVAL=1;WKST=MO;BYDAY=TH;UNTIL=2011-12-24 15:25:00', 'summary' => 'test event', 'organizer' => Tinebase_Core::getUser()->contact_id));
     $update = clone $event;
     $update->rrule = 'FREQ=WEEKLY;INTERVAL=1;BYDAY=TH;WKST=MO;UNTIL=2011-12-24 22:59:59';
     $diff = $event->diff($update);
     $this->assertFalse(isset($diff->diff['rrule']) || array_key_exists('rrule', $diff->diff), 'parts order change:' . print_r($diff->toArray(), TRUE));
     // real change
     $update->rrule = 'FREQ=WEEKLY;INTERVAL=;BYDAY=TH;WKST=SU';
     $diff = $event->diff($update);
     $this->assertTrue(isset($diff->diff['rrule']) || array_key_exists('rrule', $diff->diff), 'real change should have diff! diff:' . print_r($diff->toArray(), TRUE));
 }
Example #3
0
 public function testIsRescheduled()
 {
     $event1 = new Calendar_Model_Event(array('dtstart' => new Tinebase_DateTime('2011-11-23 14:25:00'), 'dtend' => new Tinebase_DateTime('2011-11-23 15:25:00'), 'rrule' => 'FREQ=DAILY;INTERVAL=2'));
     $event2 = clone $event1;
     $this->assertFalse($event1->isRescheduled($event2), 'failed same');
     $event2->dtstart->addMinute(30);
     $this->assertTrue($event1->isRescheduled($event2), 'failed by dtstart');
     $event2 = clone $event1;
     $event2->dtend->addMinute(30);
     $this->assertTrue($event1->isRescheduled($event2), 'failed by dtend');
     $event2 = clone $event1;
     $event2->rrule = 'FREQ=DAILY;INTERVAL=1';
     $this->assertTrue($event1->isRescheduled($event2), 'failed by rrule');
 }
Example #4
0
 public function testSearchEvents()
 {
     $from = '2009-04-03 00:00:00';
     $until = '2009-04-10 23:59:59';
     $events = new Tinebase_Record_RecordSet('Calendar_Model_Event', array(array('dtstart' => '2009-04-02 22:00:00', 'dtend' => '2009-04-02 23:59:59', 'summary' => 'non recur event ending before search period => should _not_ be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-02 23:30:00', 'dtend' => '2009-04-03 00:30:00', 'summary' => 'non recur event ending within search period => should be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-06 12:00:00', 'dtend' => '2009-04-07 12:00:00', 'summary' => 'non recur event completly within search period => should be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-10 23:30:00', 'dtend' => '2009-04-11 00:30:00', 'summary' => 'non recur event starting within search period => should be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-11 00:00:00', 'dtend' => '2009-04-11 02:00:00', 'summary' => 'non recur event starting after search period => should _not_ be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-03-27 22:00:00', 'dtend' => '2009-03-27 23:59:59', 'rrule' => 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-02 23:59:59', 'summary' => 'recur event ending before search period => should _not_ be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'rrule_until' => '2009-04-02 23:59:59', Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-03-27 22:00:00', 'dtend' => '2009-03-27 23:59:59', 'rrule' => 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-05 23:59:59', 'summary' => 'recur event ending within search period => should be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'rrule_until' => '2009-04-05 23:59:59', Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-03 22:00:00', 'dtend' => '2009-04-03 23:59:59', 'rrule' => 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-06 23:59:59', 'summary' => 'recur event completly within search period => should be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'rrule_until' => '2009-04-06 23:59:59', Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-03 22:00:00', 'dtend' => '2009-04-03 23:59:59', 'rrule' => 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-12 23:59:59', 'summary' => 'recur event starting within search period => should be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'rrule_until' => '2009-04-12 23:59:59', Tinebase_Model_Grants::GRANT_READ => true), array('dtstart' => '2009-04-11 00:00:00', 'dtend' => '2009-04-11 02:00:00', 'rrule' => 'FREQ=DAILY;INTERVAL=1;UNTIL=2009-04-15 02:00:00', 'summary' => 'recur event starting after search period => should _not_ be found', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'rrule_until' => '2009-04-15 02:00:00', Tinebase_Model_Grants::GRANT_READ => true)));
     foreach ($events as $event) {
         $persistentEvent = $this->_backend->create($event);
         $event->attendee->cal_event_id = $persistentEvent->getId();
         foreach ($event->attendee as $attender) {
             $this->_backend->createAttendee($attender);
         }
     }
     $filter = new Calendar_Model_EventFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId()), array('field' => 'period', 'operator' => 'within', 'value' => array('from' => $from, 'until' => $until))));
     $eventsFound = $this->_backend->search($filter, new Tinebase_Model_Pagination());
     $eventsFoundIds = $eventsFound->getArrayOfIds();
     foreach ($events as $event) {
         $eventId = $event->getId();
         if (strpos($event->summary, '_not_') === false) {
             $this->assertTrue(in_array($eventId, $eventsFoundIds), 'The following event is missing in the search result :' . print_r($event->toArray(), true));
         } else {
             $this->assertFalse(in_array($eventId, $eventsFoundIds), 'The following event is in the search result, but should not be :' . print_r($event->toArray(), true));
         }
     }
     $expectedAttendee = $this->_getAttendee();
     foreach ($eventsFound as $fetchedEvent) {
         $this->_assertAttendee($expectedAttendee, $fetchedEvent->attendee);
     }
 }
 /**
  * return Calendar_Model_Event and convert contact id to model if needed
  * 
  * @return Calendar_Model_Event
  */
 public function getRecord()
 {
     if (!$this->_event instanceof Calendar_Model_Event) {
         Calendar_Controller_MSEventFacade::getInstance()->assertEventFacadeParams($this->_container);
         $this->_event = Calendar_Controller_MSEventFacade::getInstance()->get($this->_event);
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . print_r($this->_event->toArray(), true));
     }
     return $this->_event;
 }
Example #6
0
 /**
  * Computes the Recurrence set of the given event leaving out $_event->exdate and $_exceptions
  * 
  * @todo respect rrule_until!
  *
  * @param  Calendar_Model_Event         $_event
  * @param  Tinebase_Record_RecordSet    $_exceptions
  * @param  Tinebase_DateTime            $_from
  * @param  Tinebase_DateTime            $_until
  * @return Tinebase_Record_RecordSet
  * @throws Tinebase_Exception_UnexpectedValue
  */
 public static function computeRecurrenceSet($_event, $_exceptions, $_from, $_until)
 {
     if (!$_event->dtstart instanceof Tinebase_DateTime) {
         throw new Tinebase_Exception_UnexpectedValue('Event needs DateTime dtstart: ' . print_r($_event->toArray(), TRUE));
     }
     $rrule = new Calendar_Model_Rrule(NULL, TRUE);
     $rrule->setFromString($_event->rrule);
     $exceptionRecurIds = self::getExceptionsRecurIds($_event, $_exceptions);
     $recurSet = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     switch ($rrule->freq) {
         case self::FREQ_DAILY:
             self::_computeRecurDaily($_event, $rrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             break;
         case self::FREQ_WEEKLY:
             // default BYDAY clause
             if (!$rrule->byday) {
                 $rrule->byday = array_search($_event->dtstart->format('w'), self::$WEEKDAY_DIGIT_MAP);
             }
             if (!$rrule->wkst) {
                 // @TODO if organizer has an account get its locales wkst
                 $rrule->wkst = self::WDAY_MONDAY;
             }
             $weekDays = array_keys(self::$WEEKDAY_DIGIT_MAP);
             array_splice($weekDays, 0, 0, array_splice($weekDays, array_search($rrule->wkst, $weekDays)));
             $dailyrrule = clone $rrule;
             $dailyrrule->freq = self::FREQ_DAILY;
             $dailyrrule->interval = 7 * $rrule->interval;
             $eventLength = $_event->dtstart->diff($_event->dtend);
             foreach (explode(',', $rrule->byday) as $recurWeekDay) {
                 // NOTE: in weekly computation, each wdays base event is a recur instance itself
                 $baseEvent = clone $_event;
                 // NOTE: skipping must be done in organizer_tz
                 $baseEvent->dtstart->setTimezone($_event->originator_tz);
                 $direction = array_search($recurWeekDay, $weekDays) >= array_search(array_search($baseEvent->dtstart->format('w'), self::$WEEKDAY_DIGIT_MAP), $weekDays) ? +1 : -1;
                 self::skipWday($baseEvent->dtstart, $recurWeekDay, $direction, TRUE);
                 $baseEvent->dtstart->setTimezone('UTC');
                 $baseEvent->dtend = clone $baseEvent->dtstart;
                 $baseEvent->dtend->add($eventLength);
                 self::_computeRecurDaily($baseEvent, $dailyrrule, $exceptionRecurIds, $_from, $_until, $recurSet);
                 // check if base event (recur instance) needs to be added to the set
                 if ($baseEvent->dtstart->isLater($_event->dtstart) && $baseEvent->dtstart->isLater($_from) && $baseEvent->dtstart->isEarlier($_until)) {
                     if (!in_array($baseEvent->setRecurId(), $exceptionRecurIds)) {
                         self::addRecurrence($baseEvent, $recurSet);
                     }
                 }
             }
             break;
         case self::FREQ_MONTHLY:
             if ($rrule->byday) {
                 self::_computeRecurMonthlyByDay($_event, $rrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             } else {
                 self::_computeRecurMonthlyByMonthDay($_event, $rrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             }
             break;
         case self::FREQ_YEARLY:
             $yearlyrrule = clone $rrule;
             $yearlyrrule->freq = self::FREQ_MONTHLY;
             $yearlyrrule->interval = 12;
             $baseEvent = clone $_event;
             $originatorsDtstart = clone $baseEvent->dtstart;
             $originatorsDtstart->setTimezone($_event->originator_tz);
             // @TODO respect BYMONTH
             if ($rrule->bymonth && $rrule->bymonth != $originatorsDtstart->format('n')) {
                 // adopt
                 $diff = (12 + $rrule->bymonth - $originatorsDtstart->format('n')) % 12;
                 // NOTE: skipping must be done in organizer_tz
                 $baseEvent->dtstart->setTimezone($_event->originator_tz);
                 $baseEvent->dtend->setTimezone($_event->originator_tz);
                 $baseEvent->dtstart->addMonth($diff);
                 $baseEvent->dtend->addMonth($diff);
                 $baseEvent->dtstart->setTimezone('UTC');
                 $baseEvent->dtend->setTimezone('UTC');
                 // check if base event (recur instance) needs to be added to the set
                 if ($baseEvent->dtstart->isLater($_from) && $baseEvent->dtstart->isEarlier($_until)) {
                     if (!in_array($baseEvent->setRecurId(), $exceptionRecurIds)) {
                         self::addRecurrence($baseEvent, $recurSet);
                     }
                 }
             }
             if ($rrule->byday) {
                 self::_computeRecurMonthlyByDay($baseEvent, $yearlyrrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             } else {
                 self::_computeRecurMonthlyByMonthDay($baseEvent, $yearlyrrule, $exceptionRecurIds, $_from, $_until, $recurSet);
             }
             break;
     }
     return $recurSet;
 }
 /**
  * returns a simple event
  *
  * @return Calendar_Model_Event
  * @param bool $_now
  * @param bool $mute
  * @todo replace with TestCase::_getEvent
  */
 protected function _getEvent($now = FALSE, $mute = NULL)
 {
     return new Calendar_Model_Event(array('summary' => 'Sleep very long', 'dtstart' => '2012-03-25 01:00:00', 'dtend' => '2012-03-25 11:15:00', 'description' => 'Early to bed and early to rise, makes a men healthy, wealthy and wise ... not.', 'attendee' => $this->_getAttendee(), 'organizer' => Tinebase_Core::getUser()->contact_id, 'uid' => Calendar_Model_Event::generateUID()));
 }
 /**
  * get notification subject and method
  * 
  * @param Calendar_Model_Event $_event
  * @param string $_notificationLevel
  * @param string $_action
  * @param array $_updates
  * @param string $timezone
  * @param Zend_Locale $locale
  * @param Zend_Translate $translate
  * @param atring $method
  * @param Calendar_Model_Attender
  * @return string
  * @throws Tinebase_Exception_UnexpectedValue
  */
 protected function _getSubject($_event, $_notificationLevel, $_action, $_updates, $timezone, $locale, $translate, &$method, Calendar_Model_Attender $attender)
 {
     $startDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_event->dtstart, $timezone, $locale);
     $endDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_event->dtend, $timezone, $locale);
     switch ($_action) {
         case 'alarm':
             $messageSubject = sprintf($translate->_('Alarm for event "%1$s" at %2$s'), $_event->summary, $startDateString);
             break;
         case 'created':
             $messageSubject = sprintf($translate->_('Event invitation "%1$s" at %2$s'), $_event->summary, $startDateString);
             $method = Calendar_Model_iMIP::METHOD_REQUEST;
             break;
         case 'booked':
             if ($attender->user_type !== Calendar_Model_Attender::USERTYPE_RESOURCE) {
                 throw new Tinebase_Exception_UnexpectedValue('not a resource');
             }
             $resource = Calendar_Controller_Resource::getInstance()->get($attender->user_id);
             $messageSubject = sprintf($translate->_('Resource "%1$s" was booked for "%2$s" at %3$s'), $resource->name, $_event->summary, $startDateString);
             $method = Calendar_Model_iMIP::METHOD_REQUEST;
             break;
         case 'deleted':
             $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been canceled'), $_event->summary, $startDateString);
             $method = Calendar_Model_iMIP::METHOD_CANCEL;
             break;
         case 'changed':
             switch ($_notificationLevel) {
                 case self::NOTIFICATION_LEVEL_EVENT_RESCHEDULE:
                     if (isset($_updates['dtstart']) || array_key_exists('dtstart', $_updates)) {
                         $oldStartDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_updates['dtstart'], $timezone, $locale);
                         $messageSubject = sprintf($translate->_('Event "%1$s" has been rescheduled from %2$s to %3$s'), $_event->summary, $oldStartDateString, $startDateString);
                         $method = Calendar_Model_iMIP::METHOD_REQUEST;
                         break;
                     }
                     // fallthrough if dtstart didn't change
                 // fallthrough if dtstart didn't change
                 case self::NOTIFICATION_LEVEL_EVENT_UPDATE:
                     $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been updated'), $_event->summary, $startDateString);
                     $method = Calendar_Model_iMIP::METHOD_REQUEST;
                     break;
                 case self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE:
                     if (!empty($_updates['attendee']) && !empty($_updates['attendee']['toUpdate']) && count($_updates['attendee']['toUpdate']) == 1) {
                         // single attendee status update
                         $attender = $_updates['attendee']['toUpdate']->getFirstRecord();
                         switch ($attender->status) {
                             case Calendar_Model_Attender::STATUS_ACCEPTED:
                                 $messageSubject = sprintf($translate->_('%1$s accepted event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                 break;
                             case Calendar_Model_Attender::STATUS_DECLINED:
                                 $messageSubject = sprintf($translate->_('%1$s declined event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                 break;
                             case Calendar_Model_Attender::STATUS_TENTATIVE:
                                 $messageSubject = sprintf($translate->_('Tentative response from %1$s for event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                 break;
                             case Calendar_Model_Attender::STATUS_NEEDSACTION:
                                 $messageSubject = sprintf($translate->_('No response from %1$s for event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                 break;
                         }
                     } else {
                         $messageSubject = sprintf($translate->_('Attendee changes for event "%1$s" at %2$s'), $_event->summary, $startDateString);
                     }
                     // we don't send iMIP parts to organizers with an account cause event is already up to date
                     if ($_event->organizer && !$_event->resolveOrganizer()->account_id) {
                         $method = Calendar_Model_iMIP::METHOD_REPLY;
                     }
                     break;
             }
             break;
         default:
             $messageSubject = 'unknown action';
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " unknown action '{$_action}'");
             }
             break;
     }
     if ($attender->user_type === Calendar_Model_Attender::USERTYPE_RESOURCE) {
         $messageSubject = '[' . $translate->_('Resource Management') . '] ' . $messageSubject;
     }
     return $messageSubject;
 }
 /**
  * send notification to a single attender
  * 
  * @param Calendar_Model_Attender    $_attender
  * @param Calendar_Model_Event       $_event
  * @param Tinebase_Model_FullAccount $_updater
  * @param Sting                      $_action
  * @param String                     $_notificationLevel
  * @param array                      $_updates
  * @param array                      $attachs
  * @return void
  */
 public function sendNotificationToAttender($_attender, $_event, $_updater, $_action, $_notificationLevel, $_updates = NULL, $attachs = FALSE)
 {
     try {
         // find organizer account
         if ($_event->organizer && $_event->resolveOrganizer()->account_id) {
             $organizer = Tinebase_User::getInstance()->getFullUserById($_event->resolveOrganizer()->account_id);
         } else {
             // use creator as organizer
             $organizer = Tinebase_User::getInstance()->getFullUserById($_event->created_by);
         }
         // get prefered language, timezone and notification level
         $prefUser = $_attender->getUserAccountId();
         $locale = Tinebase_Translation::getLocale(Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::LOCALE, $prefUser ? $prefUser : $organizer->getId()));
         $timezone = Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::TIMEZONE, $prefUser ? $prefUser : $organizer->getId());
         $translate = Tinebase_Translation::getTranslation('Calendar', $locale);
         // check if user wants this notification
         $sendLevel = $prefUser ? Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::NOTIFICATION_LEVEL, $prefUser) : 100;
         $sendOnOwnActions = $prefUser ? Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::SEND_NOTIFICATION_OF_OWN_ACTIONS, $prefUser) : 0;
         // NOTE: organizer gets mails unless she set notificationlevel to NONE
         if ($prefUser == $_updater->getId() && !$sendOnOwnActions || $sendLevel < $_notificationLevel && ($prefUser != $organizer->getId() || $sendLevel == self::NOTIFICATION_LEVEL_NONE)) {
             return;
         }
         // get date strings
         $startDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_event->dtstart, $timezone, $locale);
         $endDateString = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_event->dtend, $timezone, $locale);
         switch ($_action) {
             case 'alarm':
                 $messageSubject = sprintf($translate->_('Alarm for event "%1$s" at %2$s'), $_event->summary, $startDateString);
                 break;
             case 'created':
                 $messageSubject = sprintf($translate->_('Event invitation "%1$s" at %2$s'), $_event->summary, $startDateString);
                 $method = Calendar_Model_iMIP::METHOD_REQUEST;
                 break;
             case 'deleted':
                 $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been canceled'), $_event->summary, $startDateString);
                 $method = Calendar_Model_iMIP::METHOD_CANCEL;
                 break;
             case 'changed':
                 switch ($_notificationLevel) {
                     case self::NOTIFICATION_LEVEL_EVENT_RESCHEDULE:
                         $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been rescheduled'), $_event->summary, $startDateString);
                         $method = Calendar_Model_iMIP::METHOD_REQUEST;
                         break;
                     case self::NOTIFICATION_LEVEL_EVENT_UPDATE:
                         $messageSubject = sprintf($translate->_('Event "%1$s" at %2$s has been updated'), $_event->summary, $startDateString);
                         $method = Calendar_Model_iMIP::METHOD_REQUEST;
                         break;
                     case self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE:
                         if (!empty($_updates['attendee']) && !empty($_updates['attendee']['toUpdate']) && count($_updates['attendee']['toUpdate']) == 1) {
                             // single attendee status update
                             $attender = $_updates['attendee']['toUpdate'][0];
                             switch ($attender->status) {
                                 case Calendar_Model_Attender::STATUS_ACCEPTED:
                                     $messageSubject = sprintf($translate->_('%1$s accepted event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                     break;
                                 case Calendar_Model_Attender::STATUS_DECLINED:
                                     $messageSubject = sprintf($translate->_('%1$s declined event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                     break;
                                 case Calendar_Model_Attender::STATUS_TENTATIVE:
                                     $messageSubject = sprintf($translate->_('Tentative response from %1$s for event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                     break;
                                 case Calendar_Model_Attender::STATUS_NEEDSACTION:
                                     $messageSubject = sprintf($translate->_('No response from %1$s for event "%2$s" at %3$s'), $attender->getName(), $_event->summary, $startDateString);
                                     break;
                             }
                         } else {
                             $messageSubject = sprintf($translate->_('Attendee changes for event "%1$s" at %2$s'), $_event->summary, $startDateString);
                         }
                         // we don't send iMIP parts to organizers with an account cause event is already up to date
                         if ($_event->organizer && !$_event->resolveOrganizer()->account_id) {
                             $method = Calendar_Model_iMIP::METHOD_REPLY;
                         }
                         break;
                 }
                 break;
             default:
                 if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                     Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " unknown action '{$_action}'");
                 }
                 break;
         }
         $view = new Zend_View();
         $view->setScriptPath(dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'views');
         $view->translate = $translate;
         $view->timezone = $timezone;
         $view->event = $_event;
         $view->updater = $_updater;
         $view->updates = $_updates;
         $messageBody = $view->render('eventNotification.php');
         if (isset($method) && version_compare(PHP_VERSION, '5.3.0', '>=')) {
             $converter = Calendar_Convert_Event_VCalendar_Factory::factory(Calendar_Convert_Event_VCalendar_Factory::CLIENT_GENERIC);
             $converter->setMethod($method);
             $vcalendar = $converter->fromTine20Model($_event);
             // in Tine 2.0 non organizers might be given the grant to update events
             // @see rfc6047 section 2.2.1 & rfc5545 section 3.2.18
             if ($method != Calendar_Model_iMIP::METHOD_REPLY && $_event->organizer !== $_updater->contact_id) {
                 foreach ($vcalendar->children() as $component) {
                     if ($component->name == 'VEVENT') {
                         if (isset($component->{'ORGANIZER'})) {
                             $component->{'ORGANIZER'}->add(new Sabre_VObject_Parameter('SEND-BY', 'mailto:' . $_updater->accountEmailAddress));
                         }
                     }
                 }
             }
             /* not yet supported
                // in Tine 2.0 status updater might not be updater
                if ($method == Calendar_Model_iMIP::METHOD_REPLY) {
                    
                }
                */
             $calendarPart = new Zend_Mime_Part($vcalendar->serialize());
             $calendarPart->charset = 'UTF-8';
             $calendarPart->type = 'text/calendar; method=' . $method;
             $calendarPart->encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE;
             $attachment = new Zend_Mime_Part($vcalendar->serialize());
             $attachment->type = 'application/ics';
             $attachment->encoding = Zend_Mime::ENCODING_QUOTEDPRINTABLE;
             $attachment->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
             $attachment->filename = 'event.ics';
             $attachments = array($attachment);
             if ($attachs) {
                 foreach ($attachs as $file) {
                     $stream = fopen($file['tempFile']['path'], 'r');
                     $part = new Zend_Mime_Part($stream);
                     $part->type = $file['tempFile']['type'];
                     $part->encoding = Zend_Mime::ENCODING_BASE64;
                     $part->disposition = Zend_Mime::DISPOSITION_ATTACHMENT;
                     $part->filename = $file['tempFile']['name'];
                     $attachments[] = $part;
                 }
             }
         } else {
             $calendarPart = null;
             $attachments = null;
         }
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " receiver: '{$_attender->getEmail()}'");
         }
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " subject: '{$messageSubject}'");
         }
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " body: {$messageBody}");
         }
         // NOTE: this is a contact as we only support users and groupmembers
         $contact = $_attender->getResolvedUser();
         $sender = $_action == 'alarm' ? $organizer : $_updater;
         Tinebase_Notification::getInstance()->send($sender, array($contact), $messageSubject, $messageBody, $calendarPart, $attachments);
     } catch (Exception $e) {
         Tinebase_Core::getLogger()->WARN(__METHOD__ . '::' . __LINE__ . " could not send notification :" . $e);
         return;
     }
 }
 /**
  * updated a recur series
  *
  * @param  array $recordData
  * @param  bool  $checkBusyConflicts
  * @noparamyet  JSONstring $returnPeriod NOT IMPLEMENTED YET
  * @return array 
  */
 public function updateRecurSeries($recordData, $checkBusyConflicts = FALSE)
 {
     $recurInstance = new Calendar_Model_Event(array(), TRUE);
     $recurInstance->setFromJsonInUsersTimezone($recordData);
     //if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(print_r($recurInstance->toArray(), true));
     $baseEvent = Calendar_Controller_Event::getInstance()->updateRecurSeries($recurInstance, $checkBusyConflicts);
     return $this->getEvent($baseEvent->getId());
 }
 /**
  * convert calendar event to Sabre\VObject\Component
  * 
  * @param  \Sabre\VObject\Component\VCalendar $vcalendar
  * @param  Calendar_Model_Event               $_event
  * @param  Calendar_Model_Event               $_mainEvent
  */
 protected function _convertCalendarModelEvent(\Sabre\VObject\Component\VCalendar $vcalendar, Calendar_Model_Event $_event, Calendar_Model_Event $_mainEvent = null)
 {
     // clone the event and change the timezone
     $event = clone $_event;
     $event->setTimezone($event->originator_tz);
     $lastModifiedDateTime = $_event->last_modified_time ? $_event->last_modified_time : $_event->creation_time;
     if (!$event->creation_time instanceof Tinebase_DateTime) {
         throw new Tinebase_Exception_Record_Validation('creation_time needed for conversion to Sabre\\VObject\\Component');
     }
     $vevent = $vcalendar->create('VEVENT', array('CREATED' => $_event->creation_time->getClone()->setTimezone('UTC'), 'LAST-MODIFIED' => $lastModifiedDateTime->getClone()->setTimezone('UTC'), 'DTSTAMP' => Tinebase_DateTime::now(), 'UID' => $event->uid));
     $vevent->add('SEQUENCE', $event->hasExternalOrganizer() ? $event->external_seq : $event->seq);
     if ($event->isRecurException()) {
         $originalDtStart = $_event->getOriginalDtStart()->setTimezone($_event->originator_tz);
         $recurrenceId = $vevent->add('RECURRENCE-ID', $originalDtStart);
         if ($_mainEvent && $_mainEvent->is_all_day_event == true) {
             $recurrenceId['VALUE'] = 'DATE';
         }
     }
     // dtstart and dtend
     $dtstart = $vevent->add('DTSTART', $_event->dtstart->getClone()->setTimezone($event->originator_tz));
     if ($event->is_all_day_event == true) {
         $dtstart['VALUE'] = 'DATE';
         // whole day events ends at 23:59:(00|59) in Tine 2.0 but 00:00 the next day in vcalendar
         $event->dtend->addSecond($event->dtend->get('s') == 59 ? 1 : 0);
         $event->dtend->addMinute($event->dtend->get('i') == 59 ? 1 : 0);
         $dtend = $vevent->add('DTEND', $event->dtend);
         $dtend['VALUE'] = 'DATE';
     } else {
         $dtend = $vevent->add('DTEND', $event->dtend);
     }
     // auto status for deleted events
     if ($event->is_deleted) {
         $event->status = Calendar_Model_Event::STATUS_CANCELED;
     }
     // event organizer
     if (!empty($event->organizer)) {
         $organizerContact = $event->resolveOrganizer();
         if ($organizerContact instanceof Addressbook_Model_Contact && !empty($organizerContact->email)) {
             $organizer = $vevent->add('ORGANIZER', 'mailto:' . $organizerContact->email, array('CN' => $organizerContact->n_fileas, 'EMAIL' => $organizerContact->email));
         }
     }
     $this->_addEventAttendee($vevent, $event);
     $optionalProperties = array('class', 'status', 'description', 'geo', 'location', 'priority', 'summary', 'transp', 'url');
     foreach ($optionalProperties as $property) {
         if (!empty($event->{$property})) {
             $vevent->add(strtoupper($property), $event->{$property});
         }
     }
     $class = $event->class == Calendar_Model_Event::CLASS_PUBLIC ? 'PUBLIC' : 'CONFIDENTIAL';
     $vcalendar->add('X-CALENDARSERVER-ACCESS', $class);
     $vevent->add('X-CALENDARSERVER-ACCESS', $class);
     // categories
     if (!isset($event->tags)) {
         $event->tags = Tinebase_Tags::getInstance()->getTagsOfRecord($event);
     }
     if (isset($event->tags) && count($event->tags) > 0) {
         $vevent->add('CATEGORIES', (array) $event->tags->name);
     }
     // repeating event properties
     if ($event->rrule) {
         if ($event->is_all_day_event == true) {
             $vevent->add('RRULE', preg_replace_callback('/UNTIL=([\\d :-]{19})(?=;?)/', function ($matches) {
                 $dtUntil = new Tinebase_DateTime($matches[1]);
                 $dtUntil->setTimezone((string) Tinebase_Core::getUserTimezone());
                 return 'UNTIL=' . $dtUntil->format('Ymd');
             }, $event->rrule));
         } else {
             $vevent->add('RRULE', preg_replace('/(UNTIL=)(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/', '$1$2$3$4T$5$6$7Z', $event->rrule));
         }
         if ($event->exdate instanceof Tinebase_Record_RecordSet) {
             $event->exdate->addIndices(array('is_deleted'));
             $deletedEvents = $event->exdate->filter('is_deleted', true);
             foreach ($deletedEvents as $deletedEvent) {
                 $dateTime = $deletedEvent->getOriginalDtStart();
                 $exdate = $vevent->add('EXDATE');
                 if ($event->is_all_day_event == true) {
                     $dateTime->setTimezone($event->originator_tz);
                     $exdate['VALUE'] = 'DATE';
                 }
                 $exdate->setValue($dateTime);
             }
         }
     }
     $ownAttendee = Calendar_Model_Attender::getOwnAttender($event->attendee);
     if ($event->alarms instanceof Tinebase_Record_RecordSet) {
         $mozLastAck = NULL;
         $mozSnooze = NULL;
         foreach ($event->alarms as $alarm) {
             $valarm = $vcalendar->create('VALARM');
             $valarm->add('ACTION', 'DISPLAY');
             $valarm->add('DESCRIPTION', $event->summary);
             if ($dtack = Calendar_Controller_Alarm::getAcknowledgeTime($alarm)) {
                 $valarm->add('ACKNOWLEDGED', $dtack->getClone()->setTimezone('UTC')->format('Ymd\\THis\\Z'));
                 $mozLastAck = $dtack > $mozLastAck ? $dtack : $mozLastAck;
             }
             if ($dtsnooze = Calendar_Controller_Alarm::getSnoozeTime($alarm)) {
                 $mozSnooze = $dtsnooze > $mozSnooze ? $dtsnooze : $mozSnooze;
             }
             if (is_numeric($alarm->minutes_before)) {
                 if ($event->dtstart == $alarm->alarm_time) {
                     $periodString = 'PT0S';
                 } else {
                     $interval = $event->dtstart->diff($alarm->alarm_time);
                     $periodString = sprintf('%sP%s%s%s%s', $interval->format('%r'), $interval->format('%d') > 0 ? $interval->format('%dD') : null, $interval->format('%h') > 0 || $interval->format('%i') > 0 ? 'T' : null, $interval->format('%h') > 0 ? $interval->format('%hH') : null, $interval->format('%i') > 0 ? $interval->format('%iM') : null);
                 }
                 # TRIGGER;VALUE=DURATION:-PT1H15M
                 $trigger = $valarm->add('TRIGGER', $periodString);
                 $trigger['VALUE'] = "DURATION";
             } else {
                 # TRIGGER;VALUE=DATE-TIME:...
                 $trigger = $valarm->add('TRIGGER', $alarm->alarm_time->getClone()->setTimezone('UTC')->format('Ymd\\THis\\Z'));
                 $trigger['VALUE'] = "DATE-TIME";
             }
             $vevent->add($valarm);
         }
         if ($mozLastAck instanceof DateTime) {
             $vevent->add('X-MOZ-LASTACK', $mozLastAck->getClone()->setTimezone('UTC'), array('VALUE' => 'DATE-TIME'));
         }
         if ($mozSnooze instanceof DateTime) {
             $vevent->add('X-MOZ-SNOOZE-TIME', $mozSnooze->getClone()->setTimezone('UTC'), array('VALUE' => 'DATE-TIME'));
         }
     }
     $baseUrl = Tinebase_Core::getHostname() . "/webdav/Calendar/records/Calendar_Model_Event/{$event->getId()}/";
     if ($event->attachments instanceof Tinebase_Record_RecordSet) {
         foreach ($event->attachments as $attachment) {
             $filename = rawurlencode($attachment->name);
             $attach = $vcalendar->createProperty('ATTACH', "{$baseUrl}{$filename}", array('MANAGED-ID' => $attachment->hash, 'FMTTYPE' => $attachment->contenttype, 'SIZE' => $attachment->size, 'FILENAME' => $filename), 'TEXT');
             $vevent->add($attach);
         }
     }
     $vcalendar->add($vevent);
 }
Example #12
0
 /**
  * returns a simple event
  *
  * @return Calendar_Model_Event
  */
 protected function _getEvent()
 {
     return new Calendar_Model_Event(array('summary' => 'Wakeup', 'dtstart' => '2009-03-25 06:00:00', 'dtend' => '2009-03-25 06:15:00', 'description' => 'Early to bed and early to rise, makes a men healthy, wealthy and wise', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_testCalendar->getId(), 'organizer' => $this->_testUserContact->getId(), 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => true));
 }
 /**
  * testUpdateEvent
  */
 public function testUpdateEvent()
 {
     $event = new Calendar_Model_Event($this->testCreateEvent(), true);
     $event->dtstart->addHour(5);
     $event->dtend->addHour(5);
     $event->description = 'are you kidding?';
     $eventData = $event->toArray();
     foreach ($eventData['attendee'] as $key => $attenderData) {
         if ($eventData['attendee'][$key]['user_id'] != $this->_getTestUserContact()->getId()) {
             unset($eventData['attendee'][$key]);
         }
     }
     $updatedEventData = $this->_uit->saveEvent($eventData);
     $this->_assertJsonEvent($eventData, $updatedEventData, 'failed to update event');
     return $updatedEventData;
 }
                        break;
                    default:
                        echo sprintf($this->translate->_('"%2$s" response from %1$s'), $attender->getName(), $attender->status) . "\n";
                        break;
                }
            }
        }
    }
    ?>

<?php 
}
echo $this->translate->_('Event details');
?>
:
<?php 
$orderedFields = array('dtstart', 'dtend', 'summary', 'location', 'description', 'rrule');
foreach ($orderedFields as $field) {
    if ($this->event->{$field}) {
        echo str_pad(Calendar_Model_Event::getTranslatedFieldName($field, $this->translate) . ':', 20) . Calendar_Model_Event::getTranslatedValue($field, $this->event->{$field}, $this->translate, $this->timezone) . "\n";
    }
}
echo $this->translate->plural('Attender', 'Attendee', count($this->event->attendee)) . ":\n";
foreach ($this->event->attendee as $attender) {
    $role = $this->translate->_($attender->getRoleString());
    $status = $this->translate->_($attender->getStatusString());
    echo "    {$attender->getName()} ({$role}, {$status}) \n";
}
?>

 /**
  * gets attendee of a given event
  *
  * @param Calendar_Model_Event $_event
  * @return Tinebase_Record_RecordSet
  */
 public function getEventAttendee(Calendar_Model_Event $_event)
 {
     $attendee = $this->_attendeeBackend->getMultipleByProperty($_event->getId(), Calendar_Backend_Sql_Attendee::FOREIGNKEY_EVENT);
     return $attendee;
 }
 /**
  * converts events to calendar objects
  * 
  * @param Calendar_Model_Event $event (from MSFacade atm.)
  */
 protected function _convertCalendarObject($event)
 {
     $eventId = $event->getId();
     $lastModified = $event->last_modified_time ? $event->last_modified_time : $event->creation_time;
     // we always use a event set to return exdates at once
     $eventSet = new Tinebase_Record_RecordSet('Calendar_Model_Event', array($event));
     if ($event->rrule) {
         foreach ($event->exdate as $exEvent) {
             if (!$exEvent->is_deleted) {
                 $eventSet->addRecord($exEvent);
                 $event->exdate->removeRecord($exEvent);
             }
         }
         // remaining exdates are fallouts
         $event->exdate = $event->exdate->getOriginalDtStart();
     }
     $exporter = new Calendar_Export_Ical();
     $ics = $exporter->eventToIcal($eventSet);
     // work arround broken exdate handling in apple ical
     // -> not neccesary at the moment this is done generally in ics export
     return array('id' => $eventId, 'uri' => $eventId, 'lastmodified' => $lastModified->getTimeStamp(), 'calendardata' => $ics);
 }
 /**
  * increases content sequence of attender display container
  * 
  * @param Calendar_Model_Attender $attender
  * @param Calendar_Model_Event $event
  * @param string $action
  */
 protected function _increaseDisplayContainerContentSequence($attender, $event, $action = Tinebase_Model_ContainerContent::ACTION_UPDATE)
 {
     if ($event->container_id === $attender->displaycontainer_id || empty($attender->displaycontainer_id)) {
         // no need to increase sequence
         return;
     }
     Tinebase_Container::getInstance()->increaseContentSequence($attender->displaycontainer_id, $action, $event->getId());
 }
 /**
  * adds feast days to feast calendar
  *
  * @param array|Tinebase_DateTime $date
  */
 protected function _createFeastDay($date)
 {
     if (!$this->_feast_calendar) {
         $this->_getFeastCalendar();
     }
     $organizer = Addressbook_Controller_Contact::getInstance()->getContactByUserId(Tinebase_Core::getUser()->getId());
     if (is_array($date)) {
         $allDay = TRUE;
         if (count($date) == 1) {
             $dtstart = $date[0]->setTimezone(Tinebase_Core::getUserTimezone())->setTime(0, 0, 0);
             $dtend = clone $dtstart;
         } else {
             $dtstart = $date[0]->setTimezone(Tinebase_Core::getUserTimezone())->setTime(0, 0, 0);
             $dtend = clone $dtstart;
             $dtend = $dtend->addDay(count($date))->subHour(5);
         }
     } else {
         $allDay = FALSE;
         $dtstart = $date->setTimezone(Tinebase_Core::getUserTimezone())->setTime(6, 0, 0);
         $dtend = clone $dtstart;
         $dtend->addMinute(15);
     }
     $event = new Calendar_Model_Event(array('summary' => 'Feast Day', 'dtstart' => $dtstart->format('Y-m-d H:i:s'), 'dtend' => $dtend->format('Y-m-d H:i:s'), 'description' => Tinebase_Record_Abstract::generateUID(10), 'container_id' => $this->_feast_calendar->getId(), 'organizer' => $organizer->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'is_all_day_event' => $allDay, 'attendee' => new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(array('user_id' => $organizer->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'status_authkey' => Tinebase_Record_Abstract::generateUID()))), Tinebase_Model_Grants::GRANT_READ => true, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => true));
     return Calendar_Controller_Event::getInstance()->create($event);
 }
 /**
  * test alarm inspection from 24.03.2012 -> 25.03.2012
  */
 public function testAdoptAlarmDSTBoundaryWithSkipping()
 {
     $event = new Calendar_Model_Event(array('summary' => 'Cleanup', 'dtstart' => '2012-01-31 07:30:00', 'dtend' => '2012-01-31 10:30:00', 'container_id' => $this->_getTestCalendar()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'rrule' => 'FREQ=WEEKLY;INTERVAL=1;WKST=MO;BYDAY=TU', 'originator_tz' => 'Europe/Berlin'));
     $alarm = new Tinebase_Model_Alarm(array('model' => 'Calendar_Model_Event', 'alarm_time' => '2012-03-26 06:30:00', 'minutes_before' => 1440, 'options' => '{"minutes_before":1440,"recurid":"a7c55ce09cea9aec4ac37d9d72789183b12cad7c-2012-03-27 06:30:00","custom":false}'));
     $this->_eventController->adoptAlarmTime($event, $alarm, 'instance');
     $this->assertEquals('2012-04-02 06:30:00', $alarm->alarm_time->toString());
 }
 public function testIsRecurException()
 {
     $event = new Calendar_Model_Event(array('uid' => '839404a34a8005d2ebd0da68b6aa922460ae945a', 'summary' => 'conference exception (late)', 'dtstart' => '2003-03-28 10:00:00', 'dtend' => '2003-03-28 12:00:00', 'originator_tz' => 'US/Pacific', 'recurid' => '839404a34a8005d2ebd0da68b6aa922460ae945a-2003-03-28 08:00:00'));
     $this->assertTrue($event->isRecurException(), 'recur exception was not detected');
     $this->assertEquals('2003-03-28 08:00:00', $event->getOriginalDtStart()->format(Tinebase_Record_Abstract::ISO8601LONG));
 }
 /**
  * create event exception
  * 
  * @param Calendar_Model_Event $event
  * @return Calendar_Model_Event
  */
 protected function _createEventException($event)
 {
     $newException = clone $event;
     $newException->id = NULL;
     $newException->base_event_id = $event->getId();
     $newException->recurid = clone $newException->dtstart;
     $newException->recurid->addDay(3);
     $newException->dtstart->addDay(3)->addHour(2);
     $newException->dtend->addDay(3)->addHour(2);
     $newException->summary = 'new exception';
     $newException->exdate = NULL;
     return $newException;
 }
 /**
  * prepares an exception instance for persitence
  * 
  * @param  Calendar_Model_Event $_baseEvent
  * @param  Calendar_Model_Event $_exception
  * @return void
  * @throws Tinebase_Exception_InvalidArgument
  */
 protected function _prepareException($_baseEvent, $_exception)
 {
     if ($_exception instanceof Tinebase_Record_RecordSet) {
         foreach ($_exception as $exception) {
             $this->_prepareException($_baseEvent, $exception);
         }
         return;
     }
     if (!$_baseEvent->uid) {
         throw new Tinebase_Exception_InvalidArgument('base event has no uid');
     }
     if ($_exception->is_deleted == false) {
         $_exception->container_id = $_baseEvent->container_id;
     }
     $_exception->uid = $_baseEvent->uid;
     $_exception->recurid = $_baseEvent->uid . '-' . $_exception->getOriginalDtStart()->format(Tinebase_Record_Abstract::ISO8601LONG);
 }
 /**
  * append organizer name and email
  *
  * @param Syncroton_Model_Event $syncrotonEvent
  * @param Calendar_Model_Event $event
  */
 protected function _addOrganizer(Syncroton_Model_Event $syncrotonEvent, Calendar_Model_Event $event)
 {
     $organizer = NULL;
     if (!empty($event->organizer)) {
         try {
             $organizer = $event->resolveOrganizer();
         } catch (Tinebase_Exception_AccessDenied $tead) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . $tead);
             }
         }
     }
     if ($organizer instanceof Addressbook_Model_Contact) {
         $organizerName = $organizer->n_fileas;
         $organizerEmail = $organizer->getPreferedEmailAddress();
     } else {
         // set the current account as organizer
         // if organizer is not set, you can not edit the event on the Motorola Milestone
         $organizerName = Tinebase_Core::getUser()->accountFullName;
         $organizerEmail = Tinebase_Core::getUser()->accountEmailAddress;
     }
     $syncrotonEvent->organizerName = $organizerName;
     if ($organizerEmail) {
         $syncrotonEvent->organizerEmail = $organizerEmail;
     }
 }
 /**
  * returns a simple event
  * 
  * @param bool $now
  * @param bool $mute
  * @return Calendar_Model_Event
  */
 protected function _getEvent($now = FALSE, $mute = NULL)
 {
     $event = new Calendar_Model_Event(array('summary' => 'Wakeup', 'dtstart' => '2009-03-25 06:00:00', 'dtend' => '2009-03-25 06:15:00', 'description' => 'Early to bed and early to rise, makes a men healthy, wealthy and wise', 'attendee' => $this->_getAttendee(), 'container_id' => $this->_getTestCalendar()->getId(), 'organizer' => $this->_getTestUserContact()->getId(), 'uid' => Calendar_Model_Event::generateUID(), 'mute' => $mute, Tinebase_Model_Grants::GRANT_READ => true, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => true));
     if ($now) {
         $event->dtstart = Tinebase_DateTime::now();
         $event->dtend = Tinebase_DateTime::now()->addMinute(15);
     }
     return $event;
 }
 /**
  * prepares an exception instance for persistence
  * 
  * @param  Calendar_Model_Event $_baseEvent
  * @param  Calendar_Model_Event $_exception
  * @return void
  * @throws Tinebase_Exception_InvalidArgument
  */
 protected function _prepareException(Calendar_Model_Event $_baseEvent, Calendar_Model_Event $_exception)
 {
     if (!$_baseEvent->uid) {
         throw new Tinebase_Exception_InvalidArgument('base event has no uid');
     }
     if ($_exception->is_deleted == false) {
         $_exception->container_id = $_baseEvent->container_id;
     }
     $_exception->uid = $_baseEvent->uid;
     $_exception->base_event_id = $_baseEvent->getId();
     $_exception->recurid = $_baseEvent->uid . '-' . $_exception->getOriginalDtStart()->format(Tinebase_Record_Abstract::ISO8601LONG);
     // NOTE: we always refetch the base event as it might be touched in the meantime
     $currBaseEvent = $this->_eventController->get($_baseEvent, null, false);
     $_exception->last_modified_time = $currBaseEvent->last_modified_time;
 }
 /**
  * eventToIcal
  * 
  * @param Tinebase_Record_RecordSet|Calendar_Model_Event $_event
  * @return qCal_Component_Vcalendar
  */
 public function eventToIcal($_event)
 {
     if ($_event instanceof Tinebase_Record_RecordSet) {
         foreach ($_event as $event) {
             $this->eventToIcal($event);
         }
         return $this->_vcalendar;
     }
     // NOTE: we deliver events in originators tz
     $_event->setTimezone($_event->originator_tz);
     if (!in_array($_event->originator_tz, $this->_attachedTimezones)) {
         $this->_vcalendar->attach(self::getVtimezone($_event->originator_tz));
         $this->_attachedTimezones[] = $_event->originator_tz;
     }
     if ($_event->is_all_day_event) {
         $dtstart = new qCal_Property_Dtstart($_event->dtstart->format('Ymd'), array('VALUE' => 'DATE'));
         $dtend = new qCal_Property_Dtend($_event->dtend->format('Ymd'), array('VALUE' => 'DATE'));
     } else {
         $dtstart = new qCal_Property_Dtstart(qCal_DateTime::factory($_event->dtstart->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
         $dtend = new qCal_Property_Dtend(qCal_DateTime::factory($_event->dtend->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
     }
     $vevent = new qCal_Component_Vevent(array('uid' => $_event->uid, 'sequence' => $_event->seq, 'summary' => $_event->summary, 'dtstart' => $dtstart, 'dtend' => $dtend));
     foreach (self::$veventMap as $icalProp => $tineField) {
         if (isset($_event[$tineField])) {
             $vevent->addProperty($icalProp, $_event->{$tineField});
         }
     }
     // rrule
     if ($_event->rrule) {
         $vevent->addProperty('rrule', preg_replace('/(UNTIL=)(\\d{4})-(\\d{2})-(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})/', '$1$2$3$4T$5$6$7Z', $_event->rrule));
         if ($exdateArray = $_event->exdate) {
             // use multiple EXDATE for the moment, as apple ical uses them
             foreach ($_event->exdate as $exdate) {
                 $exdates = new qCal_Property_Exdate(qCal_DateTime::factory($exdate->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
                 $vevent->addProperty($exdates);
             }
             //                $exdates = new qCal_Property_Exdate(qCal_DateTime::factory(array_shift($exdateArray)->format('Ymd\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz));
             //                foreach($exdateArray as $exdate) {
             //                    $exdates->addValue(qCal_DateTime::factory($exdate->format('Ymd\THis'), $_event->originator_tz));
             //                }
             //
             //                $vevent->addProperty($exdates);
         }
     }
     // recurid
     if ($_event->isRecurException()) {
         $originalDtStart = $_event->getOriginalDtStart();
         $originalDtStart->setTimezone($_event->originator_tz);
         $vevent->addProperty(new qCal_Property_RecurrenceId(qCal_DateTime::factory($originalDtStart->format('Ymd\\THis'), $_event->originator_tz), array('TZID' => $_event->originator_tz)));
     }
     // organizer
     $organizerId = $_event->organizer instanceof Addressbook_Model_Contact ? array($_event->organizer->getId()) : array($_event->organizer);
     $organizer = Addressbook_Controller_Contact::getInstance()->getMultiple($organizerId, TRUE)->getFirstRecord();
     if ($organizer && ($organizerEmail = $organizer->getPreferedEmailAddress())) {
         $vevent->addProperty(new qCal_Property_Organizer("mailto:{$organizerEmail}", array('CN' => $organizer->n_fileas)));
     }
     // attendee
     if ($_event->attendee) {
         Calendar_Model_Attender::resolveAttendee($_event->attendee, FALSE);
         foreach ($_event->attendee as $attender) {
             $attenderEmail = $attender->getEmail();
             if ($attenderEmail) {
                 $vevent->addProperty(new qCal_Property_Attendee("mailto:{$attenderEmail}", array('CN' => $attender->getName(), 'CUTYPE' => self::$cutypeMap[$attender->user_type], 'EMAIL' => $attenderEmail, 'PARTSTAT' => $attender->status, 'ROLE' => "{$attender->role}-PARTICIPANT", 'RSVP' => 'FALSE')));
             }
         }
     }
     // alarms
     if ($_event->alarms) {
         foreach ($_event->alarms as $alarm) {
             $valarm = new qCal_Component_Valarm(array('ACTION' => 'DISPLAY', 'DESCRIPTION' => $_event->summary));
             // qCal only support DURATION ;-(
             $diffSeconds = $_event->dtstart->php52compat_diff($alarm->alarm_time);
             $valarm->addProperty(new qCal_Property_Trigger($diffSeconds));
             //                if (is_numeric($alarm->minutes_before)) {
             //                    $valarm->addProperty(new qCal_Property_Trigger("-PT{$alarm->minutes_before}M"));
             //                } else {
             //                    $valarm->addProperty(new qCal_Property_Trigger(qCal_DateTime::factory($alarm->alarm_time->format('Ymd\THis'), $_event->originator_tz)), array('TZID' => $_event->originator_tz));
             //                }
             $vevent->attach($valarm);
         }
     }
     // @todo status
     $this->_vcalendar->attach($vevent);
     return $this->_vcalendar;
 }
 /**
  * returns a simple event
  *
  * @param array $_contact
  * @return Calendar_Model_Event
  */
 protected function _getEvent($_contact)
 {
     $testCalendar = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array('name' => 'PHPUnit test calendar', 'type' => Tinebase_Model_Container::TYPE_PERSONAL, 'backend' => 'Sql', 'application_id' => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId()), true));
     return new Calendar_Model_Event(array('summary' => 'Wakeup', 'dtstart' => '2009-03-25 06:00:00', 'dtend' => '2009-03-25 06:15:00', 'description' => 'Early to bed and early to rise, makes a men healthy, wealthy and wise', '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' => Tinebase_Record_Abstract::generateUID()), array('user_id' => $_contact['id'], 'user_type' => Calendar_Model_Attender::USERTYPE_USER, 'role' => Calendar_Model_Attender::ROLE_OPTIONAL, 'status_authkey' => Tinebase_Record_Abstract::generateUID()))), 'container_id' => $testCalendar->getId(), 'organizer' => Tinebase_Core::getUser()->contact_id, 'uid' => Calendar_Model_Event::generateUID(), Tinebase_Model_Grants::GRANT_READ => true, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => true));
 }
 /**
  * gets implicit exceptions due to status settings
  * 
  * @param  array                $_egwEventAttendee
  * @return Tinebase_Record_RecordSet of Calendar_Model_Event
  */
 protected function _getRecurImplicitExceptions($_egwEventData)
 {
     $implictExceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     if (empty($_egwEventData['attendee'])) {
         return $implictExceptions;
     }
     $select = $this->_egwDb->select()->from(array('attendee' => 'egw_cal_user'), 'DISTINCT(' . $this->_egwDb->quoteIdentifier('attendee.cal_recur_date') . ')')->where($this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('cal_id') . ' = ?', $_egwEventData['attendee'][0]['cal_id']))->where($this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('cal_recur_date') . ' != ?', 0));
     $groupSelect = new Tinebase_Backend_Sql_Filter_GroupSelect($select);
     foreach ($_egwEventData['attendee'] as $attender) {
         $groupSelect->orWhere($this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('attendee.cal_user_type') . ' = ?', $attender['cal_user_type']) . ' AND ' . $this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('attendee.cal_user_id') . ' = ?', $attender['cal_user_id']) . ' AND ' . $this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('attendee.cal_status') . ' NOT LIKE ?', $attender['cal_status']));
     }
     $groupSelect->appendWhere(Zend_Db_Select::SQL_AND);
     $egwExceptionDates = $this->_egwDb->fetchAll($select, NULL, Zend_Db::FETCH_ASSOC);
     if (count($egwExceptionDates) > 0) {
         $this->_log->debug(__METHOD__ . '::' . __LINE__ . ' found ' . count($egwExceptionDates) . ' implicit exceptions for event ' . $_egwEventData['attendee'][0]['cal_id']);
         //print_r($_egwEventAttendee);
     }
     if (count($egwExceptionDates) > 500) {
         $this->_log->err(__METHOD__ . '::' . __LINE__ . " egw's horizont for event " . $_egwEventData['attendee'][0]['cal_id'] . " seems to be broken. Status exceptions will not be considered/migrated");
         return $implictExceptions;
     }
     //print_r($egwExceptionDates);
     $eventDuration = $_egwEventData['cal_end'] - $_egwEventData['cal_start'];
     foreach ($egwExceptionDates as $exdate) {
         $select = $this->_egwDb->select()->from(array('attendee' => 'egw_cal_user'))->where($this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('cal_recur_date') . ' = ?', $exdate['cal_recur_date']));
         $egwExceptionEventAttendee = $this->_egwDb->fetchAll($select, NULL, Zend_Db::FETCH_ASSOC);
         $exEventData = $_egwEventData;
         $exEventData['cal_id'] = Calendar_Model_Event::generateUID();
         $exEventData['cal_start'] = $exdate['cal_recur_date'];
         $exEventData['cal_end'] = $exdate['cal_recur_date'] + $eventDuration;
         $exEventData['attendee'] = $egwExceptionEventAttendee;
         $event = $this->_getTineEventRecord($exEventData);
         $event->attendee = $this->_getEventAttendee($exEventData);
         $implictExceptions->addRecord($event);
     }
     return $implictExceptions;
 }
 /**
  * computes monthly (byday) recurring events and inserts them into given $_recurSet
  *
  * @param Calendar_Model_Event      $_event
  * @param Calendar_Model_Rrule      $_rrule
  * @param array                     $_exceptionRecurIds
  * @param Tinebase_DateTime                 $_from
  * @param Tinebase_DateTime                 $_until
  * @param Tinebase_Record_RecordSet $_recurSet
  * @return void
  */
 protected static function _computeRecurMonthlyByDay($_event, $_rrule, $_exceptionRecurIds, $_from, $_until, $_recurSet)
 {
     $eventInOrganizerTZ = clone $_event;
     $eventInOrganizerTZ->setTimezone($_event->originator_tz);
     $computationStartDateArray = self::date2array($eventInOrganizerTZ->dtstart);
     // if period contains base events dtstart, we let computation start one intervall to early to catch
     // the cases when dtstart of base event not equals the first instance. If it fits, we filter the additional
     // instance out later
     if ($eventInOrganizerTZ->dtstart->isLater($_from) && $eventInOrganizerTZ->dtstart->isEarlier($_until)) {
         $computationStartDateArray = self::addMonthIgnoringDay($computationStartDateArray, -1 * $_rrule->interval);
     }
     $computationEndDate = $_event->rrule_until instanceof DateTime && $_until->isLater($_event->rrule_until) ? $_event->rrule_until : $_until;
     // if dtstart is before $_from, we compute the offset where to start our calculations
     if ($eventInOrganizerTZ->dtstart->isEarlier($_from)) {
         $computationOffsetMonth = self::getMonthDiff($eventInOrganizerTZ->dtend, $_from);
         // NOTE: $computationOffsetMonth must be multiple of interval!
         $computationOffsetMonth = floor($computationOffsetMonth / $_rrule->interval) * $_rrule->interval;
         $computationStartDateArray = self::addMonthIgnoringDay($computationStartDateArray, $computationOffsetMonth - $_rrule->interval);
     }
     $eventLength = $eventInOrganizerTZ->dtstart->diff($eventInOrganizerTZ->dtend);
     $computationStartDateArray['day'] = 1;
     $byDayInterval = (int) substr($_rrule->byday, 0, -2);
     $byDayWeekday = substr($_rrule->byday, -2);
     if ($byDayInterval === 0 || !(isset(self::$WEEKDAY_DIGIT_MAP[$byDayWeekday]) || array_key_exists($byDayWeekday, self::$WEEKDAY_DIGIT_MAP))) {
         throw new Exception('mal formated rrule byday part: "' . $_rrule->byday . '"');
     }
     while (true) {
         $computationStartDateArray = self::addMonthIgnoringDay($computationStartDateArray, $_rrule->interval);
         $computationStartDate = self::array2date($computationStartDateArray, $eventInOrganizerTZ->originator_tz);
         $recurEvent = self::cloneEvent($eventInOrganizerTZ);
         $recurEvent->dtstart = clone $computationStartDate;
         if ($byDayInterval < 0) {
             $recurEvent->dtstart = self::array2date(self::addMonthIgnoringDay($computationStartDateArray, 1), $eventInOrganizerTZ->originator_tz);
             $recurEvent->dtstart->subDay(1);
         }
         self::skipWday($recurEvent->dtstart, $byDayWeekday, $byDayInterval, TRUE);
         // we calculate dtend from the event length, as events during a dst boundary could get dtend less than dtstart otherwise
         $recurEvent->dtend = clone $recurEvent->dtstart;
         $recurEvent->dtend->add($eventLength);
         $recurEvent->setTimezone('UTC');
         if ($computationEndDate->isEarlier($recurEvent->dtstart)) {
             break;
         }
         // skip non existing dates
         if ($computationStartDate->get('m') != $recurEvent->dtstart->get('m')) {
             continue;
         }
         // skip events ending before our period.
         // NOTE: such events could be included, cause our offset only calcs months and not seconds
         if ($_from->compare($recurEvent->dtend) >= 0) {
             continue;
         }
         // skip instances begining before the baseEvent
         if ($recurEvent->dtstart->compare($_event->dtstart) < 0) {
             continue;
         }
         // skip if event equal baseevent
         if ($_event->dtstart->equals($recurEvent->dtstart)) {
             continue;
         }
         $recurEvent->setRecurId($_event->getId());
         if (!in_array($recurEvent->recurid, $_exceptionRecurIds)) {
             self::addRecurrence($recurEvent, $_recurSet);
         }
     }
 }
Example #30
0
 /**
  * converts VEVENT to an Calendar_Model_Event
  * 
  * @param   qCal_Component $vevent
  * @return  Calendar_Model_Event
  */
 protected function _getEvent(qCal_Component $vevent)
 {
     $eventData = array();
     // timezone
     if ($vevent->hasComponent('VTIMEZONE')) {
         $tz = array_value(0, $vevent->getComponent('VTIMEZONE'));
         $eventData['originator_tz'] = array_value(0, $tz->getProperty('TZID'))->getValue();
     } else {
         $eventData['originator_tz'] = $this->_defaultTimezoneId;
     }
     foreach ($this->_eventPropertyMap as $tineName => $icalName) {
         if ($vevent->hasProperty($icalName)) {
             $icalValue = array_value(0, $vevent->getProperty($icalName));
             switch ($icalValue->getType()) {
                 case 'DATE':
                     $value = new Tinebase_DateTime($icalValue->getValue() . 'T000000', $eventData['originator_tz']);
                     // events with dtstart given as date are allday events!
                     if ($tineName == 'dtstart') {
                         $eventData['is_all_day_event'] = true;
                     }
                     if ($tineName == 'dtend') {
                         $value = $value->addSecond(-1);
                     }
                     break;
                 case 'DATE-TIME':
                     $value = new Tinebase_DateTime($icalValue->getValue(), $eventData['originator_tz']);
                 case 'TEXT':
                     $value = str_replace(array('\\,', '\\n'), array(',', "\n"), $icalValue->getValue());
                     break;
                 default:
                     $value = $icalValue->getValue();
                     break;
             }
             $eventData[$tineName] = $value;
         }
     }
     // truncate string
     if (array_key_exists('uid', $eventData) && strlen($eventData['uid']) > 40) {
         $eventData['uid'] = substr($eventData['uid'], 0, 40);
     }
     $event = new Calendar_Model_Event($eventData);
     $event->setTimezone('UTC');
     return $event;
 }