/** * tests if the modelconfiguration gets created for the traditional models */ public function testModelCreationTraditional() { $contact = new Addressbook_Model_Contact(array('n_family' => 'Spencer', 'n_given' => 'Bud')); $cObj = $contact->getConfiguration(); // at first this is just null $this->assertNull($cObj); }
/** * update to 9.1 * * @return void */ public function update_0() { // we need at least addressbook version 9,7 if (version_compare($this->getApplicationVersion('Addressbook'), '9.8') < 0) { return; } $setupUser = $this->_getSetupFromConfigOrCreateOnTheFly(); if ($setupUser) { Tinebase_Core::set(Tinebase_Core::USER, $setupUser); $filter = new Phone_Model_CallFilter(array(array('field' => 'start', 'operator' => 'after', 'value' => date('Y-m-d H:i:s', time() - 3600 * 24 * 30 * 3))), 'AND', array('ignoreAcl' => true)); $addressbookController = Addressbook_Controller_Contact::getInstance(); $phoneController = Phone_Controller_Call::getInstance(); $calls = $phoneController->search($filter); foreach ($calls as $_record) { // resolve telephone number to contacts if possible $telNumber = Addressbook_Model_Contact::normalizeTelephoneNoCountry($phoneController->resolveInternalNumber($_record->destination)); if (null === $telNumber) { continue; } $filter = new Addressbook_Model_ContactFilter(array(array('field' => 'telephone_normalized', 'operator' => 'equals', 'value' => $telNumber))); $contacts = $addressbookController->search($filter); $relations = array(); foreach ($contacts as $contact) { $relations[] = array('related_model' => 'Addressbook_Model_Contact', 'related_id' => $contact->getId(), 'related_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_backend' => Tinebase_Model_Relation::DEFAULT_RECORD_BACKEND, 'type' => 'CALLER'); } if (count($relations) > 0) { $_record->relations = $relations; $phoneController->update($_record); } } } $this->setApplicationVersion('Phone', '9.1'); }
public static function getFromContact(Addressbook_Model_Contact $contact) { $obj = new self($contact->__get('bank_account_number'), $contact->__get('bank_account_name'), $contact->__get('bank_name'), $contact->__get('bank_code')); $obj->setContactId($contact->getId()); $countryCode = $contact->getLetterDrawee()->getPostalAddress()->getCountryCode('DE'); $obj->setCountryCode($countryCode); if (trim($obj->getName()) == '') { $obj->setName($contact->__get('n_fileas')); } return $obj; }
/** * inspect creation of one record (before create) * * @param Tinebase_Record_Interface $_record * @return void */ protected function _inspectBeforeCreate(Tinebase_Record_Interface $_record) { // resolve telephone number to contacts if possible $telNumber = Addressbook_Model_Contact::normalizeTelephoneNoCountry($this->resolveInternalNumber($_record->destination)); if (null !== $telNumber) { $filter = new Addressbook_Model_ContactFilter(array(array('field' => 'telephone_normalized', 'operator' => 'equals', 'value' => $telNumber))); $controller = Addressbook_Controller_Contact::getInstance(); $contacts = $controller->search($filter); $relations = $_record->relations; foreach ($contacts as $contact) { $relations[] = array('related_model' => 'Addressbook_Model_Contact', 'related_id' => $contact->getId(), 'related_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_backend' => Tinebase_Model_Relation::DEFAULT_RECORD_BACKEND, 'type' => 'CALLER'); } $_record->relations = $relations; } }
/** * testTriggerRebuildIfFatherRemovedChild */ public function testTriggerRebuildIfFatherRemovedChild() { $contact = $this->testTriggerRebuildPathForRecords(); // remove child relation from father and check paths of child records $father = Addressbook_Controller_Contact::getInstance()->get($this->_fatherRecord->getId()); foreach ($father->relations as $relation) { if ($relation->related_degree === Tinebase_Model_Relation::DEGREE_CHILD) { $father->relations->removeRecord($relation); break; } } //workaround as _setRelatedData expects an array!?! $father->relations = $father->relations->toArray(); Addressbook_Controller_Contact::getInstance()->update($father); $recordPaths = $this->_uit->getPathsForRecords($contact); $this->assertEquals(1, count($recordPaths)); // check remaining path again $expectedPaths = array('/mother/tester'); foreach ($expectedPaths as $expectedPath) { $this->assertTrue(in_array($expectedPath, $recordPaths->path), 'could not find path ' . $expectedPath . ' in ' . print_r($recordPaths->toArray(), true)); } }
/** * update contact data(first name, last name, ...) of user in local sql storage * * @param Addressbook_Model_Contact $contact * @return integer * @throws Exception */ public function updateContactInSqlBackend(Addressbook_Model_Contact $_contact) { $contactId = $_contact->getId(); $accountData = array($this->rowNameMapping['accountDisplayName'] => $_contact->n_fileas, $this->rowNameMapping['accountFullName'] => $_contact->n_fn, $this->rowNameMapping['accountFirstName'] => $_contact->n_given, $this->rowNameMapping['accountLastName'] => $_contact->n_family, $this->rowNameMapping['accountEmailAddress'] => $_contact->email); try { $accountsTable = new Tinebase_Db_Table(array('name' => SQL_TABLE_PREFIX . 'accounts')); $where = array($this->_db->quoteInto($this->_db->quoteIdentifier('contact_id') . ' = ?', $contactId)); return $accountsTable->update($accountData, $where); } catch (Exception $e) { Tinebase_TransactionManager::getInstance()->rollBack(); throw $e; } }
/** * Get/Create Calendar for external organizer * * @param Addressbook_Model_Contact $organizer organizer id * @param string $emailAddress * @return Tinebase_Model_Container container id */ public function getInvitationContainer($organizer, $emailAddress = null) { if (null !== $organizer) { $containerName = $organizer->getPreferedEmailAddress(); } else { $containerName = $emailAddress; } try { $container = Tinebase_Container::getInstance()->getContainerByName('Calendar', $containerName, Tinebase_Model_Container::TYPE_SHARED); } catch (Tinebase_Exception_NotFound $tenf) { if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' No invitation container found. Creating a new one for organizer ' . $containerName); } $container = Tinebase_Container::getInstance()->addContainer(new Tinebase_Model_Container(array('name' => $containerName, 'color' => '#333399', 'type' => Tinebase_Model_Container::TYPE_SHARED, 'backend' => Tinebase_User::SQL, 'application_id' => Tinebase_Application::getInstance()->getApplicationByName('Calendar')->getId(), 'model' => 'Calendar_Model_Event')), NULL, TRUE); $grants = new Tinebase_Record_RecordSet('Tinebase_Model_Grants', array(array('account_id' => '0', 'account_type' => Tinebase_Acl_Rights::ACCOUNT_TYPE_ANYONE, Tinebase_Model_Grants::GRANT_ADD => true, Tinebase_Model_Grants::GRANT_EDIT => true, Tinebase_Model_Grants::GRANT_DELETE => true))); Tinebase_Container::getInstance()->setGrants($container->getId(), $grants, true, false); } return $container; }
/** * update to 9.8 * * @see 0011934: show contacts in phone call grid * * @return void */ public function update_7() { if ($this->getTableVersion('addressbook') < 19) { $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_assistent_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_car_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_cell_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_cell_private_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_fax_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_fax_home_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_home_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_other_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_pager_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_prefer_normalized</name> <type>text</type> <length>32</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $declaration = new Setup_Backend_Schema_Field_Xml('<field> <name>tel_work_normalized</name> <type>text</type> <length>40</length> <notnull>false</notnull> </field>'); $this->_backend->addCol('addressbook', $declaration); $this->setTableVersion('addressbook', 19); // fill normalized columns with data $db = Tinebase_Core::getDb(); $select = $db->select(); $columns = array('id', 'tel_assistent', 'tel_car', 'tel_cell', 'tel_cell_private', 'tel_fax', 'tel_fax_home', 'tel_home', 'tel_pager', 'tel_work', 'tel_other', 'tel_prefer'); // get all telephone columns $select->from(SQL_TABLE_PREFIX . 'addressbook', $columns); $result = $db->query($select); $data = array(); array_shift($columns); $results = $result->fetchAll(Zend_Db::FETCH_ASSOC); foreach ($results as $row) { foreach ($columns as $col) { if (!empty($row[$col])) { $data[$col . '_normalized'] = Addressbook_Model_Contact::normalizeTelephoneNoCountry((string) $row[$col]); } } if (count($data) > 0) { $db->update(SQL_TABLE_PREFIX . 'addressbook', $data, $db->quoteInto('id = ?', $row['id'])); $data = array(); } } } $this->setApplicationVersion('Addressbook', '9.8'); }
/** * 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; }
/** * get test attendee * * @return Tinebase_Record_RecordSet */ protected function _getAttendee() { return new Tinebase_Record_RecordSet('Calendar_Model_Attender', array(array('user_id' => $this->_testUserContact->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'status_authkey' => Tinebase_Record_Abstract::generateUID()), array('user_id' => $this->_personasContacts['sclever']->getId(), 'user_type' => Calendar_Model_Attender::USERTYPE_USER, 'role' => Calendar_Model_Attender::ROLE_REQUIRED, 'status_authkey' => Tinebase_Record_Abstract::generateUID()))); }
/** * 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; }
/** * test getting multiple attachments at once */ public function testGetMultipleAttachmentsOfRecords() { $recordAttachments = Tinebase_FileSystem_RecordAttachments::getInstance(); $records = new Tinebase_Record_RecordSet('Addressbook_Model_Contact'); for ($i = 0; $i < 10; $i++) { $record = new Addressbook_Model_Contact(array('n_family' => Tinebase_Record_Abstract::generateUID())); $record->setId(Tinebase_Record_Abstract::generateUID()); $recordAttachments->addRecordAttachment($record, $i . 'Test.txt', fopen(__FILE__, 'r')); $records->addRecord($record); } $recordAttachments->getMultipleAttachmentsOfRecords($records); foreach ($records as $records) { $this->assertEquals(1, $record->attachments->count(), 'Attachments missing'); } }
/** * convert contact model to principal array * * @param Addressbook_Model_Contact $contact * @return array */ protected function _contactToPrincipal(Addressbook_Model_Contact $contact) { $principal = array('uri' => self::PREFIX_USERS . '/' . $contact->getId(), '{DAV:}displayname' => $contact->n_fileas, '{DAV:}alternate-URI-set' => array('urn:uuid:' . $contact->getId()), '{' . \Sabre\CalDAV\Plugin::NS_CALDAV . '}calendar-user-type' => 'INDIVIDUAL', '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}record-type' => 'users', '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}first-name' => $contact->n_given, '{' . \Sabre\CalDAV\Plugin::NS_CALENDARSERVER . '}last-name' => $contact->n_family); if (!empty(Tinebase_Core::getUser()->accountEmailAddress)) { $principal['{http://sabredav.org/ns}email-address'] = $contact->email; } return $principal; }
/** * inspect update of one record * * @param Tinebase_Record_Interface $_record the update record * @param Tinebase_Record_Interface $_oldRecord the current persistent record * @throws Tinebase_Exception_AccessDenied * @todo remove system note for updated jpegphoto when images are modlogged (@see 0000284: modlog of contact images / move images to vfs) */ protected function _inspectBeforeUpdate($_record, $_oldRecord) { /** @var Addressbook_Model_Contact $_record */ /** @var Addressbook_Model_Contact $_oldRecord */ // do update of geo data only if one of address field changed $addressDataChanged = FALSE; foreach ($this->_addressFields as $field) { if ($_record->{'adr_one_' . $field} != $_oldRecord->{'adr_one_' . $field} || $_record->{'adr_two_' . $field} != $_oldRecord->{'adr_two_' . $field}) { $addressDataChanged = TRUE; break; } } if ($addressDataChanged) { $this->_setGeoData($_record); } if (isset($_record->jpegphoto) && !empty($_record->jpegphoto)) { // add system note when jpegphoto gets updated $translate = $translate = Tinebase_Translation::getTranslation('Addressbook'); $noteMessage = $translate->_('Uploaded new contact image.'); $traceException = new Exception($noteMessage); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $traceException); } Tinebase_Notes::getInstance()->addSystemNote($_record, Tinebase_Core::getUser(), Tinebase_Model_Note::SYSTEM_NOTE_NAME_CHANGED, $noteMessage); } if (isset($_oldRecord->type) && $_oldRecord->type == Addressbook_Model_Contact::CONTACTTYPE_USER) { $_record->type = Addressbook_Model_Contact::CONTACTTYPE_USER; } if (!empty($_record->account_id) || $_record->type == Addressbook_Model_Contact::CONTACTTYPE_USER) { // first check if something changed that requires special rights $changeAccount = false; foreach (Addressbook_Model_Contact::getManageAccountFields() as $field) { if ($_record->{$field} != $_oldRecord->{$field}) { $changeAccount = true; break; } } // if so, check rights if ($changeAccount) { if (!Tinebase_Core::getUser()->hasRight('Admin', Admin_Acl_Rights::MANAGE_ACCOUNTS)) { throw new Tinebase_Exception_AccessDenied('No permission to change account properties.'); } } } }
/** * 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 * @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; foreach ($vcard->children() as $property) { switch ($property->name) { case 'VERSION': case 'PRODID': case 'UID': // do nothing break; case 'ADR': $parts = $property->getParts(); // 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(); $data['n_given'] = $data['n_fn']; break; case 'N': $parts = $property->getParts(); $data['n_family'] = $parts[0]; $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': $data['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'] = $data['n_fn']; } } $contact->setFromArray($data); 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; }
/** * create contact pdf * * @param Addressbook_Model_Contact $_contact contact data * * @return string the contact pdf */ public function generate(Addressbook_Model_Contact $_contact) { $locale = Tinebase_Core::get('locale'); $translate = Tinebase_Translation::getTranslation('Addressbook'); // set user timezone $_contact->setTimezone(Tinebase_Core::getUserTimezone()); $contactFields = array(array('label' => $translate->_('Business Contact Data'), 'type' => 'separator'), array('label' => $translate->_('Organisation / Unit'), 'type' => 'singleRow', 'value' => array(array('org_name', 'org_unit')), 'glue' => ' / '), array('label' => $translate->_('Business Address'), 'type' => 'multiRow', 'value' => array('adr_one_street', 'adr_one_street2', array('adr_one_postalcode', 'adr_one_locality'), array('adr_one_region', 'adr_one_countryname'))), array('label' => $translate->_('Email'), 'value' => array('email')), array('label' => $translate->_('Telephone Work'), 'value' => array('tel_work')), array('label' => $translate->_('Telephone Cellphone'), 'value' => array('tel_cell')), array('label' => $translate->_('Telephone Car'), 'value' => array('tel_car')), array('label' => $translate->_('Telephone Fax'), 'value' => array('tel_fax')), array('label' => $translate->_('Telephone Page'), 'value' => array('tel_pager')), array('label' => $translate->_('URL'), 'value' => array('url')), array('label' => $translate->_('Role'), 'value' => array('role')), array('label' => $translate->_('Room'), 'value' => array('room')), array('label' => $translate->_('Assistant'), 'value' => array('assistent')), array('label' => $translate->_('Assistant Telephone'), 'value' => array('tel_assistent')), array('label' => $translate->_('Private Contact Data'), 'type' => 'separator'), array('label' => $translate->_('Private Address'), 'type' => 'multiRow', 'value' => array('adr_two_street', 'adr_two_street2', array('adr_two_postalcode', 'adr_two_locality'), array('adr_two_region', 'adr_two_countryname'))), array('label' => $translate->_('Email Home'), 'value' => array('email_home')), array('label' => $translate->_('Telephone Home'), 'value' => array('tel_home')), array('label' => $translate->_('Telephone Cellphone Private'), 'value' => array('tel_cell_private')), array('label' => $translate->_('Telephone Fax Home'), 'value' => array('tel_fax_home')), array('label' => $translate->_('URL Home'), 'value' => array('url_home')), array('label' => $translate->_('Other Data'), 'type' => 'separator'), array('label' => $translate->_('Birthday'), 'value' => array('bday')), array('label' => $translate->_('Job Title'), 'value' => array('title'))); try { $tineImage = Addressbook_Controller::getInstance()->getImage($_contact->getId()); Tinebase_ImageHelper::resize($tineImage, 160, 240, Tinebase_ImageHelper::RATIOMODE_PRESERVANDCROP); $tmpPath = tempnam(Tinebase_Core::getTempDir(), 'tine20_tmp_gd'); $tmpPath .= $tineImage->getImageExtension(); file_put_contents($tmpPath, $tineImage->blob); $contactPhoto = Zend_Pdf_Image::imageWithPath($tmpPath); unlink($tmpPath); } catch (Exception $e) { // gif images are not supported yet by zf (or some other error) if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) { Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $e->__toString()); } $contactPhoto = NULL; } // build title (name) + subtitle + icon $nameFields = array('n_prefix', 'n_given', 'n_middle', 'n_family', 'n_suffix'); $titleArray = array(); foreach ($nameFields as $nameField) { if (!empty($_contact[$nameField])) { $titleArray[] = $_contact[$nameField]; } } $title = implode(' ', $titleArray); $subtitle = $_contact->org_name; $titleIcon = "/images/oxygen/32x32/apps/system-users.png"; // add data to array $record = array(); foreach ($contactFields as $fieldArray) { if (!isset($fieldArray['type']) || $fieldArray['type'] !== 'separator') { $values = array(); foreach ($fieldArray['value'] as $valueFields) { $content = array(); if (is_array($valueFields)) { $keys = $valueFields; } else { $keys = array($valueFields); } foreach ($keys as $key) { if ($_contact->{$key} instanceof Tinebase_DateTime) { $content[] = Tinebase_Translation::dateToStringInTzAndLocaleFormat($_contact->{$key}, NULL, NULL, 'date'); } elseif (!empty($_contact->{$key})) { if (preg_match("/countryname/", $key)) { $content[] = Zend_Locale::getTranslation($_contact->{$key}, 'country', $locale); } else { $content[] = $_contact->{$key}; } } } if (!empty($content)) { $glue = isset($fieldArray['glue']) ? $fieldArray['glue'] : " "; $values[] = implode($glue, $content); } } if (!empty($values)) { $record[] = array('label' => $fieldArray['label'], 'type' => isset($fieldArray['type']) ? $fieldArray['type'] : 'singleRow', 'value' => sizeof($values) === 1 ? $values[0] : $values); } } elseif (isset($fieldArray['type']) && $fieldArray['type'] === 'separator') { $record[] = $fieldArray; } } // add notes $record = $this->_addActivities($record, $_contact->notes); //print_r($record); // tags $tags = isset($_contact['tags']) ? $_contact['tags'] : array(); // generate pdf $this->generatePdf($record, $title, $subtitle, $tags, $_contact->note, $titleIcon, $contactPhoto, array(), FALSE); }
/** * 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; }
/** * add photo data to VCard * * @param Addressbook_Model_Contact $record * @param \Sabre\VObject\Component $card */ protected function _fromTine20ModelAddPhoto(Addressbook_Model_Contact $record, \Sabre\VObject\Component $card) { if (!empty($record->jpegphoto)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__); try { $jpegData = $record->getSmallContactImage($this->_maxPhotoSize); $card->add('PHOTO', $jpegData, array('TYPE' => 'JPEG', 'ENCODING' => 'b')); } catch (Exception $e) { if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) { Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . " Image for contact {$record->getId()} not found or invalid: {$e->getMessage()}"); } if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' . $e->getTraceAsString()); } } } }
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); } } }
/** * save unknown contacts * * @param integer $_user_id * @param array $_recipients * @return integer */ protected function _saveUnknownContacts($_user_id, $_recipients) { $result = 0; $_allRecipients = array(); foreach ($_recipients as $_recipts) { array_push($_allRecipients, strtolower($_recipts)); } try { $decodedFilter = array(array('field' => 'email_query', 'operator' => 'in', 'value' => $_allRecipients), array('field' => 'container_id', 'operator' => 'equals', 'value' => array('path' => '/personal/' . $_user_id))); $filter = new Addressbook_Model_ContactFilter($decodedFilter); $foundContacts = $this->_searchContacts($filter, null); $knownContacts = array(); foreach ($foundContacts as $contact) { array_push($knownContacts, $contact['email']); } $unknownContacts = array_diff($_allRecipients, $knownContacts); $unknownContactsFolder = $this->_getUnknownContactsFolder($_user_id); foreach ($unknownContacts as $recipient) { //gets everything before the @ $fullname = preg_replace('/@.*/', '', $recipient); $fullname = ucwords(preg_replace('/[\\-\\_\\.]/', ' ', $fullname)); //cuts the email in the @, removes everythig before the first . and upercases it $org_name = strtoupper(preg_replace('/.*?@/', '', $recipient)); $org_name = strtoupper(preg_replace('/\\..*/', '', $org_name)); $n_given = $fullname; $n_family = ""; $pieces = explode(' ', $fullname); if (count($pieces) > 1) { $n_given = preg_replace('/(\\s.*)/', '', $fullname); $n_family = preg_replace('/.*?\\s/', '', $fullname); } $contactData = array('email' => $recipient, 'n_family' => $n_family, 'n_given' => $n_given, 'org_name' => $org_name, 'container_id' => $unknownContactsFolder->id); if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) { Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . " adding new contact " . print_r($contactData, true)); } $contact = new Addressbook_Model_Contact(NULL, FALSE); $contact->setFromArray($contactData); Addressbook_Controller_Contact::getInstance()->create($contact, FALSE); $result += 1; } } catch (Zend_Mail_Protocol_Exception $zmpe) { Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' Could not save message note: ' . $zmpe->getMessage()); throw $zmpe; $result = -1; } return $result; }
public function inviteUsersToJoin($roomId, $users, $moderator) { $translate = Tinebase_Translation::getTranslation('Webconference'); $fullUser = Tinebase_Core::getUser(); $recipients = array(); foreach ($users as $user) { //$userName = $user[n_fn]; $addressbook = new Addressbook_Model_Contact($user); $userEmail = $addressbook->getPreferedEmailAddress(); $userName = $addressbook->n_fn; $url = Webconference_Controller_BigBlueButton::getInstance()->joinRoom($roomId, $moderator, $userName, $userEmail)->bbbUrl->bbbUrl; $subject = $translate->_("Invite User To Join Webconference"); $messagePlain = null; $_messageHtml = sprintf($translate->_("The user %s is inviting you to a Webconference"), Tinebase_Core::getUser()->accountFullName); $_messageHtml .= "<br/><br/>"; $_messageHtml .= "<div>"; $_messageHtml .= "<span class=\"{$url}\" />"; $_messageHtml .= "<span class=\"tinebase-webconference-link\">"; $_messageHtml .= $translate->_("Log in to Webconference"); $_messageHtml .= "</span>"; $_messageHtml .= "</div>"; $recipient = array($addressbook); Tinebase_Notification::getInstance()->send($fullUser, $recipient, $subject, $messagePlain, $_messageHtml); array_push($recipients, $user); } return array('message' => $translate->_('Users invited successfully') . '!'); }
/** * update user profile * * @param array $profileData * @return array */ public function updateUserProfile($profileData) { $contact = new Addressbook_Model_Contact(array(), TRUE); $contact->setFromJsonInUsersTimezone($profileData); // NOTE: $userProfile is a contact where non readable fields are clearad out! $userProfile = Tinebase_UserProfile::getInstance()->update($contact); // NOTE: This hurts! We don't have methods to call in our frontends yet which convert // a record to the json representaion :( Thus image link will be broken! $userProfile->setTimezone(Tinebase_Core::get(Tinebase_Core::USERTIMEZONE)); return $userProfile->toArray(); }
/** * start phone call and save in history * * @param Phone_Model_Call $_call * @return Phone_Model_Call */ public function callStarted(Phone_Model_Call $_call) { $backend = Phone_Backend_Factory::factory(Phone_Backend_Factory::CALLHISTORY); $_call->start = Tinebase_DateTime::now(); $filter = new Voipmanager_Model_Asterisk_SipPeerFilter(array(array('field' => 'name', 'operator' => 'equals', 'value' => $_call->line_id))); $asteriskSipPeers = Voipmanager_Controller_Asterisk_SipPeer::getInstance()->search($filter); if (count($asteriskSipPeers) > 0) { $_call->callerid = $asteriskSipPeers[0]->callerid; } else { $_call->callerid = $_call->line_id; } $call = $backend->create($_call); // resolve telephone number to contacts if possible $phoneController = Phone_Controller_Call::getInstance(); $telNumber = Addressbook_Model_Contact::normalizeTelephoneNoCountry($phoneController->resolveInternalNumber($call->destination)); if (null !== $telNumber) { $filter = new Addressbook_Model_ContactFilter(array(array('field' => 'telephone_normalized', 'operator' => 'equals', 'value' => $telNumber))); $controller = Addressbook_Controller_Contact::getInstance(); $oldAclChecks = $controller->doContainerACLChecks(); $controller->doContainerACLChecks(false); $contacts = $controller->search($filter); $relationBackend = new Tinebase_Relation_Backend_Sql(); foreach ($contacts as $contact) { // we dont add the relations to the call record as this is called by the phone server, so no need to return the relations $relationBackend->addRelation(new Tinebase_Model_Relation(array('own_model' => 'Phone_Model_Call', 'own_id' => $call->getId(), 'own_backend' => Tinebase_Model_Relation::DEFAULT_RECORD_BACKEND, 'related_model' => 'Addressbook_Model_Contact', 'related_id' => $contact->getId(), 'related_degree' => Tinebase_Model_Relation::DEGREE_SIBLING, 'related_backend' => Tinebase_Model_Relation::DEFAULT_RECORD_BACKEND, 'type' => 'CALLER'))); } $controller->doContainerACLChecks($oldAclChecks); } return $call; }