/**
  * 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)
 {
     parent::_addEventAttendee($vevent, $event);
     if (empty($event->attendee)) {
         return;
     }
     // add organizer as CHAIR Attendee if he's no organizer, otherwise yosemite would add an attendee
     // when editing the event again.
     // NOTE: when the organizer edits the event he becomes attendee anyway, see comments in MSEventFacade::update
     if (version_compare($this->_version, '10.10', '>=')) {
         if (!empty($event->organizer)) {
             $organizerContact = $event->resolveOrganizer();
             if ($organizerContact instanceof Addressbook_Model_Contact) {
                 $organizerAttendee = Calendar_Model_Attender::getAttendee($event->attendee, new Calendar_Model_Attender(array('user_id' => $organizerContact->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER)));
                 if (!$organizerAttendee) {
                     $parameters = array('CN' => $organizerContact->n_fileas, 'CUTYPE' => 'INDIVIDUAL', 'PARTSTAT' => 'ACCEPTED', 'ROLE' => 'CHAIR');
                     $organizerEmail = $organizerContact->email;
                     if (strpos($organizerEmail, '@') !== false) {
                         $parameters['EMAIL'] = $organizerEmail;
                     }
                     $vevent->add('ATTENDEE', (strpos($organizerEmail, '@') !== false ? 'mailto:' : 'urn:uuid:') . $organizerEmail, $parameters);
                 }
             }
         }
     }
 }
 /**
  * (non-PHPdoc)
  * @see Sabre\DAV\Collection::getChild()
  */
 public function getChild($_name)
 {
     $eventId = $_name instanceof Tinebase_Record_Interface ? $_name->getId() : $this->_getIdFromName($_name);
     // check if child exists in calendarQuery cache
     if ($this->_calendarQueryCache && isset($this->_calendarQueryCache[$eventId])) {
         $child = $this->_calendarQueryCache[$eventId];
         // remove entries from cache / they will not be used anymore
         unset($this->_calendarQueryCache[$eventId]);
         if (empty($this->_calendarQueryCache)) {
             $this->_calendarQueryCache = null;
         }
         return $child;
     }
     $modelName = $this->_application->name . '_Model_' . $this->_model;
     if ($_name instanceof $modelName) {
         $object = $_name;
     } else {
         $filterClass = $this->_application->name . '_Model_' . $this->_model . 'Filter';
         $filter = new $filterClass(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_container->getId()), array('condition' => 'OR', 'filters' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $eventId), array('field' => 'uid', 'operator' => 'equals', 'value' => $eventId)))));
         $object = $this->_getController()->search($filter, null, false, false, 'sync')->getFirstRecord();
         if ($object == null) {
             throw new Sabre\DAV\Exception\NotFound('Object not found');
         }
     }
     $httpRequest = new Sabre\HTTP\Request();
     // lie about existence of event of request is a PUT request from an ATTENDEE for an already existing event
     // to prevent ugly (and not helpful) error messages on the client
     if (isset($_SERVER['REQUEST_METHOD']) && $httpRequest->getMethod() == 'PUT' && $httpRequest->getHeader('If-None-Match') === '*') {
         if ($object->organizer != Tinebase_Core::getUser()->contact_id && Calendar_Model_Attender::getOwnAttender($object->attendee) !== null) {
             throw new Sabre\DAV\Exception\NotFound('Object not found');
         }
     }
     $objectClass = $this->_application->name . '_Frontend_WebDAV_' . $this->_model;
     return new $objectClass($this->_container, $object);
 }
 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);
             }
         }
     }
 }
 public function testConvert()
 {
     $emailArrayFromClient = array(array('userType' => 'user', 'firstName' => 'Users', 'lastName' => '(Group)', 'partStat' => 'NEEDS-ACTION', 'role' => 'REQ', 'email' => 'urn:uuid:principals/intelligroups/cc74c2880f8c5c0eaacc57ea95f4d2571fb8a4b1'));
     $event = new Calendar_Model_Event();
     Calendar_Model_Attender::emailsToAttendee($event, $emailArrayFromClient);
     $this->assertEquals('cc74c2880f8c5c0eaacc57ea95f4d2571fb8a4b1', $event->attendee->getFirstRecord()->user_id);
     $this->assertEquals('group', $event->attendee->getFirstRecord()->user_type);
 }
