/**
  * parse valarm properties
  * 
  * @param Tinebase_Record_Abstract $record
  * @param iteratable $valarms
  * @param \Sabre\VObject\Component $vcalendar
  */
 protected function _parseAlarm(Tinebase_Record_Abstract $record, $valarms, \Sabre\VObject\Component $vcomponent)
 {
     foreach ($valarms as $valarm) {
         if ($valarm->ACTION == 'NONE') {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' We can\'t cope with action NONE: iCal 6.0 sends default alarms in the year 1976 with action NONE. Skipping alarm.');
             }
             continue;
         }
         if (!is_object($valarm->TRIGGER)) {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Alarm has no TRIGGER value. Skipping it.');
             }
             continue;
         }
         # TRIGGER:-PT15M
         if (is_string($valarm->TRIGGER->getValue()) && $valarm->TRIGGER instanceof Sabre\VObject\Property\ICalendar\Duration) {
             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                 Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Adding DURATION trigger value for ' . $valarm->TRIGGER->getValue());
             }
             $valarm->TRIGGER->add('VALUE', 'DURATION');
         }
         $trigger = is_object($valarm->TRIGGER['VALUE']) ? $valarm->TRIGGER['VALUE'] : (is_object($valarm->TRIGGER['RELATED']) ? $valarm->TRIGGER['RELATED'] : NULL);
         if ($trigger === NULL) {
             // added Trigger/Related for eM Client alarms
             // 2014-01-03 - Bullshit, why don't we have testdata for emclient alarms?
             //              this alarm handling should be refactored, the logic is scrambled
             // @see 0006110: handle iMIP messages from outlook
             // @todo fix 0007446: handle broken alarm in outlook invitation message
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Alarm has no TRIGGER value. Skipping it.');
             }
             continue;
         }
         switch (strtoupper($trigger->getValue())) {
             # TRIGGER;VALUE=DATE-TIME:20111031T130000Z
             case 'DATE-TIME':
                 $alarmTime = new Tinebase_DateTime($valarm->TRIGGER->getValue());
                 $alarmTime->setTimezone('UTC');
                 $alarm = new Tinebase_Model_Alarm(array('alarm_time' => $alarmTime, 'minutes_before' => 'custom', 'model' => $this->_modelName));
                 break;
                 # TRIGGER;VALUE=DURATION:-PT1H15M
             # TRIGGER;VALUE=DURATION:-PT1H15M
             case 'DURATION':
             default:
                 $durationBaseTime = isset($vcomponent->DTSTART) ? $vcomponent->DTSTART : $vcomponent->DUE;
                 $alarmTime = $this->_convertToTinebaseDateTime($durationBaseTime);
                 $alarmTime->setTimezone('UTC');
                 preg_match('/(?P<invert>[+-]?)(?P<spec>P.*)/', $valarm->TRIGGER->getValue(), $matches);
                 $duration = new DateInterval($matches['spec']);
                 $duration->invert = !!($matches['invert'] === '-');
                 $alarm = new Tinebase_Model_Alarm(array('alarm_time' => $alarmTime->add($duration), 'minutes_before' => $duration->format('%d') * 60 * 24 + $duration->format('%h') * 60 + $duration->format('%i'), 'model' => $this->_modelName));
                 if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                     Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Adding DURATION alarm ' . print_r($alarm->toArray(), true));
                 }
         }
         if ($valarm->ACKNOWLEDGED) {
             $dtack = $valarm->ACKNOWLEDGED->getDateTime();
             Calendar_Controller_Alarm::setAcknowledgeTime($alarm, $dtack);
         }
         $record->alarms->addRecord($alarm);
     }
 }
 /**
  * send an alarm (to responsible person and if it does not exist, to creator)
  *
  * @param  Tinebase_Model_Alarm $_alarm
  * @return void
  */
 public function sendAlarm(Tinebase_Model_Alarm $_alarm)
 {
     // save and disable container checks to be able to get all required tasks
     $oldCheckValue = $this->_doContainerACLChecks;
     $this->_doContainerACLChecks = FALSE;
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " About to send alarm " . print_r($_alarm->toArray(), TRUE));
     }
     try {
         $task = $this->get($_alarm->record_id);
         if ($task->organizer) {
             $organizerContact = Addressbook_Controller_Contact::getInstance()->getContactByUserId($task->organizer, TRUE);
         } else {
             // use creator as organizer
             $organizerContact = Addressbook_Controller_Contact::getInstance()->getContactByUserId($task->created_by, TRUE);
         }
         // create message
         $translate = Tinebase_Translation::getTranslation($this->_applicationName);
         $messageSubject = $translate->_('Notification for Task ' . $task->summary);
         $messageBody = $task->getNotificationMessage();
         $notificationsBackend = Tinebase_Notification_Factory::getBackend(Tinebase_Notification_Factory::SMTP);
         // send message
         if ($organizerContact->email && !empty($organizerContact->email)) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Trying to send alarm email to ' . $organizerContact->email);
             }
             $notificationsBackend->send(NULL, $organizerContact, $messageSubject, $messageBody);
         } else {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Organizer / creator has no email address.');
             }
         }
     } catch (Exception $e) {
         $this->_doContainerACLChecks = $oldCheckValue;
         throw $e;
     }
 }
 /**
  * inspect alarm and set time
  *
  * @param Tinebase_Record_Abstract $_record
  * @param Tinebase_Model_Alarm $_alarm
  * @return void
  * @throws Tinebase_Exception_InvalidArgument
  */
 protected function _inspectAlarmSet(Tinebase_Record_Abstract $_record, Tinebase_Model_Alarm $_alarm)
 {
     if (!$_record->{$this->_recordAlarmField} instanceof DateTime) {
         throw new Tinebase_Exception_InvalidArgument('alarm reference time is not set');
     }
     $_alarm->setTime($_record->{$this->_recordAlarmField});
 }
 /**
  * converts egw alarms into tine alarms
  * 
  * @param  array $_egwEventData
  * @return Tinebase_Record_RecordSet of Tinebase_Model_Alarm
  */
 protected function _convertAlarms($_egwEventData)
 {
     $alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm');
     $select = $this->_egwDb->select()->from(array('alarms' => 'egw_async'))->where($this->_egwDb->quoteInto($this->_egwDb->quoteIdentifier('async_id') . ' LIKE ?', "cal:{$_egwEventData['cal_id']}:%"));
     $egwAlarms = $this->_egwDb->fetchAll($select, NULL, Zend_Db::FETCH_ASSOC);
     if (count($egwAlarms) == 0) {
         return $alarms;
     }
     foreach ($egwAlarms as $egwAlarm) {
         $egwAlarmData = unserialize($egwAlarm['async_data']);
         $tineAlarm = new Tinebase_Model_Alarm(array('model' => 'Calendar_Model_Event', 'alarm_time' => $this->convertDate($egwAlarmData['time']), 'minutes_before' => $egwAlarmData['offset'] / 60), TRUE);
         $tineAlarm->sent_status = $tineAlarm->alarm_time->isEarlier($this->_migrationStartTime) ? Tinebase_Model_Alarm::STATUS_SUCCESS : Tinebase_Model_Alarm::STATUS_PENDING;
         $tineAlarm->setOption('minutes_before', $tineAlarm->minutes_before);
         $tineAlarm->setOption('custom', false);
         if (isset($_egwEventData['rrule'])) {
             $dtstart = $this->convertDate($egwAlarmData['time'] + $egwAlarmData['offset']);
             $dtstart = $dtstart ? $dtstart : Tinebase_DateTime::now();
             $recurId = $_egwEventData['cal_uid'] . '-' . $dtstart->get(Tinebase_Record_Abstract::ISO8601LONG);
         }
         $tineAlarm->setOption('recurid', isset($_egwEventData['rrule']) ? $recurId : NULL);
         $alarms->addRecord($tineAlarm);
     }
     return $alarms;
 }
 /**
  * sets snoozed time in alarm
  *
  * @param Tinebase_Model_Alarm     $alarm
  * @param DateTime                 $time
  * @param Tinebase_Model_User      $user
  */
 public static function setSnoozeTime($alarm, $time, $user = null)
 {
     $user = $user instanceof Tinebase_Model_User ?: Tinebase_Core::getUser();
     $alarm->setOption("snoozed-{$user->contact_id}", $time->format(Tinebase_Record_Abstract::ISO8601LONG));
 }
 /**
  * send an alarm
  *
  * @param  Tinebase_Model_Alarm $_alarm
  * @return void
  * 
  * NOTE: the given alarm is raw and has not passed _inspectAlarmGet
  *  
  * @todo throw exception on error
  */
 public function sendAlarm(Tinebase_Model_Alarm $_alarm)
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " About to send alarm " . print_r($_alarm->toArray(), TRUE));
     }
     $doContainerACLChecks = $this->doContainerACLChecks(FALSE);
     try {
         $event = $this->get($_alarm->record_id);
         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array($_alarm));
         $this->_inspectAlarmGet($event);
     } catch (Exception $e) {
         $this->doContainerACLChecks($doContainerACLChecks);
         throw $e;
     }
     $this->doContainerACLChecks($doContainerACLChecks);
     if ($event->rrule) {
         $recurid = $_alarm->getOption('recurid');
         // adopts the (referenced) alarm and sets alarm time to next occurance
         parent::_inspectAlarmSet($event, $_alarm);
         $this->adoptAlarmTime($event, $_alarm, 'instance');
         // sent_status might have changed in adoptAlarmTime()
         if ($_alarm->sent_status !== Tinebase_Model_Alarm::STATUS_PENDING) {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Not sending alarm for event at ' . $event->dtstart->toString() . ' with status ' . $_alarm->sent_status);
             }
             return;
         }
         if ($recurid) {
             // NOTE: In case of recuring events $event is always the baseEvent,
             //       so we might need to adopt event time to recur instance.
             $diff = $event->dtstart->diff($event->dtend);
             $event->dtstart = new Tinebase_DateTime(substr($recurid, -19));
             $event->dtend = clone $event->dtstart;
             $event->dtend->add($diff);
         }
         if ($event->exdate && in_array($event->dtstart, $event->exdate)) {
             if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) {
                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Not sending alarm because instance at " . $event->dtstart->toString() . ' is an exception.');
             }
             return;
         }
     }
     Calendar_Controller_EventNotifications::getInstance()->doSendNotifications($event, Tinebase_Core::getUser(), 'alarm', NULL, $_alarm);
 }
 /**
  * checks if given alarm should be send to given attendee
  * 
  * @param  Calendar_Model_Attender $_attendee
  * @param  Tinebase_Model_Alarm    $_alarm
  * @return bool
  */
 public static function isAlarmForAttendee($_attendee, $_alarm, $_event = NULL)
 {
     // attendee: array with one user_type/id if alarm is for one attendee only
     $attendeeOption = $_alarm->getOption('attendee');
     // skip: array of array of user_type/id with attendees this alarm is to skip for
     $skipOption = $_alarm->getOption('skip');
     if ($attendeeOption) {
         return (bool) self::getAttendee(new Tinebase_Record_RecordSet('Calendar_Model_Attender', array($_attendee)), new Calendar_Model_Attender($attendeeOption));
     }
     if (is_array($skipOption)) {
         $skipAttendees = new Tinebase_Record_RecordSet('Calendar_Model_Attender', $skipOption);
         if (self::getAttendee($skipAttendees, $_attendee)) {
             return false;
         }
     }
     $isOrganizerCondition = $_event ? $_event->isOrganizer($_attendee) : TRUE;
     $isAttendeeCondition = $_event && $_event->attendee instanceof Tinebase_Record_RecordSet ? self::getAttendee($_event->attendee, $_attendee) : TRUE;
     return ($isAttendeeCondition || $isOrganizerCondition) && $_attendee->status != Calendar_Model_Attender::STATUS_DECLINED;
 }
