Improve display name composition when saving contacts (#1487143), with plugin-support; allow empty names in sql address book, fall back to e-mail address in listing and vcard export
| | |
| | | CHANGELOG Roundcube Webmail |
| | | =========================== |
| | | |
| | | - Improve display name composition when saving contacts (#1487143) |
| | | - Fixed handling of folder with name "0" in folder selector |
| | | - Fix problems with subfolders of INBOX folder on some IMAP servers (#1487725) |
| | | - Fix handling of folders that doesn't belong to any namespace (#1487637) |
| | |
| | | |
| | | /** |
| | | * Check the given data before saving. |
| | | * If input not valid, the message to display can be fetched using get_error() |
| | | * If input isn't valid, the message to display can be fetched using get_error() |
| | | * |
| | | * @param array Assoziative array with data to save |
| | | * @return boolean True if input is valid, False if not. |
| | | */ |
| | | public function validate($save_data) |
| | | { |
| | | if (empty($save_data['name'])) { |
| | | $this->set_error('warning', 'nonamewarning'); |
| | | return false; |
| | | } |
| | | |
| | | // check validity of email addresses |
| | | foreach ($this->get_col_values('email', $save_data, true) as $email) { |
| | | if (strlen($email)) { |
| | |
| | | |
| | | return join(" ", $arr); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Compose a valid display name from the given structured contact data |
| | | * |
| | | * @param array Hash array with contact data as key-value pairs |
| | | * @return string Display name |
| | | */ |
| | | public static function compose_display_name($contact) |
| | | { |
| | | $contact = rcmail::get_instance()->plugins->exec_hook('contact_displayname', $contact); |
| | | $fn = $contact['name']; |
| | | |
| | | if (!$fn) |
| | | $fn = join(' ', array_filter(array($contact['prefix'], $contact['firstname'], $contact['middlename'], $contact['surname'], $contact['suffix']))); |
| | | |
| | | // use email address part for name |
| | | $email = is_array($contact['email']) ? $contact['email'][0] : $contact['email']; |
| | | if ($email && (empty($fn) || $fn == $email)) { |
| | | list($emailname) = explode('@', $email); |
| | | if (preg_match('/(.*)[\.\-\_](.*)/', $emailname, $match)) |
| | | $fn = trim(ucfirst($match[1]).' '.ucfirst($match[2])); |
| | | else |
| | | $fn = ucfirst($emailname); |
| | | } |
| | | |
| | | return $fn; |
| | | } |
| | | |
| | | } |
| | | |
| | |
| | | " AND c.user_id=?" . |
| | | ($this->group_id ? " AND m.contactgroup_id=?" : ""). |
| | | ($this->filter ? " AND (".$this->filter.")" : "") . |
| | | " ORDER BY c.name", |
| | | " ORDER BY c.name, c.email", |
| | | $start_row, |
| | | $length, |
| | | $this->user_id, |
| | |
| | | */ |
| | | public function validate($save_data) |
| | | { |
| | | // check for name input |
| | | // validate e-mail addresses |
| | | $valid = parent::validate($save_data); |
| | | |
| | | // require at least one e-mail address (syntax check is done later in save.inc) |
| | | // require at least one e-mail address (syntax check is already done) |
| | | if ($valid && !array_filter($this->get_col_values('email', $save_data, true))) { |
| | | $this->set_error('warning', 'noemailwarning'); |
| | | $valid = false; |
| | |
| | | |
| | | |
| | | /** |
| | | * Check the given data before saving. |
| | | * If input not valid, the message to display can be fetched using get_error() |
| | | * |
| | | * @param array Assoziative array with data to save |
| | | * @return boolean True if input is valid, False if not. |
| | | */ |
| | | public function validate($save_data) |
| | | { |
| | | // check for name input |
| | | if (empty($save_data['name'])) { |
| | | $this->set_error('warning', 'nonamewarning'); |
| | | return false; |
| | | } |
| | | |
| | | // validate e-mail addresses |
| | | return parent::validate($save_data); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Create a new contact record |
| | | * |
| | | * @param array Hash array with save data |
| | |
| | | $this->email[0] = $this->email[$pref_index]; |
| | | $this->email[$pref_index] = $tmp; |
| | | } |
| | | |
| | | // make sure displayname is not empty (required by RFC2426) |
| | | if (!strlen($this->displayname)) { |
| | | // the same method is used in steps/mail/addcontact.inc |
| | | $this->displayname = ucfirst(preg_replace('/[\.\-]/', ' ', |
| | | substr($this->email[0], 0, strpos($this->email[0], '@')))); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | while ($type == "N" && is_array($entries[0]) && count($entries[0]) < 5) |
| | | $entries[0][] = ""; |
| | | |
| | | // make sure FN is not empty (required by RFC2426) |
| | | if ($type == "FN" && empty($entries)) |
| | | $entries[0] = $data['EMAIL'][0][0]; |
| | | |
| | | foreach((array)$entries as $entry) { |
| | | $attr = ''; |
| | | if (is_array($entry)) { |
| | |
| | | | program/steps/addressbook/export.inc | |
| | | | | |
| | | | This file is part of the Roundcube Webmail client | |
| | | | Copyright (C) 2008-2009, The Roundcube Dev Team | |
| | | | Copyright (C) 2008-2011, The Roundcube Dev Team | |
| | | | Licensed under the GNU GPL | |
| | | | | |
| | | | PURPOSE: | |
| | |
| | | |
| | | while ($result && ($row = $result->next())) { |
| | | // we already have a vcard record |
| | | if ($row['vcard']) { |
| | | if ($row['vcard'] && $row['name']) { |
| | | echo rcube_vcard::rfc2425_fold($row['vcard']) . "\n"; |
| | | } |
| | | // copy values into vcard object |
| | |
| | | // render head section with name fields (not a regular list of rows) |
| | | if ($section == 'head') { |
| | | $content = ''; |
| | | |
| | | // TODO: use the save name composition function as in save.inc |
| | | $names_arr = array($record['prefix'], $record['firstname'], $record['middlename'], $record['surname'], $record['suffix']); |
| | | if ($record['name'] == join(' ', array_filter($names_arr))) |
| | | |
| | | // unset display name if it is composed from name parts (same composition function as in save.inc) |
| | | if ($record['name'] == rcube_addressbook::compose_display_name(array('name' => '') + $record)) |
| | | unset($record['name']); |
| | | |
| | | // group fields |
| | |
| | | } |
| | | } |
| | | |
| | | // let a dedicated function or a plugin compose the full name if empty |
| | | if (empty($a_record['name'])) { |
| | | // TODO: let a dedicated function or a plugin compose the full name |
| | | $a_record['name'] = join(' ', array_filter(array($a_record['prefix'], $a_record['firstname'], $a_record['middlename'], $a_record['surname'], $a_record['suffix'],))); |
| | | $a_record['name'] = rcube_addressbook::compose_display_name($a_record); |
| | | } |
| | | |
| | | |
| | |
| | | // define list of cols to be displayed |
| | | $a_js_cols = array(); |
| | | $record = $CONTACTS->get_record($newcid ? $newcid : $cid, true); |
| | | $record['email'] = reset($CONTACTS->get_col_values('email', $record, true)); |
| | | if (!$record['name']) |
| | | $record['name'] = $record['email']; |
| | | |
| | | foreach (array('name', 'email') as $col) |
| | | $a_js_cols[] = (string)$record[$col]; |
| | |
| | | } |
| | | |
| | | $contact['email'] = rcube_idn_to_utf8($contact['email']); |
| | | |
| | | // use email address part for name |
| | | if (empty($contact['name']) || $contact['name'] == $contact['email']) |
| | | $contact['name'] = ucfirst(preg_replace('/[\.\-]/', ' ', substr($contact['email'], 0, strpos($contact['email'], '@')))); |
| | | $contact['name'] = rcube_addressbook::compose_display_name($contact); |
| | | |
| | | // check for existing contacts |
| | | $existing = $CONTACTS->search('email', $contact['email'], true, false); |