Exemple #5
0
 /**
  * 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);
 }
 /**
  * (non-PHPdoc)
  * @see Sabre\DAV\Collection::getChild()
  */
 public function getChild($_name)
 {
     try {
         $event = $_name instanceof Calendar_Model_Event ? $_name : $this->_getController()->get($this->_getIdFromName($_name));
     } catch (Tinebase_Exception_NotFound $tenf) {
         throw new \Sabre\DAV\Exception\NotFound('Object not found');
     }
     $ownAttendee = Calendar_Model_Attender::getOwnAttender($event->attendee);
     $displayContainer = $ownAttendee->displaycontainer_id instanceof Tinebase_Model_Container ? $ownAttendee->displaycontainer_id : Tinebase_Container::getInstance()->get($ownAttendee->displaycontainer_id);
     return new Calendar_Frontend_WebDAV_Event($displayContainer, $event);
 }
 /**
  * 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);
             }
         }
     }
 }
 /**
  * (non-PHPdoc)
  * @see Sabre_DAV_Collection::getChild()
  */
 public function getChild($_name)
 {
     $modelName = $this->_application->name . '_Model_' . $this->_model;
     if ($_name instanceof $modelName) {
         $object = $_name;
     } else {
         $filterClass = $this->_application->name . '_Model_' . $this->_model . 'Filter';
         $filter = new $filterClass(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_container->getId()), array('condition' => 'OR', 'filters' => array(array('field' => 'id', 'operator' => 'equals', 'value' => $this->_getIdFromName($_name)), array('field' => 'uid', 'operator' => 'equals', 'value' => $this->_getIdFromName($_name))))));
         $object = $this->_getController()->search($filter, null, false, false, 'sync')->getFirstRecord();
         if ($object == null) {
             throw new Sabre_DAV_Exception_FileNotFound('Object not found');
         }
     }
     $httpRequest = new Sabre_HTTP_Request();
     // lie about existance of event of request is a PUT request from an ATTENDEE for an already existing event
     // to prevent ugly (and not helpful) error messages on the client
     if (isset($_SERVER['REQUEST_METHOD']) && $httpRequest->getMethod() == 'PUT' && $httpRequest->getHeader('If-None-Match') === '*') {
         if ($object->organizer != Tinebase_Core::getUser()->contact_id && Calendar_Model_Attender::getOwnAttender($object->attendee) !== null) {
             throw new Sabre_DAV_Exception_FileNotFound('Object not found');
         }
     }
     $objectClass = $this->_application->name . '_Frontend_WebDAV_' . $this->_model;
     return new $objectClass($this->_container, $object);
 }
 /**
  * set status of own attender depending on BusyStatus
  * 
  * @param SimpleXMLElement $xmlData
  * @param Calendar_Model_Event $event
  * 
  * @todo move detection of special handling / device type to device library
  */
 protected function _handleBusyStatus($data, $event)
 {
     if (!isset($data->busyStatus)) {
         return;
     }
     $ownAttender = Calendar_Model_Attender::getOwnAttender($event->attendee);
     if ($ownAttender === NULL) {
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' No own attender found.');
         }
         return;
     }
     $busyStatus = $data->busyStatus;
     if (in_array(strtolower($this->_device->devicetype), $this->_devicesWithWrongBusyStatusDefault)) {
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Device uses a bad default setting. BUSY and FREE are mapped to ACCEPTED.');
         }
         $busyStatusMapping = array(Syncroton_Model_Event::BUSY_STATUS_BUSY => Calendar_Model_Attender::STATUS_ACCEPTED, Syncroton_Model_Event::BUSY_STATUS_TENATTIVE => Calendar_Model_Attender::STATUS_TENTATIVE, Syncroton_Model_Event::BUSY_STATUS_FREE => Calendar_Model_Attender::STATUS_ACCEPTED);
     } else {
         $busyStatusMapping = $this->_busyStatusMapping;
     }
     if (isset($busyStatusMapping[$busyStatus])) {
         $ownAttender->status = $busyStatusMapping[$busyStatus];
     } else {
         $ownAttender->status = Calendar_Model_Attender::STATUS_NEEDSACTION;
     }
 }
 /**
  * calculate event permissions and remove events that don't match
  * 
  * @param  Tinebase_Record_RecordSet        $events
  * @param  Tinebase_Model_Filter_AclFilter  $grantsFilter
  */
 protected function _checkGrants($events, $grantsFilter)
 {
     $currentContact = Tinebase_Core::getUser()->contact_id;
     $containerGrants = Tinebase_Container::getInstance()->getContainerGrantsOfRecords($events, Tinebase_Core::getUser());
     $resolvedAttendees = Calendar_Model_Attender::getResolvedAttendees($events->attendee, true);
     $toRemove = array();
     $inheritableGrants = array(Tinebase_Model_Grants::GRANT_FREEBUSY, Tinebase_Model_Grants::GRANT_READ, Tinebase_Model_Grants::GRANT_SYNC, Tinebase_Model_Grants::GRANT_EXPORT, Tinebase_Model_Grants::GRANT_PRIVATE);
     if ($grantsFilter instanceof Calendar_Model_GrantFilter) {
         $requiredGrants = $grantsFilter->getRequiredGrants();
         if (is_array($requiredGrants)) {
             $requiredGrants = array_intersect($requiredGrants, $this->_recordBasedGrants);
         } else {
             // TODO throw exception here?
             if (Tinebase_Core::isLogLevel(Zend_Log::NOTICE)) {
                 Tinebase_Core::getLogger()->notice(__METHOD__ . '::' . __LINE__ . ' Required grants not set in grants filter: ' . print_r($grantsFilter->toArray(), true));
             }
         }
     }
     foreach ($events as $event) {
         $containerId = $event->container_id instanceof Tinebase_Model_Container ? $event->container_id->getId() : $event->container_id;
         // either current user is organizer or has admin right on container
         if ($event->organizer === $currentContact || isset($containerGrants[$containerId]) && $containerGrants[$containerId]->account_grants[Tinebase_Model_Grants::GRANT_ADMIN]) {
             foreach ($this->_recordBasedGrants as $grant) {
                 $event->{$grant} = true;
             }
             // has all rights => no need to filter
             continue;
         }
         // grants to original container
         if (isset($containerGrants[$containerId])) {
             foreach ($this->_recordBasedGrants as $grant) {
                 $event->{$grant} = $containerGrants[$containerId]->account_grants[$grant];
             }
         }
         // check grant inheritance
         if ($event->attendee instanceof Tinebase_Record_RecordSet) {
             foreach ($inheritableGrants as $grant) {
                 if (!$event->{$grant}) {
                     foreach ($event->attendee as $attendee) {
                         $attendee = $resolvedAttendees->getById($attendee->getId());
                         if (!$attendee) {
                             continue;
                         }
                         if ($attendee->displaycontainer_id instanceof Tinebase_Model_Container && $attendee->displaycontainer_id->account_grants && ($attendee->displaycontainer_id->account_grants[$grant] || $attendee->displaycontainer_id->account_grants[Tinebase_Model_Grants::GRANT_ADMIN])) {
                             $event->{$grant} = true;
                             break;
                         }
                     }
                 }
             }
         }
         // check if one of the grants is set ...
         if (isset($requiredGrants) && is_array($requiredGrants)) {
             foreach ($requiredGrants as $requiredGrant) {
                 if ($event->{$requiredGrant}) {
                     continue 2;
                 }
             }
             // ... otherwise mark for removal
             $toRemove[] = $event;
         }
     }
     // remove records with non matching grants
     foreach ($toRemove as $event) {
         $events->removeRecord($event);
     }
 }
 /**
  * assert current user as attender
  * 
  * @param Calendar_Model_Event $exdate
  */
 protected function _assertCurrentUserAttender($event)
 {
     $this->assertTrue($event->attendee instanceof Tinebase_Record_RecordSet, 'attendee is no recordset: ' . print_r($event->toArray(), true));
     $this->assertEquals(2, $event->attendee->count(), 'exdate should have 2 attendee: ' . print_r($event->toArray(), true));
     $currentUser = Calendar_Model_Attender::getAttendee($event->attendee, new Calendar_Model_Attender(array('user_id' => Tinebase_Core::getUser()->contact_id, 'user_type' => Calendar_Model_Attender::USERTYPE_USER)));
     $this->assertNotNull($currentUser, 'currentUser not found in attendee');
     $this->assertEquals(Calendar_Model_Attender::STATUS_ACCEPTED, $currentUser->status, print_r($currentUser->toArray(), true));
 }
 public function testMissingEmailAttendee()
 {
     $noMailContact = Addressbook_Controller_Contact::getInstance()->create(new Addressbook_Model_Contact(array('org_name' => 'nomail')));
     $noMailAttendee = new Calendar_Model_Attender(array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $noMailContact->getId(), 'organizer' => Tinebase_Core::getUser()->contact_id));
     $event = $this->_getEvent();
     $event->attendee->addRecord($noMailAttendee);
     $persistentEvent = Calendar_Controller_Event::getInstance()->create($event);
     $loadedEvent = $this->_uit->get($persistentEvent->getId());
     $this->assertTrue((bool) Calendar_Model_Attender::getAttendee($persistentEvent->attendee, $noMailAttendee));
     $this->assertFalse((bool) Calendar_Model_Attender::getAttendee($loadedEvent->attendee, $noMailAttendee));
     $loadedEvent->summary = 'update';
     $update = $this->_uit->update($loadedEvent);
     $loadedEvent = Calendar_Controller_Event::getInstance()->get($persistentEvent->getId());
     $this->assertEquals('update', $loadedEvent->summary);
     $this->assertTrue((bool) Calendar_Model_Attender::getAttendee($loadedEvent->attendee, $noMailAttendee));
 }
 protected function _getEventAttendee($_egwEventData)
 {
     $tineAttendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender');
     foreach ($_egwEventData['attendee'] as $idx => $egwAttender) {
         try {
             $tineAttenderArray = array('quantity' => $egwAttender['cal_quantity'], 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'status' => isset($this->_attenderStatusMap[$egwAttender['cal_status']]) || array_key_exists($egwAttender['cal_status'], $this->_attenderStatusMap) ? $this->_attenderStatusMap[$egwAttender['cal_status']] : Calendar_Model_Attender::STATUS_NEEDSACTION, 'status_authkey' => Calendar_Model_Attender::generateUID());
             switch ($egwAttender['cal_user_type']) {
                 case 'u':
                     // user and group
                     if ($egwAttender['cal_user_id'] > 0) {
                         $tineAttenderArray['user_type'] = Calendar_Model_Attender::USERTYPE_USER;
                         $tineAttenderArray['user_id'] = Tinebase_User::getInstance()->getUserById($this->mapAccountIdEgw2Tine($egwAttender['cal_user_id']))->contact_id;
                         $tineAttenderArray['displaycontainer_id'] = $this->getPersonalContainer($this->mapAccountIdEgw2Tine($egwAttender['cal_user_id']))->getId();
                     } else {
                         $tineAttenderArray['user_type'] = Calendar_Model_Attender::USERTYPE_GROUP;
                         $tineAttenderArray['user_id'] = $this->mapAccountIdEgw2Tine($egwAttender['cal_user_id']);
                     }
                     break;
                 case 'c':
                     // try to find contact in tine (NOTE: id is useless, as contacts get new ids during migration)
                     $contact_id = $this->_getContactIdByEmail($egwAttender['email'], $this->mapAccountIdEgw2Tine($_egwEventData['cal_owner']));
                     if (!$contact_id) {
                         continue 2;
                     }
                     $tineAttenderArray['user_type'] = Calendar_Model_Attender::USERTYPE_USER;
                     $tineAttenderArray['user_id'] = $contact_id;
                     break;
                 case 'r':
                     $resource_id = $this->_getResourceId($egwAttender['cal_user_id']);
                     if (!$resource_id) {
                         continue 2;
                     }
                     $tineAttenderArray['user_type'] = Calendar_Model_Attender::USERTYPE_RESOURCE;
                     $tineAttenderArray['user_id'] = $resource_id;
                     break;
                 default:
                     throw new Exception("unsupported attender type: {$egwAttender['cal_user_type']}");
                     break;
             }
             $tineAttendee->addRecord(new Calendar_Model_Attender($tineAttenderArray));
         } catch (Exception $e) {
             $this->_log->warn(__METHOD__ . '::' . __LINE__ . ' skipping attender for event "' . $_egwEventData['cal_id'] . '"cause: ' . $e->getMessage());
             // skip attender
         }
     }
     // resolve groupmembers
     Calendar_Model_Attender::resolveGroupMembers($tineAttendee);
     $groupMembers = $tineAttendee->filter('user_type', Calendar_Model_Attender::USERTYPE_GROUPMEMBER);
     foreach ($groupMembers as $groupMember) {
         $groupMember->status_authkey = Calendar_Model_Attender::generateUID();
         $contact = Addressbook_Controller_Contact::getInstance()->get($groupMember->user_id);
         $groupMember->displaycontainer_id = $this->getPersonalContainer($contact->account_id)->getId();
     }
     return $tineAttendee;
 }
 /**
  * checks event for given grant
  * 
  * @param  string $_grant
  * @return bool
  */
 public function hasGrant($_grant)
 {
     $hasGrant = (isset($this->_properties[$_grant]) || array_key_exists($_grant, $this->_properties)) && (bool) $this->{$_grant};
     if ($this->class !== Calendar_Model_Event::CLASS_PUBLIC) {
         $hasGrant &= $this->{Tinebase_Model_Grants::GRANT_PRIVATE} || Tinebase_Core::getUser()->contact_id == ($this->organizer instanceof Addressbook_Model_Contact ? $this->organizer->getId() : $this->organizer) || Calendar_Model_Attender::getOwnAttender($this->attendee);
     }
     return $hasGrant;
 }
