If the format is 'none', the full name with all parts is returned. If
the format is 'last_first' or 'first_last', only the first name and
last name are returned.
public static formatName ( Turba_Object $ob, string $name_format = null ) : string | ||
$ob | Turba_Object | The object to get a name from. |
$name_format | string | The formatting. One of 'none', 'last_first' or 'first_last'. Defaults to the user preference. |
Результат | string | The formatted name, either "Firstname Lastname" or "Lastname, Firstname" depending on $name_format or the user's preference. |
/** */ protected function _initPages() { global $injector; $this->view->list = array(); if ($GLOBALS['browse_source_count']) { foreach (Turba::getAddressBooks() as $key => $val) { if (!empty($val['browse'])) { try { $driver = $injector->getInstance('Turba_Factory_Driver')->create($key); } catch (Turba_Exception $e) { continue; } try { $contacts = $driver->search(array(), null, 'AND', array('__key', 'name')); $contacts->reset(); } catch (Turba_Exception $e) { continue; } $url = new Horde_Core_Smartmobile_Url(); $url->add('source', $key); $url->setAnchor('entry'); $tmp = array(); while ($contact = $contacts->next()) { $name = Turba::formatName($contact); $tmp[] = array('group' => $contact->isGroup(), 'name' => strlen($name) ? $name : '[' . _("No Name") . ']', 'url' => strval($url->add('key', $contact->getValue('__key')))); } $this->view->list[$val['title']] = $tmp; } } } }
public function skip($ob) { $name = Turba::formatName($ob, $this->_format); if ($this->_alpha != '*' && Horde_String::lower(substr($name, 0, 1)) != $this->_alpha) { return true; } return false; }
/** * AJAX action: Get entry data. * * Variables used: * - key: (string) UID of entry. * - source: (string) UID of source addressbook. * * @return object TODO * - entry: (array) * - error: (boolean) * - group: (array) */ public function smartmobileEntry() { global $attributes, $cfgSources, $injector, $notification, $registry; $contact = null; $out = new stdClass(); $source = $this->vars->get('source'); if (isset($cfgSources[$source])) { try { $contact = $injector->getInstance('Turba_Factory_Driver')->create($source)->getObject($this->vars->get('key')); } catch (Horde_Exception $e) { } } if (is_null($contact)) { $notification->push(_("Addressbook entry could not be loaded."), 'horde.error'); $out->error = true; return $out; } $out->entry = array(); if (!count($tabs = $contact->driver->tabs)) { $tabs = array(_("Entries") => array_keys($contact->driver->getCriteria())); } foreach ($tabs as $key => $val) { foreach ($val as $val2) { if (strlen($val3 = $contact->getValue($val2))) { $url = null; switch ($val2) { case 'email': case 'emails': $addrs = $GLOBALS['injector']->getInstance('Horde_Mail_Rfc822')->parseAddressList($val3, array('limit' => $val2 == 'emails' ? 0 : 1)); foreach ($addrs as $addr) { $addr = $addr->writeAddress(true); try { $url = strval($registry->call('mail/compose', array(array('to' => $addr)))); } catch (Horde_Exception $e) { } $out->entry[$key][] = array_filter(array('l' => $attributes[$val2]['label'], 'u' => $url, 'v' => $addr)); } continue 2; } $out->entry[$key][] = array_filter(array('l' => $attributes[$val2]['label'], 'u' => $url, 'v' => $val3)); } } } if ($contact->isGroup()) { $members = $contact->listMembers(); $members->reset(); $url = new Horde_Core_Smartmobile_Url(); $url->setAnchor('entry'); $out->group = array('l' => _("Contact List Members"), 'm' => array()); while ($ob = $members->next()) { $out->group['m'][] = array('n' => strlen($name = Turba::formatName($ob)) ? $name : '[' . _("No Name") . ']', 'u' => strval($url->copy()->setRaw(true)->add(array('key' => $ob->getValue('__key'), 'source' => $ob->getSource())))); } } return $out; }
/** * Searches the current address book for duplicate entries. * * Duplicates are determined by comparing email and name or last name and * first name values. * * @return array A hash with the following format: * <code> * array('name' => array('John Doe' => Turba_List, ...), ...) * </code> * @throws Turba_Exception */ public function searchDuplicates() { $owner = $this->getContactOwner(); $fields = array(); if (is_array($this->map['name'])) { if (in_array('lastname', $this->map['name']['fields']) && isset($this->map['lastname'])) { $field = array($this->map['lastname']); if (in_array('firstname', $this->map['name']['fields']) && isset($this->map['firstname'])) { $field[] = $this->map['firstname']; } $fields[] = $field; } } else { $fields[] = $this->map['name']; } if (isset($this->map['email'])) { $fields[] = $this->map['email']; } $nameFormat = $GLOBALS['prefs']->getValue('name_format'); if ($nameFormat != 'first_last' && $nameFormat != 'last_first') { $nameFormat = 'first_last'; } $order = $this->_buildFields($fields); $joins = $this->_buildJoin($fields); $where = $this->_buildWhere($fields); $duplicates = array(); for ($i = 0; $i < count($joins); $i++) { /* Build up the full query. */ $values = array(); $query = sprintf('SELECT DISTINCT a1.%s, %s FROM %s a1 JOIN %s a2 ON %s AND a1.%s <> a2.%s WHERE', $this->map['__key'], $order[$i], $this->_params['table'], $this->_params['table'], $joins[$i], $this->map['__key'], $this->map['__key']); if (isset($this->map['__owner'])) { $query .= sprintf(' a1.%s = ? AND a2.%s = ? AND', $this->map['__owner'], $this->map['__owner']); $values = array($owner, $owner); } $query .= sprintf(' %s ORDER BY %s', $where[$i], $order[$i]); /* Run query. */ try { $ids = $this->_db->selectValues($query, $values); } catch (Horde_Db_Exception $e) { throw new Turba_Exception(_("Server error when performing search.")); } $field = $i == 0 ? 'name' : array_search($fields[$i], $this->map); $contacts = array(); foreach ($ids as $id) { $contact = $this->getObject($id); $value = $contact->getValue($field); if ($field == 'name') { $value = Turba::formatName($contact, $nameFormat); } /* HACK! */ if ($field == 'email') { $value = Horde_String::lower($value); } if (!isset($contacts[$value])) { $contacts[$value] = new Turba_List(); } $contacts[$value]->insert($contact); } if ($contacts) { $duplicates[$field] = $contacts; } } return $duplicates; }
/** * Returns a contact search result. * * @param mixed $names The search filter values. * @param array $opts Optional parameters: * - customStrict: (array) An array of fields that must match exactly. * DEFAULT: None * - fields: (array) The fields to search on. * DEFAULT: Search all configured search fields. * - forceSource: (boolean) Whether to use the specified sources, even * if they have been disabled in the preferences? * DEFAULT: false * - matchBegin: (boolean) Match word boundaries only? * DEFAULT: false * - returnFields: Only return these fields. * DEFAULT: Return all fields. * - rfc822Return: Return a Horde_Mail_Rfc822_List object. * DEFAULT: Returns an array of search results. * - sources: (array) The sources to search in. * DEFAULT: Search the user's default address book * - count_only: (boolean) If true, only return the count of matching * results. * DEFAULT: false (Return the full data set). * * @return mixed Either a hash containing the search results or a * Rfc822 List object (if 'rfc822Return' is true). * @throws Turba_Exception */ public function search($names = null, array $opts = array()) { global $attributes, $cfgSources, $injector; $opts = array_merge(array('fields' => array(), 'forceSource' => false, 'matchBegin' => false, 'returnFields' => array(), 'rfc822Return' => false, 'sources' => array(), 'customStrict' => array(), 'count_only' => false), $opts); $results = !empty($opts['count_only']) ? 0 : (empty($opts['rfc822Return']) ? array() : new Horde_Mail_Rfc822_List()); if (!isset($cfgSources) || !is_array($cfgSources) || !count($cfgSources) || is_null($names)) { return $results; } if (!is_array($names)) { $names = array($names); } if (!$opts['forceSource']) { // Make sure the selected source is activated in Turba. $addressbooks = array_keys(Turba::getAddressBooks()); foreach (array_keys($opts['sources']) as $id) { if (!in_array($opts['sources'][$id], $addressbooks)) { unset($opts['sources'][$id]); } } } // ...and ensure the default source is used as a default. if (!count($opts['sources'])) { $opts['sources'] = array(Turba::getDefaultAddressbook()); } $driver = $injector->getInstance('Turba_Factory_Driver'); foreach ($opts['sources'] as $source) { // Skip invalid sources -or- // skip sources that aren't browseable if the search is empty. if (!isset($cfgSources[$source]) || empty($cfgSources[$source]['browse']) && (!count($names) || count($names) == 1 && empty($names[0]))) { continue; } if (empty($opts['fields'][$source])) { $opts['fields'][$source] = $GLOBALS['cfgSources'][$source]['search']; } $sdriver = $driver->create($source); foreach ($names as $name) { $trimname = trim($name); $out = $criteria = array(); unset($tname); if (strlen($trimname)) { if (isset($opts['fields'][$source])) { foreach ($opts['fields'][$source] as $field) { $criteria[$field] = $trimname; } } } try { $search = $sdriver->search($criteria, Turba::getPreferredSortOrder(), 'OR', $opts['returnFields'], $opts['customStrict'], $opts['matchBegin'], $opts['count_only']); } catch (Exception $e) { continue; } if ($opts['count_only']) { $results += $search; continue; } elseif (!$search instanceof Turba_List) { continue; } $rfc822 = new Horde_Mail_Rfc822(); while ($ob = $search->next()) { $emails = $seen = array(); if ($ob->isGroup()) { /* Is a distribution list. */ $members = $ob->listMembers(); if (!$members instanceof Turba_List || !count($members)) { continue; } $listatt = $ob->getAttributes(); $listName = $ob->getValue('name'); while ($ob = $members->next()) { foreach (array_keys($ob->getAttributes()) as $key) { $value = $ob->getValue($key); if (empty($value)) { continue; } $seen_key = trim(Horde_String::lower($ob->getValue('name'))) . trim(Horde_String::lower(is_array($value) ? $value['load']['file'] : $value)); if (isset($attributes[$key]) && $attributes[$key]['type'] == 'email' && empty($seen[$seen_key])) { $emails[] = $value; $seen[$seen_key] = true; } } } if (empty($opts['rfc822Return'])) { $out[] = array('email' => implode(', ', $emails), 'id' => $listatt['__key'], 'name' => $listName, 'source' => $source); } else { $results->add(new Horde_Mail_Rfc822_Group($listName, $emails)); } } else { /* Not a group. */ $att = array('__key' => $ob->getValue('__key')); foreach (array_keys($ob->driver->getCriteria()) as $key) { $att[$key] = $ob->getValue($key); } $email = new Horde_Mail_Rfc822_List(); $display_name = $ob->hasValue('name') || !isset($ob->driver->alternativeName) ? Turba::formatName($ob) : $ob->getValue($ob->driver->alternativeName); unset($tdisplay_name); foreach (array_keys($att) as $key) { if ($ob->getValue($key) && isset($attributes[$key]) && $attributes[$key]['type'] == 'email') { $e_val = $ob->getValue($key); if (strlen($trimname)) { /* Ticket #12480: Don't return email if it * doesn't contain the search string, since * an entry can contain multiple e-mail * fields. Return all e-mails if it * occurs in the name. */ if (!isset($tname)) { $tname = Horde_String_Transliterate::toAscii($name); } if (!isset($tdisplay_name)) { $tdisplay_name = Horde_String_Transliterate::toAscii($display_name); } $add = Horde_String::ipos(Horde_String_Transliterate::toAscii($e_val), $tname) !== false || Horde_String::ipos($tdisplay_name, $tname) !== false; } else { $add = true; } if ($add) { // Multiple addresses support $email->add($rfc822->parseAddressList($e_val, array('limit' => isset($attributes[$key]['params']) && is_array($attributes[$key]['params']) && !empty($attributes[$key]['params']['allow_multi']) ? 0 : 1))); } } } if (count($email)) { foreach ($email as $val) { $seen_key = trim(Horde_String::lower($display_name)) . '/' . Horde_String::lower($val->bare_address); if (empty($seen[$seen_key])) { $seen[$seen_key] = true; if (empty($opts['rfc822Return'])) { $emails[] = $val->bare_address; } else { $val->personal = $display_name; $results->add($val); } } } } elseif (empty($opts['rfc822Return'])) { $emails[] = null; } if (empty($opts['rfc822Return'])) { foreach ($emails as $val) { $out[] = array_merge($att, array('__type' => 'Object', 'email' => $val, 'id' => $att['__key'], 'name' => $display_name, 'source' => $source)); } } } } if (!empty($out)) { $results[$name] = $out; } } } return $results; }
/** * Convert the contact to an ActiveSync contact message * * @param Turba_Object $object The turba object to convert * @param array $options Options: * - protocolversion: (float) The EAS version to support * DEFAULT: 2.5 * - bodyprefs: (array) A BODYPREFERENCE array. * DEFAULT: none (No body prefs enforced). * - truncation: (integer) Truncate event body to this length * DEFAULT: none (No truncation). * - device: (Horde_ActiveSync_Device) The device object. * * @return Horde_ActiveSync_Message_Contact */ public function toASContact(Turba_Object $object, array $options = array()) { global $injector; $message = new Horde_ActiveSync_Message_Contact(array('logger' => $injector->getInstance('Horde_Log_Logger'), 'protocolversion' => $options['protocolversion'], 'device' => !empty($options['device']) ? $options['device'] : null)); $hash = $object->getAttributes(); if (!isset($hash['lastname']) && isset($hash['name'])) { $this->_guessName($hash); } // Ensure we have at least a good guess as to separate address fields. // Not ideal, but EAS does not have a single "address" field so we must // map "common" to either home or work. I choose home since // work/non-personal installs will be more likely to have separated // address fields. if (!empty($hash['commonAddress'])) { if (!isset($hash['commonStreet'])) { $hash['commonStreet'] = $hash['commonHome']; } foreach (array('Address', 'Street', 'POBox', 'Extended', 'City', 'Province', 'PostalCode', 'Country') as $field) { $hash['home' . $field] = $hash['common' . $field]; } } else { if (isset($hash['homeAddress']) && !isset($hash['homeStreet'])) { $hash['homeStreet'] = $hash['homeAddress']; } if (isset($hash['workAddress']) && !isset($hash['workStreet'])) { $hash['workStreet'] = $hash['workAddress']; } } $hooks = $injector->getInstance('Horde_Core_Hooks'); $decode_hook = $hooks->hookExists('decode_attribute', 'turba'); foreach ($hash as $field => $value) { if ($decode_hook) { try { $value = $hooks->callHook('decode_attribute', 'turba', array($field, $value, $object)); } catch (Turba_Exception $e) { Horde::log($e); } } if (isset(self::$_asMap[$field])) { try { $message->{self::$_asMap[$field]} = $value; } catch (InvalidArgumentException $e) { } continue; } switch ($field) { case 'photo': $message->picture = base64_encode($value); break; case 'homeCountry': $message->homecountry = !empty($hash['homeCountryFree']) ? $hash['homeCountryFree'] : !empty($hash['homeCountry']) ? Horde_Nls::getCountryISO($hash['homeCountry']) : null; break; case 'otherCountry': $message->othercountry = !empty($hash['otherCountryFree']) ? $hash['otherCountryFree'] : !empty($hash['otherCountry']) ? Horde_Nls::getCountryISO($hash['otherCountry']) : null; break; case 'workCountry': $message->businesscountry = !empty($hash['workCountryFree']) ? $hash['workCountryFree'] : !empty($hash['workCountry']) ? Horde_Nls::getCountryISO($hash['workCountry']) : null; break; case 'email': $message->email1address = $value; break; case 'homeEmail': $message->email2address = $value; break; case 'workEmail': $message->email3address = $value; break; case 'emails': $address = 1; foreach (explode(',', $value) as $email) { while ($address <= 3 && $message->{'email' . $address . 'address'}) { $address++; } if ($address > 3) { break; } $message->{'email' . $address . 'address'} = $email; $address++; } break; case 'children': // Children FROM horde are a simple string value. Even though EAS // uses an array stucture to pass them, we pass as a single // string since we can't assure what delimter the user will // use and (at least in some languages) a comma can be used // within a full name. $message->children = array($value); break; case 'notes': if ($options['protocolversion'] > Horde_ActiveSync::VERSION_TWOFIVE) { $bp = $options['bodyprefs']; $note = new Horde_ActiveSync_Message_AirSyncBaseBody(); // No HTML supported in Turba's notes. Always use plaintext. $note->type = Horde_ActiveSync::BODYPREF_TYPE_PLAIN; if (isset($bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize'])) { if (Horde_String::length($value) > $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']) { $note->data = Horde_String::substr($value, 0, $bp[Horde_ActiveSync::BODYPREF_TYPE_PLAIN]['truncationsize']); $note->truncated = 1; } else { $note->data = $value; } $note->estimateddatasize = Horde_String::length($value); } $message->airsyncbasebody = $note; } else { // EAS 2.5 $message->body = $value; $message->bodysize = strlen($message->body); $message->bodytruncated = 0; } break; case 'birthday': case 'anniversary': if (!empty($value) && $value != '0000-00-00') { try { $date = new Horde_Date($value); } catch (Horde_Date_Exception $e) { $message->{$field} = null; } // Some sanity checking to make sure the date was // successfully parsed. if ($date->month != 0) { $message->{$field} = $date; } else { $message->{$field} = null; } } else { $message->{$field} = null; } break; } } /* Get tags. */ $message->categories = explode(',', $object->getValue('__tags')); if (empty($this->fileas)) { $message->fileas = Turba::formatName($object); } return $message; }