/**
  * the singleton pattern
  *
  * @return ActiveSync_TimezoneConverter
  */
 public static function getInstance($_logger = null, $_cache = null)
 {
     if (self::$_instance === NULL) {
         self::$_instance = new ActiveSync_TimezoneConverter($_logger, $_cache);
     }
     return self::$_instance;
 }
 /**
  * (non-PHPdoc)
  * @see ActiveSync_Frontend_Abstract::toTineModel()
  */
 public function toTineModel(Syncroton_Model_IEntry $data, $entry = null)
 {
     if ($entry instanceof Calendar_Model_Event) {
         $event = $entry;
     } else {
         $event = new Calendar_Model_Event(array(), true);
     }
     if ($data instanceof Syncroton_Model_Event) {
         $data->copyFieldsFromParent();
     }
     // Update seq to entries seq to prevent concurrent update
     $event->seq = $entry['seq'];
     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " Event before mapping: " . print_r($event->toArray(), true));
     }
     foreach ($this->_mapping as $syncrotonProperty => $tine20Property) {
         if (!isset($data->{$syncrotonProperty})) {
             if ($tine20Property === 'description' && $this->_device->devicetype == Syncroton_Model_Device::TYPE_IPHONE) {
                 // @see #8230: added alarm to event on iOS 6.1 -> description removed
                 // this should be removed when Tine 2.0 / Syncroton supports ghosted properties
                 if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                     Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Unsetting description');
                 }
                 unset($event->{$tine20Property});
             } else {
                 if ($tine20Property === 'attendee' && $entry && $this->_device->devicetype === Syncroton_Model_Device::TYPE_IPHONE && $entry->container_id !== $this->_getDefaultContainerId()) {
                     // keep attendees as the are / they were not sent to the device before
                 } else {
                     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Removing ' . $tine20Property);
                     }
                     $event->{$tine20Property} = null;
                 }
             }
             continue;
         }
         switch ($tine20Property) {
             case 'alarms':
                 // handled after switch statement
                 break;
             case 'attendee':
                 if ($entry && $this->_device->devicetype === Syncroton_Model_Device::TYPE_IPHONE && $entry->container_id !== $this->_getDefaultContainerId()) {
                     // keep attendees as the are / they were not sent to the device before
                     continue;
                 }
                 $newAttendees = array();
                 foreach ($data->{$syncrotonProperty} as $attendee) {
                     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " attendee email " . $attendee->email);
                     }
                     if (isset($attendee->attendeeType) && (isset($this->_attendeeTypeMapping[$attendee->attendeeType]) || array_key_exists($attendee->attendeeType, $this->_attendeeTypeMapping))) {
                         $role = $this->_attendeeTypeMapping[$attendee->attendeeType];
                     } else {
                         $role = Calendar_Model_Attender::ROLE_REQUIRED;
                     }
                     // AttendeeStatus send only on repsonse
                     if (preg_match('/(?P<firstName>\\S*) (?P<lastNameName>\\S*)/', $attendee->name, $matches)) {
                         $firstName = $matches['firstName'];
                         $lastName = $matches['lastNameName'];
                     } else {
                         $firstName = null;
                         $lastName = $attendee->name;
                     }
                     // @todo handle resources
                     $newAttendees[] = array('userType' => Calendar_Model_Attender::USERTYPE_USER, 'firstName' => $firstName, 'lastName' => $lastName, 'role' => $role, 'email' => $attendee->email);
                 }
                 Calendar_Model_Attender::emailsToAttendee($event, $newAttendees);
                 break;
             case 'class':
                 $event->{$tine20Property} = $data->{$syncrotonProperty} == 2 ? Calendar_Model_Event::CLASS_PRIVATE : Calendar_Model_Event::CLASS_PUBLIC;
                 break;
             case 'exdate':
                 // handle exceptions from recurrence
                 $exdates = new Tinebase_Record_RecordSet('Calendar_Model_Event');
                 foreach ($data->{$syncrotonProperty} as $exception) {
                     if ($exception->deleted == 0) {
                         $eventException = $this->toTineModel($exception);
                         $eventException->last_modified_time = new Tinebase_DateTime($this->_syncTimeStamp);
                         $eventException->recurid = new Tinebase_DateTime($exception->exceptionStartTime);
                         $eventException->is_deleted = false;
                     } else {
                         $eventException = new Calendar_Model_Event(array('recurid' => new Tinebase_DateTime($exception->exceptionStartTime), 'is_deleted' => true));
                     }
                     $eventException->seq = $entry['seq'];
                     $exdates->addRecord($eventException);
                 }
                 $event->{$tine20Property} = $exdates;
                 break;
             case 'description':
                 // @todo check $data->$fieldName->Type and convert to/from HTML if needed
                 if ($data->{$syncrotonProperty} instanceof Syncroton_Model_EmailBody) {
                     $event->{$tine20Property} = $data->{$syncrotonProperty}->data;
                 } else {
                     if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) {
                         Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Removing description.');
                     }
                     $event->{$tine20Property} = null;
                 }
                 break;
             case 'rrule':
                 // handle recurrence
                 if ($data->{$syncrotonProperty} instanceof Syncroton_Model_EventRecurrence && isset($data->{$syncrotonProperty}->type)) {
                     $rrule = new Calendar_Model_Rrule();
                     switch ($data->{$syncrotonProperty}->type) {
                         case Syncroton_Model_EventRecurrence::TYPE_DAILY:
                             $rrule->freq = Calendar_Model_Rrule::FREQ_DAILY;
                             break;
                         case Syncroton_Model_EventRecurrence::TYPE_WEEKLY:
                             $rrule->freq = Calendar_Model_Rrule::FREQ_WEEKLY;
                             $rrule->byday = $this->_convertBitMaskToDay($data->{$syncrotonProperty}->dayOfWeek);
                             break;
                         case Syncroton_Model_EventRecurrence::TYPE_MONTHLY:
                             $rrule->freq = Calendar_Model_Rrule::FREQ_MONTHLY;
                             $rrule->bymonthday = $data->{$syncrotonProperty}->dayOfMonth;
                             break;
                         case Syncroton_Model_EventRecurrence::TYPE_MONTHLY_DAYN:
                             $rrule->freq = Calendar_Model_Rrule::FREQ_MONTHLY;
                             $week = $data->{$syncrotonProperty}->weekOfMonth;
                             $day = $data->{$syncrotonProperty}->dayOfWeek;
                             $byDay = $week == 5 ? -1 : $week;
                             $byDay .= $this->_convertBitMaskToDay($day);
                             $rrule->byday = $byDay;
                             break;
                         case Syncroton_Model_EventRecurrence::TYPE_YEARLY:
                             $rrule->freq = Calendar_Model_Rrule::FREQ_YEARLY;
                             $rrule->bymonth = $data->{$syncrotonProperty}->monthOfYear;
                             $rrule->bymonthday = $data->{$syncrotonProperty}->dayOfMonth;
                             break;
                         case Syncroton_Model_EventRecurrence::TYPE_YEARLY_DAYN:
                             $rrule->freq = Calendar_Model_Rrule::FREQ_YEARLY;
                             $rrule->bymonth = $data->{$syncrotonProperty}->monthOfYear;
                             $week = $data->{$syncrotonProperty}->weekOfMonth;
                             $day = $data->{$syncrotonProperty}->dayOfWeek;
                             $byDay = $week == 5 ? -1 : $week;
                             $byDay .= $this->_convertBitMaskToDay($day);
                             $rrule->byday = $byDay;
                             break;
                     }
                     $rrule->interval = isset($data->{$syncrotonProperty}->interval) ? $data->{$syncrotonProperty}->interval : 1;
                     if (isset($data->{$syncrotonProperty}->occurrences)) {
                         $rrule->count = $data->{$syncrotonProperty}->occurrences;
                         $rrule->until = null;
                     } else {
                         if (isset($data->{$syncrotonProperty}->until)) {
                             $rrule->count = null;
                             $rrule->until = new Tinebase_DateTime($data->{$syncrotonProperty}->until);
                         } else {
                             $rrule->count = null;
                             $rrule->until = null;
                         }
                     }
                     $event->rrule = $rrule;
                 }
                 break;
             default:
                 if ($data->{$syncrotonProperty} instanceof DateTime) {
                     $event->{$tine20Property} = new Tinebase_DateTime($data->{$syncrotonProperty});
                 } else {
                     $event->{$tine20Property} = $data->{$syncrotonProperty};
                 }
                 break;
         }
     }
     // whole day events ends at 23:59:59 in Tine 2.0 but 00:00 the next day in AS
     if (isset($event->is_all_day_event) && $event->is_all_day_event == 1) {
         $event->dtend->subSecond(1);
     }
     // decode timezone data
     if (isset($data->timezone)) {
         $timeZoneConverter = ActiveSync_TimezoneConverter::getInstance(Tinebase_Core::getLogger(), Tinebase_Core::get(Tinebase_Core::CACHE));
         try {
             $timezone = $timeZoneConverter->getTimezone($data->timezone, Tinebase_Core::getUserTimezone());
             $event->originator_tz = $timezone;
         } catch (ActiveSync_TimezoneNotFoundException $e) {
             Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . " timezone data not found " . $data->timezone);
             $event->originator_tz = Tinebase_Core::getUserTimezone();
         }
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " timezone data " . $event->originator_tz);
         }
     }
     $this->_handleAlarms($data, $event);
     $this->_handleBusyStatus($data, $event);
     // event should be valid now
     $event->isValid();
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " eventData " . print_r($event->toArray(), true));
     }
     return $event;
 }
 public function setUp()
 {
     $this->_uit = ActiveSync_TimezoneConverter::getInstance(Tinebase_Core::getLogger());
 }
