protected function _addEventAttendee(Sabre_VObject_Component $_vevent, Calendar_Model_Event $_event) { if (version_compare($this->_version, '1.0b2', '>')) { parent::_addEventAttendee($_vevent, $_event); } else { // special handling for Lightning <= 1.0b2 // attendees get screwed up, if the CN contains commas Calendar_Model_Attender::resolveAttendee($_event->attendee, FALSE, $_event); foreach ($_event->attendee as $eventAttendee) { $attendeeEmail = $eventAttendee->getEmail(); if ($attendeeEmail) { $attendee = new Sabre_VObject_Property('ATTENDEE', (strpos($attendeeEmail, '@') !== false ? 'mailto:' : 'urn:uuid:') . $attendeeEmail); $attendee->add('CN', str_replace(',', null, $eventAttendee->getName())); $attendee->add('CUTYPE', Calendar_Convert_Event_VCalendar_Abstract::$cutypeMap[$eventAttendee->user_type]); $attendee->add('PARTSTAT', $eventAttendee->status); $attendee->add('ROLE', "{$eventAttendee->role}-PARTICIPANT"); $attendee->add('RSVP', 'FALSE'); if (strpos($attendeeEmail, '@') !== false) { $attendee->add('EMAIL', $attendeeEmail); } $_vevent->add($attendee); } } } }
/** * @return void */ public function testEmailsToAttendeeWithGroups() { if (Tinebase_User::getConfiguredBackend() === Tinebase_User::LDAP || Tinebase_User::getConfiguredBackend() === Tinebase_User::ACTIVEDIRECTORY) { $this->markTestSkipped('FIXME: Does not work with LDAP/AD backend'); } $event = $this->_getEvent(); $persistentEvent = Calendar_Controller_Event::getInstance()->create($event); $primaryGroup = Tinebase_Group::getInstance()->getGroupById(Tinebase_Core::getUser()->accountPrimaryGroup); $newAttendees = array(array('userType' => Calendar_Model_Attender::USERTYPE_USER, 'firstName' => $this->_originalTestUser->accountFirstName, 'lastName' => $this->_originalTestUser->accountLastName, 'partStat' => Calendar_Model_Attender::STATUS_TENTATIVE, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'email' => $this->_originalTestUser->accountEmailAddress), array('userType' => Calendar_Model_Attender::USERTYPE_GROUP, 'displayName' => $primaryGroup->name, 'partStat' => Calendar_Model_Attender::STATUS_NEEDSACTION, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'email' => '*****@*****.**')); Calendar_Model_Attender::emailsToAttendee($persistentEvent, $newAttendees, TRUE); $persistentEvent = Calendar_Controller_Event::getInstance()->update($persistentEvent); $attendees = clone $persistentEvent->attendee; Calendar_Model_Attender::resolveAttendee($attendees); $newAttendees = array(); foreach ($attendees as $attendee) { $newAttendees[] = array('userType' => $attendee->user_type == 'group' ? Calendar_Model_Attender::USERTYPE_GROUP : Calendar_Model_Attender::USERTYPE_USER, 'partStat' => Calendar_Model_Attender::STATUS_TENTATIVE, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'email' => $attendee->user_type == 'group' ? $attendee->user_id->getId() : $attendee->user_id->email, 'displayName' => $attendee->user_type == 'group' ? $attendee->user_id->name : $attendee->user_id->n_fileas); } Calendar_Model_Attender::emailsToAttendee($persistentEvent, $newAttendees, TRUE); $persistentEvent = Calendar_Controller_Event::getInstance()->update($persistentEvent); // print_r($persistentEvent->attendee->toArray()); // there must be more than 2 attendees the user, the group + the groupmembers $this->assertGreaterThan(2, count($persistentEvent->attendee)); // current account must not be a groupmember $this->assertFalse(!!Calendar_Model_Attender::getAttendee($persistentEvent->attendee, new Calendar_Model_Attender(array('user_type' => Calendar_Model_Attender::USERTYPE_GROUPMEMBER, 'user_id' => $this->_originalTestUser->contact_id))), 'found user as groupmember'); $this->assertEquals(Calendar_Model_Attender::STATUS_TENTATIVE, Calendar_Model_Attender::getOwnAttender($persistentEvent->attendee)->status); }
/** * resolve related event data: attendee, rrule and organizer * * @param Calendar_Model_Event $_record */ public static function resolveRelatedData($_record) { if (!$_record instanceof Calendar_Model_Event) { return; } Calendar_Model_Attender::resolveAttendee($_record->attendee, TRUE, $_record); self::resolveRrule($_record); self::resolveOrganizer($_record); }
/** * resolve records and prepare for export (set user timezone, ...) * * @param Tinebase_Record_RecordSet $_records */ protected function _resolveRecords(Tinebase_Record_RecordSet $_records) { parent::_resolveRecords($_records); Calendar_Model_Attender::resolveAttendee($_records->attendee, false, $_records); foreach ($_records as $record) { $attendee = $record->attendee->getName(); $record->attendee = implode('& ', $attendee); $organizer = $record->resolveOrganizer(); if ($organizer) { $record->organizer = $organizer->n_fileas; } } }
/** * resolve records and prepare for export (set user timezone, ...) * * @param Tinebase_Record_RecordSet $_records */ protected function _resolveRecords(Tinebase_Record_RecordSet $_records) { Calendar_Model_Attender::resolveAttendee($_records->attendee, false, $_records); $organizers = Addressbook_Controller_Contact::getInstance()->getMultiple(array_unique($_records->organizer), TRUE); foreach ($_records as $record) { $attendee = $record->attendee->getName(); $record->attendee = implode('& ', $attendee); $organizer = $organizers->getById($record->organizer); if ($organizer) { $record->organizer = $organizer->n_fileas; } } }
/** * @return void */ public function testEmailsToAttendeeWithGroups() { $event = $this->_getEvent(); $persistentEvent = Calendar_Controller_Event::getInstance()->create($event); $primaryGroup = Tinebase_Group::getInstance()->getGroupById(Tinebase_Core::getUser()->accountPrimaryGroup); $newAttendees = array(array('userType' => Calendar_Model_Attender::USERTYPE_USER, 'firstName' => $this->_testUser->accountFirstName, 'lastName' => $this->_testUser->accountLastName, 'partStat' => Calendar_Model_Attender::STATUS_TENTATIVE, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'email' => $this->_testUser->accountEmailAddress), array('userType' => Calendar_Model_Attender::USERTYPE_GROUP, 'displayName' => $primaryGroup->name, 'partStat' => Calendar_Model_Attender::STATUS_NEEDSACTION, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'email' => '*****@*****.**')); Calendar_Model_Attender::emailsToAttendee($persistentEvent, $newAttendees, TRUE); $persistentEvent = Calendar_Controller_Event::getInstance()->update($persistentEvent); $attendees = clone $persistentEvent->attendee; Calendar_Model_Attender::resolveAttendee($attendees); $newAttendees = array(); foreach ($attendees as $attendee) { $newAttendees[] = array('userType' => $attendee->user_type == 'group' ? Calendar_Model_Attender::USERTYPE_GROUP : Calendar_Model_Attender::USERTYPE_USER, 'partStat' => Calendar_Model_Attender::STATUS_TENTATIVE, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'email' => $attendee->user_type == 'group' ? $attendee->user_id->getId() : $attendee->user_id->email, 'displayName' => $attendee->user_type == 'group' ? $attendee->user_id->name : $attendee->user_id->n_fileas); } Calendar_Model_Attender::emailsToAttendee($persistentEvent, $newAttendees, TRUE); $persistentEvent = Calendar_Controller_Event::getInstance()->update($persistentEvent); //var_dump($persistentEvent->attendee->toArray()); // there must be more than 2 attendees the user, the group + the groupmembers $this->assertGreaterThan(2, count($persistentEvent->attendee)); }
/** * (non-PHPdoc) * @see Calendar_Convert_Event_VCalendar_Abstract::_addEventAttendee() */ protected function _addEventAttendee(\Sabre\VObject\Component\VEvent $vevent, Calendar_Model_Event $event) { if (version_compare($this->_version, '1.0b2', '>')) { parent::_addEventAttendee($vevent, $event); } else { // special handling for Lightning <= 1.0b2 // attendees get screwed up, if the CN contains commas Calendar_Model_Attender::resolveAttendee($event->attendee, FALSE, $event); foreach ($event->attendee as $eventAttendee) { $attendeeEmail = $eventAttendee->getEmail(); if ($attendeeEmail) { $parameters = array('CN' => str_replace(',', null, $eventAttendee->getName()), 'CUTYPE' => Calendar_Convert_Event_VCalendar_Abstract::$cutypeMap[$eventAttendee->user_type], 'PARTSTAT' => $eventAttendee->status, 'ROLE' => "{$eventAttendee->role}-PARTICIPANT", 'RSVP' => 'FALSE'); if (strpos($attendeeEmail, '@') !== false) { $parameters['EMAIL'] = $attendeeEmail; } $vevent->add('ATTENDEE', (strpos($attendeeEmail, '@') !== false ? 'mailto:' : 'urn:uuid:') . $attendeeEmail, $parameters); } } } }
/** * send notifications * * @param Calendar_Model_Event $_event * @param Tinebase_Model_FullAccount $_updater * @param Sting $_action * @param Calendar_Model_Event $_oldEvent * @param array $attachs * @return void */ public function doSendNotifications($_event, $_updater, $_action, $_oldEvent = NULL, $attachs = FALSE) { if (!$_event->attendee instanceof Tinebase_Record_RecordSet) { return; } // lets resolve attendee once as batch to fill cache $attendee = clone $_event->attendee; Calendar_Model_Attender::resolveAttendee($attendee); switch ($_action) { case 'alarm': foreach ($_event->attendee as $attender) { $this->sendNotificationToAttender($attender, $_event, $_updater, $_action, self::NOTIFICATION_LEVEL_NONE); } break; case 'created': foreach ($_event->attendee as $attender) { $this->sendNotificationToAttender($attender, $_event, $_updater, $_action, self::NOTIFICATION_LEVEL_INVITE_CANCEL, FALSE, $attachs); } break; case 'deleted': foreach ($_event->attendee as $attender) { $this->sendNotificationToAttender($attender, $_event, $_updater, $_action, self::NOTIFICATION_LEVEL_INVITE_CANCEL); } break; case 'changed': $attendeeMigration = $_oldEvent->attendee->getMigration($_event->attendee->getArrayOfIds()); foreach ($attendeeMigration['toCreateIds'] as $attenderId) { $attender = $_event->attendee[$_event->attendee->getIndexById($attenderId)]; $this->sendNotificationToAttender($attender, $_event, $_updater, 'created', self::NOTIFICATION_LEVEL_INVITE_CANCEL); } foreach ($attendeeMigration['toDeleteIds'] as $attenderId) { $attender = $_oldEvent->attendee[$_oldEvent->attendee->getIndexById($attenderId)]; $this->sendNotificationToAttender($attender, $_oldEvent, $_updater, 'deleted', self::NOTIFICATION_LEVEL_INVITE_CANCEL); } // NOTE: toUpdateIds are all attendee to be notified if (!empty($attendeeMigration['toUpdateIds'])) { $updates = $this->_getUpdates($_event, $_oldEvent); if (empty($updates)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " empty update, nothing to notify about"); return; } // compute change type if (count(array_intersect(array('dtstart', 'dtend'), array_keys($updates))) > 0) { $notificationLevel = self::NOTIFICATION_LEVEL_EVENT_RESCHEDULE; } else { if (count(array_diff(array_keys($updates), array('attendee'))) > 0) { $notificationLevel = self::NOTIFICATION_LEVEL_EVENT_UPDATE; } else { $notificationLevel = self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE; } } // send notifications foreach ($attendeeMigration['toUpdateIds'] as $attenderId) { $attender = $_event->attendee[$_event->attendee->getIndexById($attenderId)]; $this->sendNotificationToAttender($attender, $_event, $_updater, 'changed', $notificationLevel, $updates); } } break; default: if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " unknown action '{$_action}'"); } break; } // SEND REPLY/COUNTER to external organizer if ($_event->organizer && !$_event->resolveOrganizer()->account_id && count($_event->attendee) == 1) { $updates = array('attendee' => array('toUpdate' => array($_event->attendee->getFirstRecord()))); $organizer = new Calendar_Model_Attender(array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $_event->resolveOrganizer())); $this->sendNotificationToAttender($organizer, $_event, $_updater, 'changed', self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE, $updates); } }
/** * find existing event by uid * * @param $_iMIP * @param bool $_refetch * @param bool $_getDeleted * @return NULL|Tinebase_Record_Abstract */ public function getExistingEvent($_iMIP, $_refetch = FALSE, $_getDeleted = FALSE) { if ($_refetch || !$_iMIP->existing_event instanceof Calendar_Model_Event) { $iMIPEvent = $_iMIP->getEvent(); $filters = new Calendar_Model_EventFilter(array(array('field' => 'uid', 'operator' => 'equals', 'value' => $iMIPEvent->uid))); if ($_getDeleted) { $deletedFilter = new Tinebase_Model_Filter_Bool('is_deleted', 'equals', Tinebase_Model_Filter_Bool::VALUE_NOTSET); $filters->addFilter($deletedFilter); } $events = Calendar_Controller_MSEventFacade::getInstance()->search($filters); // NOTE: cancelled attendees from ext. organizers don't have read grant // find a better way to check grants if (!$_getDeleted) { $events = $events->filter(Tinebase_Model_Grants::GRANT_READ, TRUE); } $event = $events->getFirstRecord(); Calendar_Model_Attender::resolveAttendee($event['attendee']); $_iMIP->existing_event = $event; } return $_iMIP->existing_event; }
/** * send notifications * * @param Calendar_Model_Event $_event * @param Tinebase_Model_FullAccount $_updater * @param Sting $_action * @param Calendar_Model_Event $_oldEvent * @param Tinebase_Model_Alarm $_alarm * @return void */ public function doSendNotifications($_event, $_updater, $_action, $_oldEvent = NULL, $_alarm = NULL) { // we only send notifications to attendee if (!$_event->attendee instanceof Tinebase_Record_RecordSet) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Event has no attendee"); } return; } if ($_event->dtend === NULL) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " " . print_r($_event->toArray(), TRUE)); } throw new Tinebase_Exception_UnexpectedValue('no dtend set in event'); } if (Tinebase_DateTime::now()->subHour(1)->isLater($_event->dtend)) { if ($_action == 'alarm' || !($_event->isRecurException() || $_event->rrule)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skip notifications to past events"); } return; } } $notificationPeriodConfig = Calendar_Config::getInstance()->get(Calendar_Config::MAX_NOTIFICATION_PERIOD_FROM); if (Tinebase_DateTime::now()->subWeek($notificationPeriodConfig)->isLater($_event->dtend)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skip notifications to past events (MAX_NOTIFICATION_PERIOD_FROM: " . $notificationPeriodConfig . " week(s))"); } return; } // lets resolve attendee once as batch to fill cache $attendee = clone $_event->attendee; Calendar_Model_Attender::resolveAttendee($attendee); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " " . print_r($_event->toArray(), true)); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Notification action: " . $_action); } switch ($_action) { case 'alarm': foreach ($_event->attendee as $attender) { if (Calendar_Model_Attender::isAlarmForAttendee($attender, $_alarm)) { $this->sendNotificationToAttender($attender, $_event, $_updater, $_action, self::NOTIFICATION_LEVEL_NONE); } } break; case 'booked': case 'created': case 'deleted': foreach ($_event->attendee as $attender) { $this->sendNotificationToAttender($attender, $_event, $_updater, $_action, self::NOTIFICATION_LEVEL_INVITE_CANCEL); } break; case 'changed': $attendeeMigration = Calendar_Model_Attender::getMigration($_oldEvent->attendee, $_event->attendee); foreach ($attendeeMigration['toCreate'] as $attender) { $this->sendNotificationToAttender($attender, $_event, $_updater, 'created', self::NOTIFICATION_LEVEL_INVITE_CANCEL); } foreach ($attendeeMigration['toDelete'] as $attender) { $this->sendNotificationToAttender($attender, $_oldEvent, $_updater, 'deleted', self::NOTIFICATION_LEVEL_INVITE_CANCEL); } // NOTE: toUpdate are all attendee to be notified if (count($attendeeMigration['toUpdate']) > 0) { $updates = $this->_getUpdates($_event, $_oldEvent); if (empty($updates)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " empty update, nothing to notify about"); return; } // compute change type if (count(array_intersect(array('dtstart', 'dtend'), array_keys($updates))) > 0) { $notificationLevel = self::NOTIFICATION_LEVEL_EVENT_RESCHEDULE; } else { if (count(array_diff(array_keys($updates), array('attendee'))) > 0) { $notificationLevel = self::NOTIFICATION_LEVEL_EVENT_UPDATE; } else { $notificationLevel = self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE; } } // send notifications foreach ($attendeeMigration['toUpdate'] as $attender) { $this->sendNotificationToAttender($attender, $_event, $_updater, 'changed', $notificationLevel, $updates); } } break; default: if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " unknown action '{$_action}'"); } break; } // SEND REPLY/COUNTER to external organizer if ($_event->organizer && !$_event->resolveOrganizer()->account_id && count($_event->attendee) == 1) { $updates = array('attendee' => array('toUpdate' => $_event->attendee)); $organizer = new Calendar_Model_Attender(array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $_event->resolveOrganizer())); $this->sendNotificationToAttender($organizer, $_event, $_updater, 'changed', self::NOTIFICATION_LEVEL_ATTENDEE_STATUS_UPDATE, $updates); } }
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; }
/** * converts Tinebase_Record_RecordSet to external format * * @param Tinebase_Record_RecordSet $_records * @param Tinebase_Model_Filter_FilterGroup $_filter * @param Tinebase_Model_Pagination $_pagination * * @return mixed */ public function fromTine20RecordSet(Tinebase_Record_RecordSet $_records = NULL, $_filter = NULL, $_pagination = NULL) { if (count($_records) == 0) { return array(); } Tinebase_Notes::getInstance()->getMultipleNotesOfRecords($_records); Tinebase_Tags::getInstance()->getMultipleTagsOfRecords($_records); if (Tinebase_Core::isFilesystemAvailable()) { Tinebase_FileSystem_RecordAttachments::getInstance()->getMultipleAttachmentsOfRecords($_records); } Calendar_Model_Attender::resolveAttendee($_records->attendee, TRUE, $_records); Calendar_Convert_Event_Json::resolveRrule($_records); Calendar_Controller_Event::getInstance()->getAlarms($_records); Calendar_Convert_Event_Json::resolveGrantsOfExternalOrganizers($_records); Calendar_Model_Rrule::mergeAndRemoveNonMatchingRecurrences($_records, $_filter); $_records->sortByPagination($_pagination); Tinebase_Frontend_Json_Abstract::resolveContainersAndTags($_records, array('container_id')); $_records->setTimezone(Tinebase_Core::getUserTimezone()); $_records->convertDates = true; $eventsData = $_records->toArray(); foreach ($eventsData as $idx => $eventData) { if (!(isset($eventData[Tinebase_Model_Grants::GRANT_READ]) || array_key_exists(Tinebase_Model_Grants::GRANT_READ, $eventData)) || !$eventData[Tinebase_Model_Grants::GRANT_READ]) { $eventsData[$idx] = array_intersect_key($eventsData[$idx], array_flip(array('id', 'dtstart', 'dtend', 'transp', 'is_all_day_event'))); } } return $eventsData; }
/** * append event data to xml element * * @todo handle BusyStatus * @todo handle TimeZone data * * @param DOMElement $_domParrent the parrent xml node * @param string $_folderId the local folder id * @param boolean $_withBody retrieve body of entry */ public function appendXML(DOMElement $_domParrent, $_collectionData, $_serverId) { $data = $_serverId instanceof Tinebase_Record_Abstract ? $_serverId : $this->_contentController->get($_serverId); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " calendar data " . print_r($data->toArray(), true)); } // add calendar namespace $_domParrent->ownerDocument->documentElement->setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:Calendar', 'uri:Calendar'); foreach ($this->_mapping as $key => $value) { if (!empty($data->{$value}) || $data->{$value} == '0') { $nodeContent = null; switch ($value) { case 'dtend': if ($data->{$value} instanceof DateTime) { if ($data->is_all_day_event == true) { // whole day events ends at 23:59:59 in Tine 2.0 but 00:00 the next day in AS $dtend = clone $data->dtend; $dtend->addSecond($dtend->get('s') == 59 ? 1 : 0); $dtend->addMinute($dtend->get('i') == 59 ? 1 : 0); $nodeContent = $dtend->format('Ymd\\THis') . 'Z'; } else { $nodeContent = $data->dtend->format('Ymd\\THis') . 'Z'; } } break; case 'dtstart': if ($data->{$value} instanceof DateTime) { $nodeContent = $data->{$value}->format('Ymd\\THis') . 'Z'; } break; default: $nodeContent = $data->{$value}; break; } // skip empty elements if ($nodeContent === null || $nodeContent == '') { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Value for {$key} is empty. Skip element."); continue; } // strip off any non printable control characters if (!ctype_print($nodeContent)) { $nodeContent = $this->removeControlChars($nodeContent); } $node = $_domParrent->ownerDocument->createElementNS('uri:Calendar', $key); $node->appendChild($_domParrent->ownerDocument->createTextNode($nodeContent)); $_domParrent->appendChild($node); } } if (!empty($data->description)) { if (version_compare($this->_device->acsversion, '12.0', '>=') === true) { $body = $_domParrent->appendChild(new DOMElement('Body', null, 'uri:AirSyncBase')); $body->appendChild(new DOMElement('Type', 1, 'uri:AirSyncBase')); // create a new DOMElement ... $dataTag = new DOMElement('Data', null, 'uri:AirSyncBase'); // ... append it to parent node aka append it to the document ... $body->appendChild($dataTag); // ... and now add the content (DomText takes care of special chars) $dataTag->appendChild(new DOMText($data->description)); } else { // create a new DOMElement ... $node = new DOMElement('Body', null, 'uri:Calendar'); // ... append it to parent node aka append it to the document ... $_domParrent->appendChild($node); // ... and now add the content (DomText takes care of special chars) $node->appendChild(new DOMText($data->description)); } } if (!empty($data->alarms)) { $alarm = $data->alarms->getFirstRecord(); if ($alarm instanceof Tinebase_Model_Alarm) { // NOTE: option minutes_before is always calculated by Calendar_Controller_Event::_inspectAlarmSet $minutesBefore = (int) $alarm->getOption('minutes_before'); if ($minutesBefore >= 0) { $_domParrent->appendChild(new DOMElement('Reminder', $minutesBefore, 'uri:Calendar')); } } } if (!empty($data->rrule)) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " calendar rrule " . $data->rrule); } $rrule = Calendar_Model_Rrule::getRruleFromString($data->rrule); $recurrence = $_domParrent->appendChild(new DOMElement('Recurrence', null, 'uri:Calendar')); // required fields switch ($rrule->freq) { case Calendar_Model_Rrule::FREQ_DAILY: $recurrence->appendChild(new DOMElement('Type', self::RECUR_TYPE_DAILY, 'uri:Calendar')); break; case Calendar_Model_Rrule::FREQ_WEEKLY: $recurrence->appendChild(new DOMElement('Type', self::RECUR_TYPE_WEEKLY, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('DayOfWeek', $this->_convertDayToBitMask($rrule->byday), 'uri:Calendar')); break; case Calendar_Model_Rrule::FREQ_MONTHLY: if (!empty($rrule->bymonthday)) { $recurrence->appendChild(new DOMElement('Type', self::RECUR_TYPE_MONTHLY, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('DayOfMonth', $rrule->bymonthday, 'uri:Calendar')); } else { $weekOfMonth = (int) substr($rrule->byday, 0, -2); $weekOfMonth = $weekOfMonth == -1 ? 5 : $weekOfMonth; $dayOfWeek = substr($rrule->byday, -2); $recurrence->appendChild(new DOMElement('Type', self::RECUR_TYPE_MONTHLY_DAYN, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('WeekOfMonth', $weekOfMonth, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('DayOfWeek', $this->_convertDayToBitMask($dayOfWeek), 'uri:Calendar')); } break; case Calendar_Model_Rrule::FREQ_YEARLY: if (!empty($rrule->bymonthday)) { $recurrence->appendChild(new DOMElement('Type', self::RECUR_TYPE_YEARLY, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('DayOfMonth', $rrule->bymonthday, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('MonthOfYear', $rrule->bymonth, 'uri:Calendar')); } else { $weekOfMonth = (int) substr($rrule->byday, 0, -2); $weekOfMonth = $weekOfMonth == -1 ? 5 : $weekOfMonth; $dayOfWeek = substr($rrule->byday, -2); $recurrence->appendChild(new DOMElement('Type', self::RECUR_TYPE_YEARLY_DAYN, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('WeekOfMonth', $weekOfMonth, 'uri:Calendar')); $recurrence->appendChild(new DOMElement('DayOfWeek', $this->_convertDayToBitMask($dayOfWeek), 'uri:Calendar')); $recurrence->appendChild(new DOMElement('MonthOfYear', $rrule->bymonth, 'uri:Calendar')); } break; } // required field $recurrence->appendChild(new DOMElement('Interval', $rrule->interval, 'uri:Calendar')); if ($rrule->until instanceof DateTime) { $recurrence->appendChild(new DOMElement('Until', $rrule->until->format('Ymd\\THis') . 'Z', 'uri:Calendar')); } // handle exceptions of repeating events if ($data->exdate instanceof Tinebase_Record_RecordSet && $data->exdate->count() > 0) { $exceptionsTag = $_domParrent->appendChild(new DOMElement('Exceptions', null, 'uri:Calendar')); foreach ($data->exdate as $exception) { $exceptionTag = $exceptionsTag->appendChild(new DOMElement('Exception', null, 'uri:Calendar')); $exceptionTag->appendChild(new DOMElement('Deleted', (int) $exception->is_deleted, 'uri:Calendar')); $exceptionTag->appendChild(new DOMElement('ExceptionStartTime', $exception->getOriginalDtStart()->format('Ymd\\THis') . 'Z', 'uri:Calendar')); if ((int) $exception->is_deleted === 0) { $this->appendXML($exceptionTag, $_collectionData, $exception); } } } } if (count($data->attendee) > 0) { // fill attendee cache Calendar_Model_Attender::resolveAttendee($data->attendee, FALSE); $attendees = $_domParrent->ownerDocument->createElementNS('uri:Calendar', 'Attendees'); foreach ($data->attendee as $attenderObject) { $attendee = $attendees->appendChild(new DOMElement('Attendee', null, 'uri:Calendar')); $attendee->appendChild(new DOMElement('Name', $attenderObject->getName(), 'uri:Calendar')); $attendee->appendChild(new DOMElement('Email', $attenderObject->getEmail(), 'uri:Calendar')); if (version_compare($this->_device->acsversion, '12.0', '>=') === true) { $acsType = array_search($attenderObject->role, $this->_attendeeTypeMapping); $attendee->appendChild(new DOMElement('AttendeeType', $acsType ? $acsType : self::ATTENDEE_TYPE_REQUIRED, 'uri:Calendar')); $acsStatus = array_search($attenderObject->status, $this->_attendeeStatusMapping); $attendee->appendChild(new DOMElement('AttendeeStatus', $acsStatus ? $acsStatus : self::ATTENDEE_STATUS_UNKNOWN, 'uri:Calendar')); } } if ($attendees->hasChildNodes()) { $_domParrent->appendChild($attendees); } // set own status if (($ownAttendee = Calendar_Model_Attender::getOwnAttender($data->attendee)) !== null && ($busyType = array_search($ownAttendee->status, $this->_busyStatusMapping)) !== false) { $_domParrent->appendChild(new DOMElement('BusyStatus', $busyType, 'uri:Calendar')); } } $timeZoneConverter = ActiveSync_TimezoneConverter::getInstance(Tinebase_Core::getLogger(), Tinebase_Core::get(Tinebase_Core::CACHE)); $_domParrent->appendChild(new DOMElement('Timezone', $timeZoneConverter->encodeTimezone(Tinebase_Core::get(Tinebase_Core::USERTIMEZONE)), 'uri:Calendar')); $_domParrent->appendChild(new DOMElement('MeetingStatus', 1, 'uri:Calendar')); $_domParrent->appendChild(new DOMElement('Sensitivity', 0, 'uri:Calendar')); $_domParrent->appendChild(new DOMElement('DtStamp', $data->creation_time->format('Ymd\\THis') . 'Z', 'uri:Calendar')); $_domParrent->appendChild(new DOMElement('UID', $data->uid, 'uri:Calendar')); if (!empty($data->organizer)) { try { $contact = Addressbook_Controller_Contact::getInstance()->get($data->organizer); $_domParrent->appendChild(new DOMElement('OrganizerName', $contact->n_fileas, 'uri:Calendar')); $_domParrent->appendChild(new DOMElement('OrganizerEmail', $contact->email, 'uri:Calendar')); } catch (Tinebase_Exception_AccessDenied $e) { // set the current account as organizer // if organizer is not set, you can not edit the event on the Motorola Milestone $_domParrent->appendChild(new DOMElement('OrganizerName', Tinebase_Core::getUser()->accountFullName, 'uri:Calendar')); if (isset(Tinebase_Core::getUser()->accountEmailAddress)) { $_domParrent->appendChild(new DOMElement('OrganizerEmail', Tinebase_Core::getUser()->accountEmailAddress, 'uri:Calendar')); } } } else { // set the current account as organizer // if organizer is not set, you can not edit the event on the Motorola Milestone $_domParrent->appendChild(new DOMElement('OrganizerName', Tinebase_Core::getUser()->accountFullName, 'uri:Calendar')); if (isset(Tinebase_Core::getUser()->accountEmailAddress)) { $_domParrent->appendChild(new DOMElement('OrganizerEmail', Tinebase_Core::getUser()->accountEmailAddress, 'uri:Calendar')); } } if (isset($data->tags) && count($data->tags) > 0) { $categories = $_domParrent->appendChild(new DOMElement('Categories', null, 'uri:Calendar')); foreach ($data->tags as $tag) { $categories->appendChild(new DOMElement('Category', $tag, 'uri:Calendar')); } } }
/** * checks if all attendee of given event are not busy for given event * * @param Calendar_Model_Event $_event * @return void * @throws Calendar_Exception_AttendeeBusy */ public function checkBusyConflicts($_event) { $ignoreUIDs = !empty($_event->uid) ? array($_event->uid) : array(); if ($_event->transp == Calendar_Model_Event::TRANSP_TRANSP || count($_event->attendee) < 1) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skipping free/busy check because event is transparent or has no attendee"); } return; } $periods = $this->getBlockingPeriods($_event, array('from' => $_event->dtstart, 'until' => $_event->dtstart->getClone()->addMonth(2))); $fbInfo = $this->getFreeBusyInfo($periods, $_event->attendee, $ignoreUIDs); if (count($fbInfo) > 0) { $busyException = new Calendar_Exception_AttendeeBusy(); $busyException->setFreeBusyInfo($fbInfo); Calendar_Model_Attender::resolveAttendee($_event->attendee, false); $busyException->setEvent($_event); throw $busyException; } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Free/busy check: no conflict found"); } }
/** * add event attendee to VEVENT object * * @param \Sabre\VObject\Component\VEvent $vevent * @param Calendar_Model_Event $event */ protected function _addEventAttendee(\Sabre\VObject\Component\VEvent $vevent, Calendar_Model_Event $event) { if (empty($event->attendee)) { return; } Calendar_Model_Attender::resolveAttendee($event->attendee, FALSE, $event); foreach ($event->attendee as $eventAttendee) { $attendeeEmail = $eventAttendee->getEmail(); $parameters = array('CN' => $eventAttendee->getName(), 'CUTYPE' => Calendar_Convert_Event_VCalendar_Abstract::$cutypeMap[$eventAttendee->user_type], 'PARTSTAT' => $eventAttendee->status, 'ROLE' => "{$eventAttendee->role}-PARTICIPANT", 'RSVP' => 'FALSE'); if (strpos($attendeeEmail, '@') !== false) { $parameters['EMAIL'] = $attendeeEmail; } $vevent->add('ATTENDEE', (strpos($attendeeEmail, '@') !== false ? 'mailto:' : 'urn:uuid:') . $attendeeEmail, $parameters); } }
/** * returns multiple records prepared for json transport * * @param Tinebase_Record_RecordSet $_records Tinebase_Record_Abstract * @param Tinebase_Model_Filter_FilterGroup $_filter * @param Tinebase_Model_Pagination $_pagination needed for sorting * @return array data * * @todo perhaps we need to resolveContainerTagsUsers() before mergeAndRemoveNonMatchingRecurrences(), but i'm not sure about that * @todo use Calendar_Convert_Event_Json */ protected function _multipleRecordsToJson(Tinebase_Record_RecordSet $_records, $_filter = NULL, $_pagination = NULL) { if ($_records->getRecordClassName() == 'Calendar_Model_Event') { if (is_null($_filter)) { throw new Tinebase_Exception_InvalidArgument('Required argument $_filter is missing'); } Tinebase_Notes::getInstance()->getMultipleNotesOfRecords($_records); Calendar_Model_Attender::resolveAttendee($_records->attendee, TRUE, $_records); Calendar_Convert_Event_Json::resolveOrganizer($_records); Calendar_Convert_Event_Json::resolveRrule($_records); Calendar_Controller_Event::getInstance()->getAlarms($_records); Calendar_Model_Rrule::mergeAndRemoveNonMatchingRecurrences($_records, $_filter); $_records->sortByPagination($_pagination); $eventsData = parent::_multipleRecordsToJson($_records); foreach ($eventsData as $eventData) { if (!array_key_exists(Tinebase_Model_Grants::GRANT_READ, $eventData) || !$eventData[Tinebase_Model_Grants::GRANT_READ]) { $eventData['notes'] = array(); $eventData['tags'] = array(); } } return $eventsData; } return parent::_multipleRecordsToJson($_records); }
/** * (non-PHPdoc) * @see ActiveSync_Frontend_Abstract::toSyncrotonModel() * @todo handle BusyStatus */ public function toSyncrotonModel($entry, array $options = array()) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " calendar data " . print_r($entry->toArray(), true)); } $syncrotonEvent = new Syncroton_Model_Event(); foreach ($this->_mapping as $syncrotonProperty => $tine20Property) { if (empty($entry->{$tine20Property}) && $entry->{$tine20Property} != '0' || count($entry->{$tine20Property}) === 0) { continue; } switch ($tine20Property) { case 'alarms': $entry->{$tine20Property}->sort('alarm_time'); $alarm = $entry->alarms->getFirstRecord(); if ($alarm instanceof Tinebase_Model_Alarm) { // NOTE: option minutes_before is always calculated by Calendar_Controller_Event::_inspectAlarmSet $minutesBefore = (int) $alarm->getOption('minutes_before'); // avoid negative alarms which may break phones if ($minutesBefore >= 0) { $syncrotonEvent->{$syncrotonProperty} = $minutesBefore; } } break; case 'attendee': if ($this->_device->devicetype === Syncroton_Model_Device::TYPE_IPHONE && $entry->container_id !== $this->_getDefaultContainerId()) { continue; } // fill attendee cache Calendar_Model_Attender::resolveAttendee($entry->{$tine20Property}, FALSE); $attendees = array(); foreach ($entry->{$tine20Property} as $attenderObject) { $attendee = new Syncroton_Model_EventAttendee(); $attendee->name = $attenderObject->getName(); $attendee->email = $attenderObject->getEmail(); $acsType = array_search($attenderObject->role, $this->_attendeeTypeMapping); $attendee->attendeeType = $acsType ? $acsType : Syncroton_Model_EventAttendee::ATTENDEE_TYPE_REQUIRED; $acsStatus = array_search($attenderObject->status, $this->_attendeeStatusMapping); $attendee->attendeeStatus = $acsStatus ? $acsStatus : Syncroton_Model_EventAttendee::ATTENDEE_STATUS_UNKNOWN; $attendees[] = $attendee; } $syncrotonEvent->{$syncrotonProperty} = $attendees; // set own status if (($ownAttendee = Calendar_Model_Attender::getOwnAttender($entry->attendee)) !== null && ($busyType = array_search($ownAttendee->status, $this->_busyStatusMapping)) !== false) { $syncrotonEvent->busyStatus = $busyType; } break; case 'class': $syncrotonEvent->{$syncrotonProperty} = $entry->{$tine20Property} == Calendar_Model_Event::CLASS_PRIVATE ? 2 : 0; break; case 'description': $syncrotonEvent->{$syncrotonProperty} = new Syncroton_Model_EmailBody(array('type' => Syncroton_Model_EmailBody::TYPE_PLAINTEXT, 'data' => $entry->{$tine20Property})); break; case 'dtend': if ($entry->{$tine20Property} instanceof DateTime) { if ($entry->is_all_day_event == true) { // whole day events ends at 23:59:59 in Tine 2.0 but 00:00 the next day in AS $dtend = clone $entry->{$tine20Property}; $dtend->addSecond($dtend->get('s') == 59 ? 1 : 0); $dtend->addMinute($dtend->get('i') == 59 ? 1 : 0); $syncrotonEvent->{$syncrotonProperty} = $dtend; } else { $syncrotonEvent->{$syncrotonProperty} = $entry->{$tine20Property}; } } break; case 'dtstart': if ($entry->{$tine20Property} instanceof DateTime) { $syncrotonEvent->{$syncrotonProperty} = $entry->{$tine20Property}; } break; case 'exdate': // handle exceptions of repeating events if ($entry->{$tine20Property} instanceof Tinebase_Record_RecordSet && $entry->{$tine20Property}->count() > 0) { $exceptions = array(); foreach ($entry->exdate as $exdate) { $exception = new Syncroton_Model_EventException(); // send the Deleted element only, when needed // HTC devices ignore the value(0 or 1) of the Deleted element if ((int) $exdate->is_deleted === 1) { $exception->deleted = 1; } $exception->exceptionStartTime = $exdate->getOriginalDtStart(); if ((int) $exdate->is_deleted === 0) { $exceptionSyncrotonEvent = $this->toSyncrotonModel($exdate); foreach ($exception->getProperties() as $property) { if (isset($exceptionSyncrotonEvent->{$property})) { $exception->{$property} = $exceptionSyncrotonEvent->{$property}; } } unset($exceptionSyncrotonEvent); } $exceptions[] = $exception; } $syncrotonEvent->{$syncrotonProperty} = $exceptions; } break; case 'rrule': if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " calendar rrule " . $entry->{$tine20Property}); } $rrule = Calendar_Model_Rrule::getRruleFromString($entry->{$tine20Property}); $recurrence = new Syncroton_Model_EventRecurrence(); // required fields switch ($rrule->freq) { case Calendar_Model_Rrule::FREQ_DAILY: $recurrence->type = Syncroton_Model_EventRecurrence::TYPE_DAILY; break; case Calendar_Model_Rrule::FREQ_WEEKLY: $recurrence->type = Syncroton_Model_EventRecurrence::TYPE_WEEKLY; $recurrence->dayOfWeek = $this->_convertDayToBitMask($rrule->byday); break; case Calendar_Model_Rrule::FREQ_MONTHLY: if (!empty($rrule->bymonthday)) { $recurrence->type = Syncroton_Model_EventRecurrence::TYPE_MONTHLY; $recurrence->dayOfMonth = $rrule->bymonthday; } else { $weekOfMonth = (int) substr($rrule->byday, 0, -2); $weekOfMonth = $weekOfMonth == -1 ? 5 : $weekOfMonth; $dayOfWeek = substr($rrule->byday, -2); $recurrence->type = Syncroton_Model_EventRecurrence::TYPE_MONTHLY_DAYN; $recurrence->weekOfMonth = $weekOfMonth; $recurrence->dayOfWeek = $this->_convertDayToBitMask($dayOfWeek); } break; case Calendar_Model_Rrule::FREQ_YEARLY: if (!empty($rrule->bymonthday)) { $recurrence->type = Syncroton_Model_EventRecurrence::TYPE_YEARLY; $recurrence->dayOfMonth = $rrule->bymonthday; $recurrence->monthOfYear = $rrule->bymonth; } else { $weekOfMonth = (int) substr($rrule->byday, 0, -2); $weekOfMonth = $weekOfMonth == -1 ? 5 : $weekOfMonth; $dayOfWeek = substr($rrule->byday, -2); $recurrence->type = Syncroton_Model_EventRecurrence::TYPE_YEARLY_DAYN; $recurrence->weekOfMonth = $weekOfMonth; $recurrence->dayOfWeek = $this->_convertDayToBitMask($dayOfWeek); $recurrence->monthOfYear = $rrule->bymonth; } break; } // required field $recurrence->interval = $rrule->interval ? $rrule->interval : 1; if ($rrule->count) { $recurrence->occurrences = $rrule->count; } else { if ($rrule->until instanceof DateTime) { $recurrence->until = $rrule->until; } } $syncrotonEvent->{$syncrotonProperty} = $recurrence; break; case 'tags': $syncrotonEvent->{$syncrotonProperty} = $entry->{$tine20Property}->name; break; default: $syncrotonEvent->{$syncrotonProperty} = $entry->{$tine20Property}; break; } } $timeZoneConverter = ActiveSync_TimezoneConverter::getInstance(Tinebase_Core::getLogger(), Tinebase_Core::get(Tinebase_Core::CACHE)); $syncrotonEvent->timezone = $timeZoneConverter->encodeTimezone(Tinebase_Core::getUserTimezone()); $syncrotonEvent->meetingStatus = 1; $syncrotonEvent->dtStamp = $entry->creation_time; $syncrotonEvent->uID = $entry->uid; $this->_addOrganizer($syncrotonEvent, $entry); return $syncrotonEvent; }
/** * checks if all attendee of given event are not busy for given event * * @param Calendar_Model_Event $_event * @return void * @throws Calendar_Exception_AttendeeBusy */ public function checkBusyConflicts($_event) { $ignoreUIDs = !empty($_event->uid) ? array($_event->uid) : array(); if ($_event->transp == Calendar_Model_Event::TRANSP_TRANSP || count($_event->attendee) < 1) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skipping free/busy check because event is transparent or has no attendee"); } return; } $eventSet = new Tinebase_Record_RecordSet('Calendar_Model_Event', array($_event)); if (!empty($_event->rrule)) { $checkUntil = clone $_event->dtstart; $checkUntil->add(1, Tinebase_DateTime::MODIFIER_MONTH); Calendar_Model_Rrule::mergeRecurrenceSet($eventSet, $_event->dtstart, $checkUntil); } $periods = array(); foreach ($eventSet as $event) { $periods[] = array('from' => $event->dtstart, 'until' => $event->dtend); } $fbInfo = $this->getFreeBusyInfo($periods, $_event->attendee, $ignoreUIDs); if (count($fbInfo) > 0) { $busyException = new Calendar_Exception_AttendeeBusy(); $busyException->setFreeBusyInfo($fbInfo); Calendar_Model_Attender::resolveAttendee($_event->attendee, false); $busyException->setEvent($_event); throw $busyException; } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Free/busy check: no conflict found"); } }
/** * returns array with the filter settings of this filter * * @param bool $_valueToJson resolve value for json api? * @return array */ public function toArray($_valueToJson = false) { $result = parent::toArray($_valueToJson); if ($_valueToJson) { Calendar_Model_Attender::resolveAttendee($this->_value); } $result['value'] = $this->_operator == 'equals' ? $this->_value[0]->toArray($_valueToJson) : $this->_value->toArray($_valueToJson); return $result; }
protected function _addEventAttendee(Sabre_VObject_Component $_vevent, Calendar_Model_Event $_event) { Calendar_Model_Attender::resolveAttendee($_event->attendee, FALSE, $_event); foreach ($_event->attendee as $eventAttendee) { $attendeeEmail = $eventAttendee->getEmail(); $attendee = new Sabre_VObject_Property('ATTENDEE', (strpos($attendeeEmail, '@') !== false ? 'mailto:' : 'urn:uuid:') . $attendeeEmail); $attendee->add('CN', $eventAttendee->getName()); $attendee->add('CUTYPE', Calendar_Convert_Event_VCalendar_Abstract::$cutypeMap[$eventAttendee->user_type]); $attendee->add('PARTSTAT', $eventAttendee->status); $attendee->add('ROLE', "{$eventAttendee->role}-PARTICIPANT"); $attendee->add('RSVP', 'FALSE'); if (strpos($attendeeEmail, '@') !== false) { $attendee->add('EMAIL', $attendeeEmail); } $_vevent->add($attendee); } }