예제 #8
0
 /**
  * send an alarm
  *
  * @param  Tinebase_Model_Alarm $_alarm
  * @return void
  * 
  * NOTE: the given alarm is raw and has not passed _inspectAlarmGet
  *  
  * @todo make this working with recuring events
  * @todo throw exception on error
  */
 public function sendAlarm(Tinebase_Model_Alarm $_alarm)
 {
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " About to send alarm " . print_r($_alarm->toArray(), TRUE));
     }
     $doContainerACLChecks = $this->doContainerACLChecks(FALSE);
     $event = $this->get($_alarm->record_id);
     $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array($_alarm));
     $this->_inspectAlarmGet($event);
     if ($event->rrule) {
         $recurid = $_alarm->getOption('recurid');
         // adopts the (referenced) alarm and sets alarm time to next occurance
         parent::_inspectAlarmSet($event, $_alarm);
         $this->adoptAlarmTime($event, $_alarm, 'instance');
         if ($recurid) {
             // NOTE: In case of recuring events $event is always the baseEvent,
             //       so we might need to adopt event time to recur instance.
             $diff = $event->dtstart->diff($event->dtend);
             $event->dtstart = new Tinebase_DateTime(substr($recurid, -19));
             $event->dtend = clone $event->dtstart;
             $event->dtend->add($diff);
         }
     }
     $this->doContainerACLChecks($doContainerACLChecks);
     $this->doSendNotifications($event, $this->_currentAccount, 'alarm');
 }