Exemple #18
0
 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;
 }
Exemple #19
0
 /**
  * process request
  * 
  * @param  Calendar_Model_iMIP   $_iMIP
  * @param  string                $_status
  * @throws Tinebase_Exception_NotImplemented
  * 
  * @todo handle external organizers
  * @todo create event in the organizers context
  */
 protected function _processRequest($_iMIP, $_status)
 {
     $existingEvent = $_iMIP->getExistingEvent();
     $ownAttender = Calendar_Model_Attender::getOwnAttender($existingEvent ? $existingEvent->attendee : $_iMIP->getEvent()->attendee);
     $organizer = $existingEvent ? $existingEvent->resolveOrganizer() : $_iMIP->getEvent()->resolveOrganizer();
     // internal organizer:
     //  - event is up to date
     //  - status change could also be done by calendar method
     //  - normal notifications
     if ($organizer->account_id) {
         if (!$existingEvent) {
             // organizer has an account but no event exists, it seems that event was created from a non-caldav client
             // do not send notifications in this case + create event in context of organizer
             return;
             // not clear how to create in the organizers context...
             $sendNotifications = Calendar_Controller_Event::getInstance()->sendNotifications(FALSE);
             $existingEvent = Calendar_Controller_MSEventFacade::getInstance()->create($_iMIP->getEvent());
             Calendar_Controller_Event::getInstance()->sendNotifications($sendNotifications);
         }
         if ($_status && $_status != $ownAttender->status) {
             $ownAttender->status = $_status;
             Calendar_Controller_Event::getInstance()->attenderStatusUpdate($existingEvent, $ownAttender, $ownAttender->status_authkey);
         }
     } else {
         if ($ownAttender && $_status) {
             $ownAttender->status = $_status;
         }
         if (!$existingEvent) {
             $event = $_iMIP->getEvent();
             if (!$event->container_id) {
                 $event->container_id = Tinebase_Core::getPreference('Calendar')->{Calendar_Preference::DEFAULTCALENDAR};
             }
             $_iMIP->event = Calendar_Controller_MSEventFacade::getInstance()->create($event);
         } else {
             $_iMIP->event = Calendar_Controller_MSEventFacade::getInstance()->update($existingEvent);
         }
         //  - send reply to organizer
     }
 }
 /**
  * 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;
     }
 }
 /**
  * process request
  * 
  * @param  Calendar_Model_iMIP   $_iMIP
  * @param  string                $_status
  */
 protected function _processRequest($_iMIP, $_status)
 {
     $existingEvent = $this->getExistingEvent($_iMIP);
     $ownAttender = Calendar_Model_Attender::getOwnAttender($existingEvent ? $existingEvent->attendee : $_iMIP->getEvent()->attendee);
     $organizer = $existingEvent ? $existingEvent->resolveOrganizer() : $_iMIP->getEvent()->resolveOrganizer();
     // internal organizer:
     //  - event is up to date
     //  - status change could also be done by calendar method
     //  - normal notifications
     if ($organizer->account_id) {
         if (!$existingEvent) {
             // organizer has an account but no event exists, it seems that event was created from a non-caldav client
             // do not send notifications in this case + create event in context of organizer
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Organizer has an account but no event exists!');
             }
             return;
             // not clear how to create in the organizers context...
             $sendNotifications = Calendar_Controller_Event::getInstance()->sendNotifications(FALSE);
             $existingEvent = Calendar_Controller_MSEventFacade::getInstance()->create($_iMIP->getEvent());
             Calendar_Controller_Event::getInstance()->sendNotifications($sendNotifications);
         }
         if ($_status && $_status != $ownAttender->status) {
             $ownAttender->status = $_status;
             Calendar_Controller_Event::getInstance()->attenderStatusUpdate($existingEvent, $ownAttender, $ownAttender->status_authkey);
         }
     } else {
         $sendNotifications = Calendar_Controller_Event::getInstance()->sendNotifications(false);
         $event = $_iMIP->getEvent();
         if (!$existingEvent) {
             if (!$event->container_id) {
                 $event->container_id = Tinebase_Core::getPreference('Calendar')->{Calendar_Preference::DEFAULTCALENDAR};
             }
             $event = $_iMIP->event = Calendar_Controller_MSEventFacade::getInstance()->create($event);
         } else {
             if ($event->external_seq > $existingEvent->external_seq && !$_status) {
                 // no buttons pressed (just reading/updating)
                 // updates event with .ics
                 $event->id = $existingEvent->id;
                 $event = $_iMIP->event = Calendar_Controller_MSEventFacade::getInstance()->update($event);
             } else {
                 $event = $_iMIP->event = Calendar_Controller_MSEventFacade::getInstance()->update($existingEvent);
             }
         }
         Calendar_Controller_Event::getInstance()->sendNotifications($sendNotifications);
         $ownAttender = Calendar_Model_Attender::getOwnAttender($event->attendee);
         // NOTE: we do the status update in a separate call to trigger the right notifications
         if ($ownAttender && $_status) {
             $ownAttender->status = $_status;
             $a = Calendar_Controller_Event::getInstance()->attenderStatusUpdate($event, $ownAttender, $ownAttender->status_authkey);
         }
     }
 }
 /**
  * send notification to a single attender
  * 
  * @param Calendar_Model_Attender    $_attender
  * @param Calendar_Model_Event       $_event
  * @param Tinebase_Model_FullAccount $_updater
  * @param string                     $_action
  * @param string                     $_notificationLevel
  * @param array                      $_updates
  * @return void
  *
  * TODO this needs major refactoring
  */
 public function sendNotificationToAttender(Calendar_Model_Attender $_attender, $_event, $_updater, $_action, $_notificationLevel, $_updates = NULL)
 {
     try {
         $organizer = $_event->resolveOrganizer();
         $organizerAccountId = $organizer->account_id;
         $attendee = $_attender->getResolvedUser();
         if ($attendee instanceof Addressbook_Model_List) {
             // don't send notification to lists as we already resolved the list members for individual mails
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Skip notification for list " . $attendee->name);
             }
             return;
         }
         $attendeeAccountId = $_attender->getUserAccountId();
         $prefUserId = $attendeeAccountId ? $attendeeAccountId : ($organizerAccountId ? $organizerAccountId : $_event->created_by);
         try {
             $prefUser = Tinebase_User::getInstance()->getFullUserById($prefUserId);
         } catch (Exception $e) {
             $prefUser = Tinebase_Core::getUser();
             $prefUserId = $prefUser->getId();
         }
         // get prefered language, timezone and notification level
         $locale = Tinebase_Translation::getLocale(Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::LOCALE, $prefUserId));
         $timezone = Tinebase_Core::getPreference()->getValueForUser(Tinebase_Preference::TIMEZONE, $prefUserId);
         $translate = Tinebase_Translation::getTranslation('Calendar', $locale);
         $sendLevel = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::NOTIFICATION_LEVEL, $prefUserId);
         $sendOnOwnActions = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::SEND_NOTIFICATION_OF_OWN_ACTIONS, $prefUserId);
         $sendAlarms = Tinebase_Core::getPreference('Calendar')->getValueForUser(Calendar_Preference::SEND_ALARM_NOTIFICATIONS, $prefUserId);
         // external (non account) notification
         if (!$attendeeAccountId) {
             // external organizer needs status updates
             $sendLevel = is_object($organizer) && $_attender->getEmail() == $organizer->getPreferedEmailAddress() ? 40 : 30;
             $sendOnOwnActions = false;
             $sendAlarms = false;
         }
         $recipients = array($attendee);
         $this->_handleResourceEditors($_attender, $_notificationLevel, $recipients, $_action, $sendLevel, $_updates);
         // check if user wants this notification NOTE: organizer gets mails unless she set notificationlevel to NONE
         // NOTE prefUser is organizer for external notifications
         if ($attendeeAccountId == $_updater->getId() && !$sendOnOwnActions || $sendLevel < $_notificationLevel && (is_object($organizer) && method_exists($attendee, 'getPreferedEmailAddress') && $attendee->getPreferedEmailAddress() != $organizer->getPreferedEmailAddress() || is_object($organizer) && !method_exists($attendee, 'getPreferedEmailAddress') && $attendee->email != $organizer->getPreferedEmailAddress() || $sendLevel == self::NOTIFICATION_LEVEL_NONE)) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " Preferred notification level not reached -> skipping notification for {$_attender->getEmail()}");
             }
             return;
         }
         if ($_action == 'alarm' && !$sendAlarms) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " User does not want alarm mails -> skipping notification for {$_attender->getEmail()}");
             }
             return;
         }
         $method = NULL;
         // NOTE $method gets set in _getSubject as referenced param
         $messageSubject = $this->_getSubject($_event, $_notificationLevel, $_action, $_updates, $timezone, $locale, $translate, $method, $_attender);
         // we don't send iMIP parts to external attendee if config is active
         if (Calendar_Config::getInstance()->get(Calendar_Config::DISABLE_EXTERNAL_IMIP) && !$attendeeAccountId) {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " External iMIP is disabled.");
             }
             $method = NULL;
         }
         $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');
         $calendarPart = null;
         $attachments = $this->_getAttachments($method, $_event, $_action, $_updater, $calendarPart);
         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}");
         }
         $sender = $_action == 'alarm' ? $prefUser : $_updater;
         Tinebase_Notification::getInstance()->send($sender, $recipients, $messageSubject, $messageBody, $calendarPart, $attachments);
     } catch (Exception $e) {
         Tinebase_Exception::log($e);
         return;
     }
 }
 /**
  * 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;
 }
Exemple #24
0
 /**
  * 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);
 }
 /**
  * converts an iTIP event to a tine20 event
  * 
  * @param Calendar_Model_Event $_event
  * @param Calendar_Model_Event $_currentEvent (not iTIP!)
  */
 protected function _fromiTIP($_event, $_currentEvent)
 {
     if (!$_event->rrule) {
         $_event->exdate = NULL;
     }
     if ($_event->exdate instanceof Tinebase_Record_RecordSet) {
         try {
             $currExdates = $this->_eventController->getRecurExceptions($_event, TRUE);
             $this->getAlarms($currExdates);
             $currClientExdates = $this->_eventController->getRecurExceptions($_event, TRUE, $this->getEventFilter());
             $this->getAlarms($currClientExdates);
         } catch (Tinebase_Exception_NotFound $e) {
             $currExdates = NULL;
             $currClientExdates = NULL;
         }
         foreach ($_event->exdate as $idx => $exdate) {
             try {
                 $this->_prepareException($_event, $exdate);
             } catch (Exception $e) {
             }
             $currExdate = $currExdates instanceof Tinebase_Record_RecordSet ? $currExdates->filter('recurid', $exdate->recurid)->getFirstRecord() : NULL;
             if ($exdate->is_deleted) {
                 // reset implicit filter fallouts and mark as don't touch (seq = -1)
                 $currClientExdate = $currClientExdates instanceof Tinebase_Record_RecordSet ? $currClientExdates->filter('recurid', $exdate->recurid)->getFirstRecord() : NULL;
                 if ($currClientExdate && $currClientExdate->is_deleted) {
                     $_event->exdate[$idx] = $currExdate;
                     $currExdate->seq = -1;
                     continue;
                 }
             }
             $this->_fromiTIP($exdate, $currExdate ? $currExdate : clone $_currentEvent);
         }
     }
     // assert organizer
     $_event->organizer = $_event->organizer ?: ($_currentEvent->organizer ?: $this->_calendarUser->user_id);
     $this->_addAttendeeWithoutEmail($_event, $_currentEvent);
     $CUAttendee = Calendar_Model_Attender::getAttendee($_event->attendee, $this->_calendarUser);
     $currentCUAttendee = Calendar_Model_Attender::getAttendee($_currentEvent->attendee, $this->_calendarUser);
     $isOrganizer = $_event->isOrganizer($this->_calendarUser);
     // remove perspective
     if ($CUAttendee && !$isOrganizer) {
         $CUAttendee->transp = $_event->transp;
         $_event->transp = $_currentEvent->transp ? $_currentEvent->transp : $_event->transp;
     }
     // apply changes to original alarms
     $_currentEvent->alarms = $_currentEvent->alarms instanceof Tinebase_Record_RecordSet ? $_currentEvent->alarms : new Tinebase_Record_RecordSet('Tinebase_Model_Alarm');
     $_event->alarms = $_event->alarms instanceof Tinebase_Record_RecordSet ? $_event->alarms : new Tinebase_Record_RecordSet('Tinebase_Model_Alarm');
     foreach ($_currentEvent->alarms as $currentAlarm) {
         if (Calendar_Model_Attender::isAlarmForAttendee($this->_calendarUser, $currentAlarm)) {
             $alarmUpdate = Calendar_Controller_Alarm::getMatchingAlarm($_event->alarms, $currentAlarm);
             if ($alarmUpdate) {
                 // we could map the alarm => save ack & snooze options
                 if ($dtAck = Calendar_Controller_Alarm::getAcknowledgeTime($alarmUpdate)) {
                     Calendar_Controller_Alarm::setAcknowledgeTime($currentAlarm, $dtAck, $this->getCalendarUser()->user_id);
                 }
                 if ($dtSnooze = Calendar_Controller_Alarm::getSnoozeTime($alarmUpdate)) {
                     Calendar_Controller_Alarm::setSnoozeTime($currentAlarm, $dtSnooze, $this->getCalendarUser()->user_id);
                 }
                 $_event->alarms->removeRecord($alarmUpdate);
             } else {
                 // alarm is to be skiped/deleted
                 if (!$currentAlarm->getOption('attendee')) {
                     Calendar_Controller_Alarm::skipAlarm($currentAlarm, $this->_calendarUser);
                 } else {
                     $_currentEvent->alarms->removeRecord($currentAlarm);
                 }
             }
         }
     }
     if (!$isOrganizer) {
         $_event->alarms->setOption('attendee', Calendar_Controller_Alarm::attendeeToOption($this->_calendarUser));
     }
     $_event->alarms->merge($_currentEvent->alarms);
     // assert organizer for personal calendars to be calendar owner
     if ($this->_currentEventFacadeContainer && $this->_currentEventFacadeContainer->getId() == $_event->container_id && $this->_currentEventFacadeContainer->type == Tinebase_Model_Container::TYPE_PERSONAL && !$_event->hasExternalOrganizer()) {
         $_event->organizer = $this->_calendarUser->user_id;
     }
     // in MS world only cal_user can do status updates
     if ($CUAttendee) {
         $CUAttendee->status_authkey = $currentCUAttendee ? $currentCUAttendee->status_authkey : NULL;
     }
 }
 /**
  * testInvitationExternalReply
  */
 public function testInvitationExternalReply()
 {
     $email = $email = $this->_getEmailAddress();
     $ics = file_get_contents(dirname(__FILE__) . '/files/invitation_reply_external_accepted.ics');
     $ics = preg_replace('/unittest@tine20\\.org/', $email, $ics);
     $iMIP = new Calendar_Model_iMIP(array('id' => Tinebase_Record_Abstract::generateUID(), 'ics' => $ics, 'method' => 'REPLY', 'originator' => '*****@*****.**'));
     $this->assertEquals(1, $iMIP->getEvent()->seq);
     $this->assertTrue(!empty($iMIP->getEvent()->last_modified_time));
     // force creation of external attendee
     $externalAttendee = new Calendar_Model_Attender(array('user_type' => Calendar_Model_Attender::USERTYPE_USER, 'user_id' => $iMIP->getEvent()->attendee->getFirstRecord()->user_id, 'status' => Calendar_Model_Attender::STATUS_NEEDSACTION));
     // create matching event
     $event = new Calendar_Model_Event(array('summary' => 'TEST7', 'dtstart' => '2011-11-30 14:00:00', 'dtend' => '2011-11-30 15:00:00', 'description' => 'Early to bed and early to rise, makes a men healthy, wealthy and wise ...', 'attendee' => $this->_getAttendee(), 'organizer' => Tinebase_Core::getUser()->contact_id, 'uid' => 'a8d10369e051094ae9322bd65e8afecac010bfc8'));
     $event->attendee->addRecord($externalAttendee);
     $event = Calendar_Controller_Event::getInstance()->create($event);
     $this->_eventIdsToDelete[] = $event->getId();
     // TEST NORMAL REPLY
     try {
         $this->_iMIPFrontend->autoProcess($iMIP);
     } catch (Exception $e) {
         $this->fail('TEST NORMAL REPLY autoProcess throws Exception: ' . $e);
     }
     unset($iMIP->existing_event);
     $updatedEvent = Calendar_Controller_Event::getInstance()->get($event->getId());
     $updatedExternalAttendee = Calendar_Model_Attender::getAttendee($updatedEvent->attendee, $externalAttendee);
     $this->assertEquals(3, count($updatedEvent->attendee));
     $this->assertEquals(Calendar_Model_Attender::STATUS_ACCEPTED, $updatedExternalAttendee->status, 'status not updated');
     // TEST ACCEPTABLE NON RECENT REPLY
     $updatedExternalAttendee->status = Calendar_Model_Attender::STATUS_NEEDSACTION;
     Calendar_Controller_Event::getInstance()->attenderStatusUpdate($updatedEvent, $updatedExternalAttendee, $updatedExternalAttendee->status_authkey);
     try {
         $iMIP->preconditionsChecked = false;
         $this->_iMIPFrontend->autoProcess($iMIP);
     } catch (Exception $e) {
         $this->fail('TEST ACCEPTABLE NON RECENT REPLY autoProcess throws Exception: ' . $e);
     }
     unset($iMIP->existing_event);
     $updatedEvent = Calendar_Controller_Event::getInstance()->get($event->getId());
     $updatedExternalAttendee = Calendar_Model_Attender::getAttendee($updatedEvent->attendee, $externalAttendee);
     $this->assertEquals(3, count($updatedEvent->attendee));
     $this->assertEquals(Calendar_Model_Attender::STATUS_ACCEPTED, $updatedExternalAttendee->status, 'status not updated');
     // check if attendee are resolved
     $existingEvent = $this->_iMIPFrontend->getExistingEvent($iMIP);
     $this->assertTrue($iMIP->existing_event->attendee instanceof Tinebase_Record_RecordSet);
     $this->assertEquals(3, count($iMIP->existing_event->attendee));
     // TEST NON ACCEPTABLE NON RECENT REPLY
     $iMIP->preconditionsChecked = false;
     try {
         $this->_iMIPFrontend->autoProcess($iMIP);
         $this->fail('autoProcess should throw Calendar_Exception_iMIP');
     } catch (Calendar_Exception_iMIP $cei) {
         $this->assertContains('iMIP preconditions failed: RECENT', $cei->getMessage());
     }
 }
 /**
  * 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;
 }
 public function testAlarmSkipDeclined()
 {
     $event = $this->_getEvent();
     $event->attendee = $this->_getPersonaAttendee('sclever, pwulf');
     $event->organizer = $this->_getPersonasContacts('sclever')->getId();
     $event->dtstart = Tinebase_DateTime::now()->addMinute(25);
     $event->dtend = clone $event->dtstart;
     $event->dtend->addMinute(30);
     $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(new Tinebase_Model_Alarm(array('minutes_before' => 30), TRUE)));
     $persistentEvent = $this->_eventController->create($event);
     $sclever = Calendar_Model_Attender::getAttendee($persistentEvent->attendee, $event->attendee[0]);
     $sclever->status = Calendar_Model_Attender::STATUS_DECLINED;
     $this->_eventController->attenderStatusUpdate($persistentEvent, $sclever, $sclever->status_authkey);
     self::flushMailer();
     Tinebase_Alarm::getInstance()->sendPendingAlarms("Tinebase_Event_Async_Minutely");
     $this->_assertMail('pwulf', 'Alarm');
     $this->assertEquals(1, count(self::getMessages()));
 }
 public function testMeetingResponseWithNewInstanceId()
 {
     $syncrotonFolder = $this->testCreateFolder();
     list($serverId, $event) = $this->testCreateEntry($syncrotonFolder);
     $controller = Syncroton_Data_Factory::factory($this->_class, $this->_getDevice(Syncroton_Model_Device::TYPE_IPHONE), new Tinebase_DateTime(null, null, 'de_DE'));
     $XMLMeetingResponse = $this->_testXMLMeetingResponse;
     $thisYear = Tinebase_DateTime::now()->format('Y');
     $XMLMeetingResponse = str_replace('2012', $thisYear, $XMLMeetingResponse);
     $XMLMeetingResponse = str_replace('<CollectionId>17</CollectionId>', '<CollectionId>' . $syncrotonFolder->serverId . '</CollectionId>', $XMLMeetingResponse);
     $XMLMeetingResponse = str_replace('<RequestId>f0c79775b6b44be446f91187e24566aa1c5d06ab</RequestId>', '<RequestId>' . $serverId . '</RequestId>', $XMLMeetingResponse);
     $XMLMeetingResponse = str_replace('<InstanceId>20121125T130000Z</InstanceId>', '<InstanceId>20121126T130000Z</InstanceId>', $XMLMeetingResponse);
     $xml = new SimpleXMLElement($XMLMeetingResponse);
     $meetingResponse = new Syncroton_Model_MeetingResponse($xml->Request[0]);
     $eventId = $controller->setAttendeeStatus($meetingResponse);
     $event = Calendar_Controller_MSEventFacade::getInstance()->get($serverId);
     $event->exdate->sort('dtstart', 'DESC');
     $instance = $event->exdate->filter('is_deleted', 0)->getFirstRecord();
     $ownAttendee = Calendar_Model_Attender::getOwnAttender($instance->attendee);
     $this->assertEquals(Calendar_Model_Attender::STATUS_TENTATIVE, $ownAttendee->status);
 }
 /**
  * test implicit recur (exception) series creation for attendee status only
  */
 public function testAttendeeSetStatusRecurExceptionAllFollowing()
 {
     $from = new Tinebase_DateTime('2012-02-01 00:00:00');
     $until = new Tinebase_DateTime('2012-02-29 23:59:59');
     $event = new Calendar_Model_Event(array('summary' => 'Some Daily Event', 'dtstart' => '2012-02-03 09:00:00', 'dtend' => '2012-02-03 10:00:00', 'rrule' => 'FREQ=DAILY;INTERVAL=1', 'container_id' => $this->_testCalendar->getId(), 'attendee' => $this->_getAttendee()));
     $persistentEvent = $this->_controller->create($event);
     $exceptions = new Tinebase_Record_RecordSet('Calendar_Model_Event');
     $recurSet = Calendar_Model_Rrule::computeRecurrenceSet($persistentEvent, $exceptions, $from, $until);
     // accept for sclever thisandfuture
     $start = $recurSet[10];
     $sclever = Calendar_Model_Attender::getAttendee($start->attendee, $event->attendee[1]);
     $sclever->status = Calendar_Model_Attender::STATUS_ACCEPTED;
     $this->_controller->attenderStatusCreateRecurException($start, $sclever, $sclever->status_authkey, TRUE);
     $events = $this->_controller->search(new Calendar_Model_EventFilter(array(array('field' => 'container_id', 'operator' => 'equals', 'value' => $this->_testCalendar->getId()))))->sort('dtstart', 'ASC');
     // assert two baseEvents
     $this->assertTrue($events[0]->rrule_until instanceof Tinebase_DateTime, 'rrule_until of first baseEvent is not set');
     $this->assertTrue($events[0]->rrule_until < new Tinebase_DateTime('2012-02-14 09:00:00'), 'rrule_until of first baseEvent is not adopted properly');
     $this->assertEquals(Calendar_Model_Attender::STATUS_NEEDSACTION, Calendar_Model_Attender::getAttendee($events[0]->attendee, $event->attendee[1])->status, 'first baseEvent status must not be touched');
     $this->assertEquals($events[1]->dtstart, new Tinebase_DateTime('2012-02-14 09:00:00'), 'start of second baseEvent is wrong');
     $this->assertTrue(empty($events[1]->recurid), 'second baseEvent is not a baseEvent');
     $this->assertEquals($events[1]->rrule, $event->rrule, 'rrule of second baseEvent must be set');
     $this->assertFalse($events[1]->rrule_until instanceof Tinebase_DateTime, 'rrule_until of second baseEvent must not be set');
     $this->assertEquals(Calendar_Model_Attender::STATUS_ACCEPTED, Calendar_Model_Attender::getAttendee($events[1]->attendee, $event->attendee[1])->status, 'second baseEvent status is not touched');
 }