Exemple #4
0
 public static function getVtimezone($tzName)
 {
     $tzinfo = ActiveSync_TimezoneConverter::getInstance()->getOffsetsForTimezone($tzName);
     $standardOffset = (-1 * $tzinfo['bias'] > 0 ? '+' : '-') . str_pad((string) floor(-1 * $tzinfo['bias'] / 60), 2, 0, STR_PAD_LEFT) . str_pad((string) floor(-1 * $tzinfo['bias'] % 60), 2, 0, STR_PAD_LEFT);
     $daylightOffset = (-1 * ($tzinfo['bias'] + $tzinfo['daylightBias']) > 0 ? '+' : '-') . str_pad((string) floor(-1 * ($tzinfo['bias'] + $tzinfo['daylightBias']) / 60), 2, 0, STR_PAD_LEFT) . str_pad((string) floor(-1 * ($tzinfo['bias'] + $tzinfo['daylightBias']) % 60), 2, 0, STR_PAD_LEFT);
     return new qCal_Component_Vtimezone(array('tzid' => $tzName), array(new qCal_Component_Daylight(array('tzoffsetfrom' => $standardOffset, 'tzoffsetto' => $daylightOffset, 'rrule' => "FREQ=YEARLY;BYMONTH={$tzinfo['daylightMonth']};BYDAY=" . ($tzinfo['daylightDay'] < 5 ? $tzinfo['daylightDay'] : '-1') . array_search($tzinfo['daylightDayOfWeek'], Calendar_Model_Rrule::$WEEKDAY_DIGIT_MAP))), new qCal_Component_Standard(array('tzoffsetfrom' => $daylightOffset, 'tzoffsetto' => $standardOffset, 'rrule' => "FREQ=YEARLY;BYMONTH={$tzinfo['standardMonth']};BYDAY=" . ($tzinfo['daylightDay'] < 5 ? $tzinfo['daylightDay'] : '-1') . array_search($tzinfo['standardDayOfWeek'], Calendar_Model_Rrule::$WEEKDAY_DIGIT_MAP)))));
 }
