/** * convert Tasks_Model_Task to \Sabre\VObject\Component * * @param Tasks_Model_Task $_record * @return \Sabre\VObject\Component */ public function fromTine20Model(Tinebase_Record_Abstract $_record) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' event ' . print_r($_record->toArray(), true)); } $vcalendar = new \Sabre\VObject\Component\VCalendar(); // required vcalendar fields $version = Tinebase_Application::getInstance()->getApplicationByName('Tasks')->version; $vcalendar->PRODID = "-//tine20.com//Tine 2.0 Tasks V{$version}//EN"; $vcalendar->VERSION = '2.0'; $vcalendar->CALSCALE = 'GREGORIAN'; // catch exceptions for unknown timezones try { $vcalendar->add(new Sabre_VObject_Component_VTimezone($_record->originator_tz)); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::WARN)) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' timezone exception ' . $e->getMessage()); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' timezone exception ' . $e->getTraceAsString()); } } $this->_convertTasksModelTask($vcalendar, $_record); $this->_afterFromTine20Model($vcalendar); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' card ' . $vcalendar->serialize()); } return $vcalendar; }
/** * converts Addressbook_Model_Contact to vcard * * @param Addressbook_Model_Contact $_record * @return \Sabre\VObject\Component\VCard */ public function fromTine20Model(Tinebase_Record_Abstract $_record) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' contact ' . print_r($_record->toArray(), true)); } // initialize vcard object $card = $this->_fromTine20ModelRequiredFields($_record); $card->add('TEL', $_record->tel_work, array('TYPE' => array('WORK', 'VOICE'))); $card->add('TEL', $_record->tel_home, array('TYPE' => array('HOME', 'VOICE'))); $card->add('TEL', $_record->tel_cell, array('TYPE' => 'CELL')); $card->add('TEL', $_record->tel_cell_private, array('TYPE' => 'OTHER')); $card->add('TEL', $_record->tel_fax, array('TYPE' => array('FAX', 'WORK'))); $card->add('TEL', $_record->tel_fax_home, array('TYPE' => array('FAX', 'HOME'))); $card->add('ADR', array(null, $_record->adr_one_street2, $_record->adr_one_street, $_record->adr_one_locality, $_record->adr_one_region, $_record->adr_one_postalcode, $_record->adr_one_countryname), array('TYPE' => 'WORK')); $card->add('ADR', array(null, $_record->adr_two_street2, $_record->adr_two_street, $_record->adr_two_locality, $_record->adr_two_region, $_record->adr_two_postalcode, $_record->adr_two_countryname), array('TYPE' => 'HOME')); $card->add('EMAIL', $_record->email, array('TYPE' => 'PREF')); $card->add('EMAIL', $_record->email_home); $card->add('URL', $_record->url, array('TYPE' => 'WORK')); $card->add('URL', $_record->url_home, array('TYPE' => 'HOME')); $card->add('NOTE', $_record->note); $this->_fromTine20ModelAddBirthday($_record, $card); $this->_fromTine20ModelAddPhoto($_record, $card); $this->_fromTine20ModelAddGeoData($_record, $card); $this->_fromTine20ModelAddCategories($_record, $card); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' card ' . $card->serialize()); } return $card; }
/** * returns array with record related properties * * @param boolean $_recursive * @return array */ public function toArray($_recursive = TRUE) { $array = parent::toArray($_recursive); // remove highly sensitive data to prevent accidental apperance in logs etc. unset($array['key']); unset($array['username']); unset($array['password']); return $array; }
/** * converts record into raw data for adapter * * @param Tinebase_Record_Abstract $_record * @return array */ protected function _recordToRawData($_record) { if (is_object($_record->filters)) { $_record->filters->removeId(); } $rawData = $_record->toArray(); $rawData['filters'] = Zend_Json::encode($rawData['filters']); return $rawData; }
/** * returns array with record related properties * * @param boolean $_recursive * @return array */ public function toArray($_recursive = TRUE) { $recordArray = parent::toArray($_recursive); if ($_recursive && isset($recordArray['diff'])) { foreach ($recordArray['diff'] as $property => $value) { if ($this->_hasToArray($value)) { $recordArray['diff'][$property] = $value->toArray(); } } } return $recordArray; }
/** * returns array with record related properties * resolves the creator display name and calls Tinebase_Record_Abstract::toArray() * * @param boolean $_recursive * @param boolean $_resolveCreator * @return array */ public function toArray($_recursive = TRUE, $_resolveCreator = TRUE) { $result = parent::toArray($_recursive); // get creator if ($this->created_by && $_resolveCreator) { //resolve creator; return default NonExistentUser-Object if creator cannot be resolved => //@todo perhaps we should add a "getNonExistentUserIfNotExists" parameter to Tinebase_User::getUserById try { $creator = Tinebase_User::getInstance()->getUserById($this->created_by); } catch (Tinebase_Exception_NotFound $e) { $creator = Tinebase_User::getInstance()->getNonExistentUser(); } $result['created_by'] = $creator->accountDisplayName; } return $result; }
/** * convert Calendar_Model_Event to Sabre_VObject_Component * * @param Calendar_Model_Event $_record * @return Sabre_VObject_Component */ public function fromTine20Model(Tinebase_Record_Abstract $_record) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' event ' . print_r($_record->toArray(), true)); } $vcalendar = new Sabre_VObject_Component('VCALENDAR'); // required vcalendar fields $version = Tinebase_Application::getInstance()->getApplicationByName('Calendar')->version; if (isset($this->_method)) { $vcalendar->METHOD = $this->_method; } $vcalendar->PRODID = "-//tine20.org//Tine 2.0 Calendar V{$version}//EN"; $vcalendar->VERSION = '2.0'; $vcalendar->CALSCALE = 'GREGORIAN'; $vtimezone = $this->_convertDateTimezone($_record->originator_tz); $vcalendar->add($vtimezone); $vevent = $this->_convertCalendarModelEvent($_record); $vcalendar->add($vevent); if ($_record->exdate instanceof Tinebase_Record_RecordSet) { $eventExceptions = $_record->exdate->filter('is_deleted', false); foreach ($eventExceptions as $eventException) { // set timefields // @todo move to MS event facade $eventException->creation_time = $_record->creation_time; if (isset($_record->last_modified_time)) { $eventException->last_modified_time = $_record->last_modified_time; } $vevent = $this->_convertCalendarModelEvent($eventException, $_record); $vcalendar->add($vevent); } } $this->_afterFromTine20Model($vcalendar); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' card ' . $vcalendar->serialize()); } return $vcalendar; }
/** * converts Addressbook_Model_Contact to vcard * * @param Addressbook_Model_Contact $_record * @return string */ public function fromTine20Model(Tinebase_Record_Abstract $_record) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' contact ' . print_r($_record->toArray(), true)); } $card = new Sabre_VObject_Component('VCARD'); // required vcard fields $card->add(new Sabre_VObject_Property('VERSION', '3.0')); $card->add(new Sabre_VObject_Property('FN', $_record->n_fileas)); $card->add(new Sabre_VObject_Element_MultiValue('N', array($_record->n_family, $_record->n_given))); $card->add(new Sabre_VObject_Property('PRODID', '-//tine20.org//Tine 2.0//EN')); $card->add(new Sabre_VObject_Property('UID', $_record->getId())); // optional fields $card->add(new Sabre_VObject_Element_MultiValue('ORG', array($_record->org_name, $_record->org_unit))); $card->add(new Sabre_VObject_Property('TITLE', $_record->title)); $tel = new Sabre_VObject_Property('TEL', $_record->tel_work); $tel->add('TYPE', 'WORK'); $card->add($tel); $tel = new Sabre_VObject_Property('TEL', $_record->tel_home); $tel->add('TYPE', 'HOME'); $card->add($tel); $tel = new Sabre_VObject_Property('TEL', $_record->tel_cell); $tel->add('TYPE', 'CELL'); $card->add($tel); $tel = new Sabre_VObject_Property('TEL', $_record->tel_pager); $tel->add('TYPE', 'PAGER'); $card->add($tel); $tel = new Sabre_VObject_Property('TEL', $_record->tel_fax); $tel->add('TYPE', 'FAX'); $card->add($tel); #$tel = new Sabre_VObject_Property('TEL', $_record->tel_fax_home); #$tel->add('TYPE', 'FAX'); #$tel->add('TYPE', 'HOME'); #$card->add($tel); $adr = new Sabre_VObject_Element_MultiValue('ADR', array(null, $_record->adr_one_street2, $_record->adr_one_street, $_record->adr_one_locality, $_record->adr_one_region, $_record->adr_one_postalcode, $_record->adr_one_countryname)); $adr->add('TYPE', 'WORK'); $card->add($adr); $adr = new Sabre_VObject_Element_MultiValue('ADR', array(null, $_record->adr_two_street2, $_record->adr_two_street, $_record->adr_two_locality, $_record->adr_two_region, $_record->adr_two_postalcode, $_record->adr_two_countryname)); $adr->add('TYPE', 'HOME'); $card->add($adr); $card->add(new Sabre_VObject_Property('EMAIL;TYPE=work', $_record->email)); $card->add(new Sabre_VObject_Property('EMAIL;TYPE=home', $_record->email_home)); $card->add(new Sabre_VObject_Property('URL;TYPE=work', $_record->url)); $card->add(new Sabre_VObject_Property('URL;TYPE=home', $_record->url_home)); $card->add(new Sabre_VObject_Property('NOTE', $_record->note)); if (!empty($_record->jpegphoto)) { try { $image = Tinebase_Controller::getInstance()->getImage('Addressbook', $_record->getId()); $jpegData = $image->getBlob('image/jpeg'); $photo = new Sabre_VObject_Property('PHOTO', $jpegData); $photo->add('ENCODING', 'b'); $photo->add('TYPE', 'JPEG'); $card->add($photo); } catch (Exception $e) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Image for contact {$_record->getId()} not found or invalid"); } } if (isset($_record->tags) && count($_record->tags) > 0) { $card->add(new Sabre_VObject_Property('CATEGORIES', Sabre_VObject_Element_List((array) $_record->tags->name))); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' card ' . $card->serialize()); } return $card; }
/** * to array * * @param boolean $_recursive */ public function toArray($_recursive = TRUE) { $result = parent::toArray($_recursive); // don't show password unset($result['password']); unset($result['smtp_password']); return $result; }
/** * computes changes of records and writes them to the logbook * * NOTE: expects last_modified_by and last_modified_time to be set * properly in the $_newRecord * * @param Tinebase_Record_Abstract $_newRecord record from user data * @param Tinebase_Record_Abstract $_curRecord record from storage * @param string $_model * @param string $_backend * @param string $_id * @return Tinebase_Record_RecordSet RecordSet of Tinebase_Model_ModificationLog */ public function writeModLog($_newRecord, $_curRecord, $_model, $_backend, $_id) { $commonModLog = $this->_getCommonModlog($_model, $_backend, array('last_modified_time' => $_newRecord->last_modified_time, 'last_modified_by' => $_newRecord->last_modified_by), $_id); $diffs = $_curRecord->diff($_newRecord); if (!empty($diffs) && Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' diffs: ' . print_r($diffs, TRUE)); } if (!empty($diffs) && Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' curRecord: ' . print_r($_curRecord->toArray(), TRUE)); } $modifications = new Tinebase_Record_RecordSet('Tinebase_Model_ModificationLog'); $this->_loopModifications($diffs, $commonModLog, $modifications, $_curRecord->toArray(), $_curRecord->getModlogOmitFields()); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Logged ' . count($modifications) . ' modifications.'); } return $modifications; }
/** * import record and resolve possible conflicts * * supports $_resolveStrategy(s): ['mergeTheirs', ('Merge, keeping existing details')], * ['mergeMine', ('Merge, keeping my details')], * ['keep', ('Keep both records')] * * @param Tinebase_Record_Abstract $record * @param string $resolveStrategy * @param Tinebase_Record_Abstract $clientRecord * @return Tinebase_Record_Abstract * * @todo we should refactor the merge handling: this function should always get the merged record OR always do the merging itself */ protected function _importAndResolveConflict(Tinebase_Record_Abstract $record, $resolveStrategy = null, $clientRecord = null) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ResolveStrategy: ' . $resolveStrategy); } if ($clientRecord && Tinebase_Core::isLogLevel(Zend_Log::TRACE) && $clientRecord) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Client record: ' . print_r($clientRecord->toArray(), TRUE)); } switch ($resolveStrategy) { case 'mergeTheirs': case 'mergeMine': if ($clientRecord) { if ($resolveStrategy === 'mergeTheirs') { $recordToUpdate = $this->_mergeRecord($record, $clientRecord); } else { $recordToUpdate = $this->_mergeRecord($clientRecord, $record); } } else { $recordToUpdate = $record; } if ($recordToUpdate !== null) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE) && $clientRecord) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Merged record: ' . print_r($record->toArray(), TRUE)); } $record = call_user_func(array($this->_controller, $this->_options['updateMethod']), $recordToUpdate, FALSE); } break; case 'keep': if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Record to import (keep both / no duplicate check): ' . print_r($record->toArray(), TRUE)); } $record = call_user_func(array($this->_controller, $this->_options['createMethod']), $record, FALSE); break; default: if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Record to import: ' . print_r($record->toArray(), TRUE)); } $record = call_user_func(array($this->_controller, $this->_options['createMethod']), $record); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' record: ' . print_r($record->toArray(), TRUE)); } return $record; }
/** * adopt alarm time to next occurrence for recurring events * * @param Tinebase_Record_Abstract $_record * @param Tinebase_Model_Alarm $_alarm * @param bool $_nextBy {instance|time} set recurr alarm to next from given instance or next by current time * @return void */ public function adoptAlarmTime(Tinebase_Record_Abstract $_record, Tinebase_Model_Alarm $_alarm, $_nextBy = 'time') { if ($_record->rrule) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Adopting alarm time for next recur occurrence (by ' . $_nextBy . ')'); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . print_r($_record->toArray(), TRUE)); } if ($_nextBy == 'time') { // NOTE: this also finds instances running right now $from = Tinebase_DateTime::now(); } else { $recurid = $_alarm->getOption('recurid'); $instanceStart = $recurid ? new Tinebase_DateTime(substr($recurid, -19)) : clone $_record->dtstart; $eventLength = $_record->dtstart->diff($_record->dtend); $instanceStart->setTimezone($_record->originator_tz); $from = $instanceStart->add($eventLength); $from->setTimezone('UTC'); } // compute next $exceptions = $this->getRecurExceptions($_record); $nextOccurrence = Calendar_Model_Rrule::computeNextOccurrence($_record, $exceptions, $from); if ($nextOccurrence === NULL) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' Recur series is over, no more alarms pending'); } } else { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Found next occurrence, adopting alarm to dtstart ' . $nextOccurrence->dtstart->toString()); } } // save recurid so we know for which recurrance the alarm is for $_alarm->setOption('recurid', isset($nextOccurrence) ? $nextOccurrence->recurid : NULL); $_alarm->sent_status = $nextOccurrence ? Tinebase_Model_Alarm::STATUS_PENDING : Tinebase_Model_Alarm::STATUS_SUCCESS; $_alarm->sent_message = $nextOccurrence ? '' : 'Nothing to send, series is over'; $eventStart = $nextOccurrence ? clone $nextOccurrence->dtstart : clone $_record->dtstart; } else { $eventStart = clone $_record->dtstart; } // save minutes before / compute it for custom alarms $minutesBefore = $_alarm->minutes_before == Tinebase_Model_Alarm::OPTION_CUSTOM ? ($_record->dtstart->getTimestamp() - $_alarm->alarm_time->getTimestamp()) / 60 : $_alarm->minutes_before; $minutesBefore = round($minutesBefore); $_alarm->setOption('minutes_before', $minutesBefore); $_alarm->alarm_time = $eventStart->subMinute($minutesBefore); if ($_record->rrule && $_alarm->sent_status == Tinebase_Model_Alarm::STATUS_PENDING && $_alarm->alarm_time < $_alarm->sent_time) { $this->adoptAlarmTime($_record, $_alarm, 'instance'); } if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' alarm: ' . print_r($_alarm->toArray(), true)); } }
/** * handle import exceptions * * @param Exception $_e * @param integer $_recordIndex * @param Tinebase_Record_Abstract|array $_record * * @todo use json converter for client record */ protected function _handleImportException(Exception $_e, $_recordIndex, $_record = NULL) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . $_e->getMessage()); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $_e->getTraceAsString()); } if ($_e instanceof Tinebase_Exception_Duplicate) { $this->_importResult['duplicatecount']++; $exception = $_e->toArray(); } else { $this->_importResult['failcount']++; $exception = array('code' => $_e->getCode(), 'message' => $_e->getMessage(), 'clientRecord' => $_record !== NULL && $_record instanceof Tinebase_Record_Abstract ? $_record->toArray() : (is_array($_record) ? $_record : array())); } $this->_importResult['exceptions']->addRecord(new Tinebase_Model_ImportException(array('code' => $_e->getCode(), 'message' => $_e->getMessage(), 'exception' => $exception, 'index' => $_recordIndex))); }
/** * converts record into raw data for adapter * * @param Tinebase_Record_Abstract $_record * @return array */ protected function _recordToRawData($_record) { $_record->runConvertToData(); $readOnlyFields = $_record->getReadOnlyFields(); $raw = $_record->toArray(FALSE); foreach ($raw as $key => $value) { if ($value instanceof Tinebase_Record_Interface) { $raw[$key] = $value->getId(); } if (in_array($key, $readOnlyFields)) { unset($raw[$key]); } } return $raw; }
/** * set file attachments of a record * * @param Tinebase_Record_Abstract $record */ public function setRecordAttachments(Tinebase_Record_Abstract $record) { if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' Record: ' . print_r($record->toArray(), TRUE)); } $currentAttachments = $record->getId() ? $this->getRecordAttachments(clone $record) : new Tinebase_Record_RecordSet('Tinebase_Model_Tree_Node'); $attachmentsToSet = $record->attachments instanceof Tinebase_Record_RecordSet ? $record->attachments : new Tinebase_Record_RecordSet('Tinebase_Model_Tree_Node', (array) $record->attachments, TRUE); $attachmentDiff = $currentAttachments->diff($attachmentsToSet); foreach ($attachmentDiff->added as $added) { try { $this->addRecordAttachment($record, $added->name, $added); } catch (Tinebase_Exception_InvalidArgument $teia) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Could not add new attachment ' . print_r($added->toArray(), TRUE) . ' to record: ' . print_r($record->toArray(), TRUE)); } Tinebase_Exception::log($teia); } catch (Tinebase_Exception_NotFound $tenf) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' Could not add new attachment ' . print_r($added->toArray(), TRUE) . ' to record: ' . print_r($record->toArray(), TRUE)); } Tinebase_Exception::log($tenf); } } foreach ($attachmentDiff->removed as $removed) { $this->_fsController->deleteFileNode($removed); } foreach ($attachmentDiff->modified as $modified) { $this->_fsController->update($attachmentsToSet->getById($modified->getId())); } }