/** * convert contact from xml to Addressbook_Model_Contact * * @param SimpleXMLElement $_data * @return Addressbook_Model_Contact */ public function toTineModel(SimpleXMLElement $_data, $_entry = null) { if ($_entry instanceof Addressbook_Model_Contact) { $contact = $_entry; } else { $contact = new Addressbook_Model_Contact(null, true); } unset($contact->jpegphoto); $xmlData = $_data->children('uri:Contacts'); $airSyncBase = $_data->children('uri:AirSyncBase'); foreach ($this->_mapping as $fieldName => $value) { switch ($value) { case 'jpegphoto': // do not change if not set if (isset($xmlData->{$fieldName})) { if (!empty($xmlData->{$fieldName})) { $devicePhoto = base64_decode((string) $xmlData->{$fieldName}); try { $currentPhoto = Tinebase_Controller::getInstance()->getImage('Addressbook', $contact->getId())->getBlob('image/jpeg', 36000); } catch (Exception $e) { } if (isset($currentPhoto) && $currentPhoto == $devicePhoto) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->INFO(__METHOD__ . '::' . __LINE__ . " photo did not change on device -> preserving server photo"); } } else { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->INFO(__METHOD__ . '::' . __LINE__ . " using new contact photo from device (" . strlen($devicePhoto) . "KB)"); } $contact->jpegphoto = $devicePhoto; } } else { if ($_entry && !empty($_entry->jpegphoto)) { $contact->jpegphoto = ''; if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->INFO(__METHOD__ . '::' . __LINE__ . ' Deleting contact photo on device request (contact id: ' . $contact->getId() . ')'); } } } } break; case 'bday': if (isset($xmlData->{$fieldName})) { $isoDate = (string) $xmlData->{$fieldName}; $contact->bday = new Tinebase_DateTime($isoDate); if ($this->_device->devicetype == Syncope_Model_Device::TYPE_IPHONE && $this->_device->getMajorVersion() < 800 || preg_match("/^\\d{4}-\\d{2}-\\d{2}\$/", $isoDate)) { // iOS < 4 & webow < 2.1 send birthdays to the entered date, but the time the birthday got entered on the device // acutally iOS < 4 somtimes sends the bday at noon but the timezone is not clear // -> we don't trust the time part and set the birthdays timezone to the timezone the user has set in tine $userTimezone = Tinebase_Core::get(Tinebase_Core::USERTIMEZONE); $contact->bday = new Tinebase_DateTime($contact->bday->setTime(0, 0, 0)->format(Tinebase_Record_Abstract::ISO8601LONG), $userTimezone); $contact->bday->setTimezone('UTC'); } } else { $contact->bday = null; } break; case 'adr_one_countryname': case 'adr_two_countryname': $contact->{$value} = Tinebase_Translation::getRegionCodeByCountryName((string) $xmlData->{$fieldName}); break; case 'adr_one_street': if (strtolower($this->_device->devicetype) == 'palm') { // palm pre sends the whole address in the <Contacts:BusinessStreet> tag unset($contact->adr_one_street); } else { // default handling for all other devices if (isset($xmlData->{$fieldName})) { $contact->{$value} = (string) $xmlData->{$fieldName}; } else { $contact->{$value} = null; } } break; case 'email': case 'email_home': // android send email address as // Lars Kneschke <*****@*****.**> if (preg_match('/(.*)<(.+@[^@]+)>/', (string) $xmlData->{$fieldName}, $matches)) { $contact->{$value} = trim($matches[2]); } else { $contact->{$value} = (string) $xmlData->{$fieldName}; } break; default: if (isset($xmlData->{$fieldName})) { $contact->{$value} = (string) $xmlData->{$fieldName}; } else { $contact->{$value} = null; } break; } } // get body if (version_compare($this->_device->acsversion, '12.0', '>=') === true) { $contact->note = isset($airSyncBase->Body) ? (string) $airSyncBase->Body->Data : null; } else { $contact->note = isset($xmlData->Body) ? (string) $xmlData->Body : null; } // force update of n_fileas and n_fn $contact->setFromArray(array('n_given' => $contact->n_given, 'n_family' => $contact->n_family, 'org_name' => $contact->org_name)); // contact should be valid now $contact->isValid(); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " contactData " . print_r($contact->toArray(), true)); } return $contact; }
/** * converts vcard to Addressbook_Model_Contact * * @param \Sabre\VObject\Component|resource|string $blob the vcard to parse * @param Tinebase_Record_Abstract $_record update existing contact * @param array $options array of options * @return Addressbook_Model_Contact */ public function toTine20Model($blob, Tinebase_Record_Abstract $_record = null, $options = array()) { $vcard = self::getVObject($blob); if ($_record instanceof Addressbook_Model_Contact) { $contact = $_record; } else { $contact = new Addressbook_Model_Contact(null, false); } $data = $this->_emptyArray; /** @var \Sabre\VObject\Property $property */ foreach ($vcard->children() as $property) { switch ($property->name) { case 'VERSION': case 'PRODID': case 'UID': // do nothing break; case 'ADR': $type = null; foreach ($property['TYPE'] as $typeProperty) { $typeProperty = strtolower($typeProperty); if (in_array($typeProperty, array('home', 'work'))) { $type = $typeProperty; break; } } $parts = $property->getParts(); if ($type == 'home') { // home address $data['adr_two_street2'] = $parts[1]; $data['adr_two_street'] = $parts[2]; $data['adr_two_locality'] = $parts[3]; $data['adr_two_region'] = $parts[4]; $data['adr_two_postalcode'] = $parts[5]; $data['adr_two_countryname'] = $parts[6]; } elseif ($type == 'work') { // work address $data['adr_one_street2'] = $parts[1]; $data['adr_one_street'] = $parts[2]; $data['adr_one_locality'] = $parts[3]; $data['adr_one_region'] = $parts[4]; $data['adr_one_postalcode'] = $parts[5]; $data['adr_one_countryname'] = $parts[6]; } break; case 'CATEGORIES': $tags = Tinebase_Model_Tag::resolveTagNameToTag($property->getParts(), 'Addressbook'); if (!isset($data['tags'])) { $data['tags'] = $tags; } else { $data['tags']->merge($tags); } break; case 'EMAIL': $this->_toTine20ModelParseEmail($data, $property, $vcard); break; case 'FN': $data['n_fn'] = $property->getValue(); break; case 'N': $parts = $property->getParts(); $data['n_family'] = $parts[0]; $data['n_given'] = isset($parts[1]) ? $parts[1] : null; $data['n_middle'] = isset($parts[2]) ? $parts[2] : null; $data['n_prefix'] = isset($parts[3]) ? $parts[3] : null; $data['n_suffix'] = isset($parts[4]) ? $parts[4] : null; break; case 'NOTE': $data['note'] = $property->getValue(); break; case 'ORG': $parts = $property->getParts(); $data['org_name'] = $parts[0]; $data['org_unit'] = isset($parts[1]) ? $parts[1] : null; break; case 'PHOTO': $jpegphoto = $property->getValue(); break; case 'TEL': $this->_toTine20ModelParseTel($data, $property); break; case 'URL': switch (strtoupper($property['TYPE'])) { case 'HOME': $data['url_home'] = $property->getValue(); break; case 'WORK': default: $data['url'] = $property->getValue(); break; } break; case 'TITLE': $data['title'] = $property->getValue(); break; case 'BDAY': $this->_toTine20ModelParseBday($data, $property); break; default: if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' cardData ' . $property->name); } break; } } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' data ' . print_r($data, true)); } // Some email clients will only set a contact with FN (formatted name) without surname if (empty($data['n_family']) && empty($data['org_name']) && !empty($data['n_fn'])) { if (strpos($data['n_fn'], ",") > 0) { list($lastname, $firstname) = explode(",", $data['n_fn'], 2); $data['n_family'] = trim($lastname); $data['n_given'] = trim($firstname); } elseif (strpos($data['n_fn'], " ") > 0) { list($firstname, $lastname) = explode(" ", $data['n_fn'], 2); $data['n_family'] = trim($lastname); $data['n_given'] = trim($firstname); } else { $data['n_family'] = empty($data['n_fn']) ? 'VCARD (imported)' : $data['n_fn']; } } $contact->setFromArray($data); if (isset($jpegphoto)) { $contact->setSmallContactImage($jpegphoto, $this->_maxPhotoSize); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' data ' . print_r($contact->toArray(), true)); } if (isset($options[self::OPTION_USE_SERVER_MODLOG]) && $options[self::OPTION_USE_SERVER_MODLOG] === true) { $contact->creation_time = $_record->creation_time; $contact->last_modified_time = $_record->last_modified_time; $contact->seq = $_record->seq; } return $contact; }
/** * convert contact from xml to Addressbook_Model_Contact * * @param SimpleXMLElement $_data * @return Addressbook_Model_Contact */ public function toTineModel(Syncroton_Model_IEntry $data, $entry = null) { if ($entry instanceof Addressbook_Model_Contact) { $contact = $entry; } else { $contact = new Addressbook_Model_Contact(null, true); } unset($contact->jpegphoto); foreach ($this->_mapping as $fieldName => $value) { if (!isset($data->{$fieldName})) { $contact->{$value} = null; continue; } switch ($value) { case 'jpegphoto': if (!empty($data->{$fieldName})) { $devicePhoto = $data->{$fieldName}; $contact->setSmallContactImage($devicePhoto); } else { if ($entry && !empty($entry->jpegphoto)) { $contact->jpegphoto = ''; if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->INFO(__METHOD__ . '::' . __LINE__ . ' Deleting contact photo on device request (contact id: ' . $contact->getId() . ')'); } } } break; case 'bday': $contact->{$value} = new Tinebase_DateTime($data->{$fieldName}); if ($this->_device->devicetype == Syncroton_Model_Device::TYPE_IPHONE && $this->_device->getMajorVersion() < 800) { // iOS < 4 & webos < 2.1 send birthdays to the entered date, but the time the birthday got entered on the device // actually iOS < 4 sometimes sends the bday at noon but the timezone is not clear // -> we don't trust the time part and set the birthdays timezone to the timezone the user has set in tine $userTimezone = Tinebase_Core::getUserTimezone(); $contact->{$value} = new Tinebase_DateTime($contact->bday->setTime(0, 0, 0)->format(Tinebase_Record_Abstract::ISO8601LONG), $userTimezone); $contact->{$value}->setTimezone('UTC'); } elseif ($this->_device->devicetype == Syncroton_Model_Device::TYPE_BLACKBERRY && version_compare($this->_device->getMajorVersion(), '10', '>=')) { // BB 10+ expects birthday to be at noon $contact->{$value}->subHour(12); } break; case 'adr_one_countryname': case 'adr_two_countryname': $contact->{$value} = Tinebase_Translation::getRegionCodeByCountryName($data->{$fieldName}); break; case 'adr_one_street': if (strtolower($this->_device->devicetype) == 'palm') { // palm pre sends the whole address in the <Contacts:BusinessStreet> tag unset($contact->adr_one_street); } else { $contact->{$value} = $data->{$fieldName}; } break; case 'email': case 'email_home': // android sends email address as // Lars Kneschke <*****@*****.**> if (preg_match('/(.*)<(.+@[^@]+)>/', $data->{$fieldName}, $matches)) { $contact->{$value} = trim($matches[2]); } else { $contact->{$value} = $data->{$fieldName}; } break; case 'note': // @todo check $data->$fieldName->Type and convert to/from HTML if needed if ($data->{$fieldName} instanceof Syncroton_Model_EmailBody) { $contact->{$value} = $data->{$fieldName}->data; } else { $contact->{$value} = null; } break; case 'url': // remove facebook urls if (!preg_match('/^fb:\\/\\//', $data->{$fieldName})) { $contact->{$value} = $data->{$fieldName}; } break; default: $contact->{$value} = $data->{$fieldName}; break; } } // force update of n_fileas and n_fn $contact->setFromArray(array('n_given' => $contact->n_given, 'n_family' => $contact->n_family, 'org_name' => $contact->org_name)); // either "org_name" or "n_family" must be given! if (empty($contact->org_name) && empty($contact->n_family)) { $contact->n_family = 'imported'; } // contact should be valid now $contact->isValid(); if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . " contactData " . print_r($contact->toArray(), true)); } return $contact; }
public function sampledata($_opts) { echo 'importing data ...'; include '/var/www/tine20/Addressbook/sampledata.php'; $controller = Addressbook_Controller_Contact::getInstance(); $contact = array(); for ($i = 0; $i < 10; $i++) { // create a company $contact['org_name'] = $sampledata['companyNames'][array_rand($sampledata['companyNames'])] . ' ' . $sampledata['companyDesc'][array_rand($sampledata['companyDesc'])] . ' ' . $sampledata['companyFrom'][array_rand($sampledata['companyFrom'])]; $randCompNumber = array_rand($sampledata['companyPlz']); $contact['adr_one_street'] = $sampledata['companyStreet'][array_rand($sampledata['companyStreet'])]; $contact['adr_one_postalcode'] = $sampledata['companyPlz'][$randCompNumber]; $contact['adr_one_locality'] = $sampledata['companyOrt'][$randCompNumber]; for ($j = 0; $j < 10; $j++) { // create person $contact['tel_work'] = $sampledata['companyDialcode'][$randCompNumber] . rand(2456, 871234); $contact['tel_fax'] = $contact['tel_work'] . '9'; $contact['tel_cell'] = $sampledata['mobileDialcode'][array_rand($sampledata['mobileDialcode'])] . rand(245634, 87123224); $contact['role'] = $sampledata['position'][array_rand($sampledata['position'])]; $randNameNumber = array_rand($sampledata['personFirstName']); $contact['n_given'] = $sampledata['personFirstName'][$randNameNumber]; // todo: generate salutation even maile / odd femail $contact['n_family'] = $sampledata['personLastName'][array_rand($sampledata['personLastName'])]; $randPersNumber = array_rand($sampledata['personPlz']); $contact['adr_two_street'] = $sampledata['personStreet'][array_rand($sampledata['personStreet'])]; $contact['adr_two_postalcode'] = $sampledata['personPlz'][$randPersNumber]; $contact['adr_two_locality'] = $sampledata['personOrt'][$randPersNumber]; $contact['tel_home'] = $sampledata['personDialcode'][$randPersNumber] . rand(2456, 871234); $contact['tel_cell_private'] = $sampledata['mobileDialcode'][array_rand($sampledata['mobileDialcode'])] . rand(245634, 87123224); $contact['container_id'] = 133; $contactObj = new Addressbook_Model_Contact($contact, true); print_r($contactObj->toArray()); $controller->create($contactObj); } } }
/** * converts vcard to Addressbook_Model_Contact * * @param Sabre_VObject_Component|stream|string $_blob the vcard to parse * @param Tinebase_Record_Abstract $_record update existing contact * @return Addressbook_Model_Contact */ public function toTine20Model($_blob, Tinebase_Record_Abstract $_record = null) { if ($_blob instanceof Sabre_VObject_Component) { $vcard = $_blob; } else { if (is_resource($_blob)) { $_blob = stream_get_contents($_blob); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' vcard data: ' . $_blob); } $vcard = Sabre_VObject_Reader::read($_blob); } if ($_record instanceof Addressbook_Model_Contact) { $contact = $_record; } else { $contact = new Addressbook_Model_Contact(null, false); } $data = $this->_emptyArray; foreach ($vcard->children() as $property) { switch ($property->name) { case 'VERSION': case 'PRODID': case 'UID': // do nothing break; case 'ADR': $type = null; foreach ($property['TYPE'] as $typeProperty) { if (strtolower($typeProperty) == 'home' || strtolower($typeProperty) == 'work') { $type = strtolower($typeProperty); break; } } if ($type == 'home') { // home address $data['adr_two_street2'] = $property->value[1]; $data['adr_two_street'] = $property->value[2]; $data['adr_two_locality'] = $property->value[3]; $data['adr_two_region'] = $property->value[4]; $data['adr_two_postalcode'] = $property->value[5]; $data['adr_two_countryname'] = $property->value[6]; } elseif ($type == 'work') { // work address $data['adr_one_street2'] = $property->value[1]; $data['adr_one_street'] = $property->value[2]; $data['adr_one_locality'] = $property->value[3]; $data['adr_one_region'] = $property->value[4]; $data['adr_one_postalcode'] = $property->value[5]; $data['adr_one_countryname'] = $property->value[6]; } break; case 'CATEGORIES': $tags = $property->value; if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' cardData ' . print_r($tags, true)); } break; case 'EMAIL': $this->_toTine20ModelParseEmail($data, $property); break; case 'FN': $data['n_fn'] = $property->value; break; case 'N': #$components = Sabre_VObject_Property::splitCompoundValues($property->value); $data['n_family'] = $property->value[0]; $data['n_given'] = $property->value[1]; $data['n_middle'] = isset($property->value[2]) ? $property->value[2] : null; $data['n_prefix'] = isset($property->value[3]) ? $property->value[3] : null; $data['n_suffix'] = isset($property->value[4]) ? $property->value[4] : null; break; case 'NOTE': $data['note'] = $property->value; break; case 'ORG': #$components = Sabre_VObject_Property::splitCompoundValues($property->value); $data['org_name'] = $property->value[0]; $data['org_unit'] = isset($property->value[1]) ? $property->value[1] : null; break; case 'PHOTO': $data['jpegphoto'] = base64_decode($property->value); break; case 'TEL': $this->_toTine20ModelParseTel($data, $property); break; case 'URL': switch (strtoupper($property['TYPE'])) { case 'HOME': $data['url_home'] = $property->value; break; case 'WORK': default: $data['url'] = $property->value; break; } break; case 'TITLE': $data['title'] = $property->value; break; default: if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' cardData ' . $property->name); } break; } } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' data ' . print_r($data, true)); } if (empty($data['n_family'])) { $parts = explode(' ', $data['n_fn']); $data['n_family'] = $parts[count($parts) - 1]; $data['n_given'] = count($parts) > 1 ? $parts[0] : null; } $contact->setFromArray($data); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' data ' . print_r($contact->toArray(), true)); } return $contact; }