Exemple #5
0
 function getASTimezone($_timezone, $_startDate = null)
 {
     $TZconverter = ActiveSync_TimezoneConverter::getInstance();
     return $TZconverter->encodeTimezone($_timezone, $_startDate = null);
 }
 /**
  * convert contact from xml to Calendar_Model_Event
  *
  * @todo handle BusyStatus
  * @param SimpleXMLElement $_data
  * @return Calendar_Model_Event
  */
 public function toTineModel(SimpleXMLElement $_data, $_entry = null)
 {
     if ($_entry instanceof Calendar_Model_Event) {
         $event = $_entry;
     } else {
         $event = new Calendar_Model_Event(array(), true);
     }
     $xmlData = $_data->children('uri:Calendar');
     $airSyncBase = $_data->children('uri:AirSyncBase');
     foreach ($this->_mapping as $fieldName => $value) {
         switch ($value) {
             case 'dtend':
             case 'dtstart':
                 if (isset($xmlData->{$fieldName})) {
                     $event->{$value} = new Tinebase_DateTime((string) $xmlData->{$fieldName});
                 } else {
                     $event->{$value} = null;
                 }
                 break;
             default:
                 if (isset($xmlData->{$fieldName})) {
                     $event->{$value} = (string) $xmlData->{$fieldName};
                 } else {
                     $event->{$value} = null;
                 }
                 break;
         }
     }
     // get body
     if (version_compare($this->_device->acsversion, '12.0', '>=') === true) {
         $event->description = isset($airSyncBase->Body) ? (string) $airSyncBase->Body->Data : null;
     } else {
         $event->description = isset($xmlData->Body) ? (string) $xmlData->Body : null;
     }
     // whole day events ends at 23:59:59 in Tine 2.0 but 00:00 the next day in AS
     if (isset($xmlData->AllDayEvent) && $xmlData->AllDayEvent == 1) {
         $event->dtend->subSecond(1);
     }
     if (isset($xmlData->Reminder)) {
         $alarm = clone $event->dtstart;
         $event->alarms = new Tinebase_Record_RecordSet('Tinebase_Model_Alarm', array(array('alarm_time' => $alarm->subMinute((int) $xmlData->Reminder), 'minutes_before' => (int) $xmlData->Reminder, 'model' => 'Calendar_Model_Event')));
     }
     // decode timezone data
     if (isset($xmlData->Timezone)) {
         $timeZoneConverter = ActiveSync_TimezoneConverter::getInstance(Tinebase_Core::getLogger(), Tinebase_Core::get(Tinebase_Core::CACHE));
         try {
             $timezone = $timeZoneConverter->getTimezone((string) $xmlData->Timezone, Tinebase_Core::get(Tinebase_Core::USERTIMEZONE));
             $event->originator_tz = $timezone;
         } catch (ActiveSync_TimezoneNotFoundException $e) {
             Tinebase_Core::getLogger()->crit(__METHOD__ . '::' . __LINE__ . " timezone data not found " . (string) $xmlData->Timezone);
             $event->originator_tz = Tinebase_Core::get(Tinebase_Core::USERTIMEZONE);
         }
         if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
             Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " timezone data " . $event->originator_tz);
         }
     }
     if (!$event->attendee instanceof Tinebase_Record_RecordSet) {
         $event->attendee = new Tinebase_Record_RecordSet('Calendar_Model_Attender');
     }
     if (isset($xmlData->Attendees)) {
         $newAttendees = array();
         foreach ($xmlData->Attendees->Attendee as $attendee) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " attendee email " . $attendee->Email);
             }
             if (isset($attendee->AttendeeType) && array_key_exists((int) $attendee->AttendeeType, $this->_attendeeTypeMapping)) {
                 $role = $this->_attendeeTypeMapping[(int) $attendee->AttendeeType];
             } else {
                 $role = Calendar_Model_Attender::ROLE_REQUIRED;
             }
             // AttendeeStatus send only on repsonse
             if (preg_match('/(?P<firstName>\\S*) (?P<lastNameName>\\S*)/', (string) $attendee->Name, $matches)) {
                 $firstName = $matches['firstName'];
                 $lastName = $matches['lastNameName'];
             } else {
                 $firstName = null;
                 $lastName = $attendee->Name;
             }
             // @todo handle resources
             $newAttendees[] = array('userType' => Calendar_Model_Attender::USERTYPE_USER, 'firstName' => $firstName, 'lastName' => $lastName, 'role' => $role, 'email' => (string) $attendee->Email);
         }
         Calendar_Model_Attender::emailsToAttendee($event, $newAttendees);
     }
     // new event, add current user as participant
     if ($event->getId() == null) {
         $selfContactId = Tinebase_Core::getUser()->contact_id;
         $selfAttender = $event->attendee->filter('user_type', Calendar_Model_Attender::USERTYPE_USER)->filter('user_id', $selfContactId);
         if (count($selfAttender) == 0) {
             if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
                 Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " added current user as attender for new event ");
             }
             $newAttender = new Calendar_Model_Attender(array('user_id' => $selfContactId, 'user_type' => Calendar_Model_Attender::USERTYPE_USER, 'status' => Calendar_Model_Attender::STATUS_ACCEPTED, 'role' => Calendar_Model_Attender::ROLE_REQUIRED));
             $event->attendee->addRecord($newAttender);
         }
     }
     if (isset($xmlData->BusyStatus) && ($ownAttendee = Calendar_Model_Attender::getOwnAttender($event->attendee)) !== null) {
         if (isset($this->_busyStatusMapping[(string) $xmlData->BusyStatus])) {
             $ownAttendee->status = $this->_busyStatusMapping[(string) $xmlData->BusyStatus];
         } else {
             $ownAttendee->status = Calendar_Model_Attender::STATUS_NEEDSACTION;
         }
     }
     // handle recurrence
     if (isset($xmlData->Recurrence) && isset($xmlData->Recurrence->Type)) {
         $rrule = new Calendar_Model_Rrule();
         switch ((int) $xmlData->Recurrence->Type) {
             case self::RECUR_TYPE_DAILY:
                 $rrule->freq = Calendar_Model_Rrule::FREQ_DAILY;
                 break;
             case self::RECUR_TYPE_WEEKLY:
                 $rrule->freq = Calendar_Model_Rrule::FREQ_WEEKLY;
                 $rrule->byday = $this->_convertBitMaskToDay((int) $xmlData->Recurrence->DayOfWeek);
                 break;
             case self::RECUR_TYPE_MONTHLY:
                 $rrule->freq = Calendar_Model_Rrule::FREQ_MONTHLY;
                 $rrule->bymonthday = (int) $xmlData->Recurrence->DayOfMonth;
                 break;
             case self::RECUR_TYPE_MONTHLY_DAYN:
                 $rrule->freq = Calendar_Model_Rrule::FREQ_MONTHLY;
                 $week = (int) $xmlData->Recurrence->WeekOfMonth;
                 $day = (int) $xmlData->Recurrence->DayOfWeek;
                 $byDay = $week == 5 ? -1 : $week;
                 $byDay .= $this->_convertBitMaskToDay($day);
                 $rrule->byday = $byDay;
                 break;
             case self::RECUR_TYPE_YEARLY:
                 $rrule->freq = Calendar_Model_Rrule::FREQ_YEARLY;
                 $rrule->bymonth = (int) $xmlData->Recurrence->MonthOfYear;
                 $rrule->bymonthday = (int) $xmlData->Recurrence->DayOfMonth;
                 break;
             case self::RECUR_TYPE_YEARLY_DAYN:
                 $rrule->freq = Calendar_Model_Rrule::FREQ_YEARLY;
                 $rrule->bymonth = (int) $xmlData->Recurrence->MonthOfYear;
                 $week = (int) $xmlData->Recurrence->WeekOfMonth;
                 $day = (int) $xmlData->Recurrence->DayOfWeek;
                 $byDay = $week == 5 ? -1 : $week;
                 $byDay .= $this->_convertBitMaskToDay($day);
                 $rrule->byday = $byDay;
                 break;
         }
         $rrule->interval = isset($xmlData->Recurrence->Interval) ? (int) $xmlData->Recurrence->Interval : 1;
         if (isset($xmlData->Recurrence->Until)) {
             $rrule->until = new Tinebase_DateTime((string) $xmlData->Recurrence->Until);
             // until ends at 23:59:59 in Tine 2.0 but at 00:00:00 in Windows CE (local user time)
             if ($rrule->until->format('s') == '00') {
                 $rrule->until->addHour(23)->addMinute(59)->addSecond(59);
             }
         } else {
             $rrule->until = null;
         }
         $event->rrule = $rrule;
         // handle exceptions from recurrence
         if (isset($xmlData->Exceptions)) {
             $exdates = new Tinebase_Record_RecordSet('Calendar_Model_Event');
             foreach ($xmlData->Exceptions->Exception as $exception) {
                 $eventException = new Calendar_Model_Event(array('recurid' => new Tinebase_DateTime((string) $exception->ExceptionStartTime)));
                 if ((int) $exception->Deleted === 0) {
                     $eventException->is_deleted = false;
                     $this->toTineModel($exception, $eventException);
                 } else {
                     $eventException->is_deleted = true;
                 }
                 $exdates->addRecord($eventException);
             }
             $event->exdate = $exdates;
         }
     } else {
         $event->rrule = null;
         $event->exdate = null;
     }
     if (empty($event->organizer)) {
         $event->organizer = Tinebase_Core::getUser()->contact_id;
     }
     // event should be valid now
     $event->isValid();
     if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) {
         Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " eventData " . print_r($event->toArray(), true));
     }
     return $event;
 }