From 39cafac3f5e9cff676b379c1ecb1c847eec558e2 Mon Sep 17 00:00:00 2001 From: thomascube <thomas@roundcube.net> Date: Fri, 07 Oct 2011 07:07:23 -0400 Subject: [PATCH] Autocomplete LDAP records when adding contacts from mail (#1488073) --- CHANGELOG | 1 program/include/rcube_addressbook.php | 7 ++- program/include/rcube_ldap.php | 84 ++++++++++++++++++++++++++++++----------- program/include/rcube_contacts.php | 7 ++- program/steps/mail/addcontact.inc | 10 +++++ 5 files changed, 80 insertions(+), 29 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 748d930..f9c1ff0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Autocomplete LDAP records when adding contacts from mail (#1488073) - Plugin API: added 'ready' hook (#1488063) - Ignore DSN request when it isn't supported by SMTP server (#1487800) - Make sure LDAP name fields aren't arrays (#1488108) diff --git a/program/include/rcube_addressbook.php b/program/include/rcube_addressbook.php index 94a715b..88f0aa9 100644 --- a/program/include/rcube_addressbook.php +++ b/program/include/rcube_addressbook.php @@ -30,7 +30,7 @@ /** constants for error reporting **/ const ERROR_READ_ONLY = 1; const ERROR_NO_CONNECTION = 2; - const ERROR_INCOMPLETE = 3; + const ERROR_VALIDATE = 3; const ERROR_SAVING = 4; const ERROR_SEARCH = 5; @@ -182,15 +182,16 @@ * If input isn't valid, the message to display can be fetched using get_error() * * @param array Assoziative array with data to save + * @param boolean Attempt to fix/complete record automatically * @return boolean True if input is valid, False if not. */ - public function validate($save_data) + public function validate(&$save_data, $autofix = false) { // check validity of email addresses foreach ($this->get_col_values('email', $save_data, true) as $email) { if (strlen($email)) { if (!check_email(rcube_idn_to_ascii($email))) { - $this->set_error('warning', rcube_label(array('name' => 'emailformaterror', 'vars' => array('email' => $email)))); + $this->set_error(self::ERROR_VALIDATE, rcube_label(array('name' => 'emailformaterror', 'vars' => array('email' => $email)))); return false; } } diff --git a/program/include/rcube_contacts.php b/program/include/rcube_contacts.php index 3ad53a6..c810ce6 100644 --- a/program/include/rcube_contacts.php +++ b/program/include/rcube_contacts.php @@ -500,16 +500,17 @@ * If input not valid, the message to display can be fetched using get_error() * * @param array Assoziative array with data to save + * @param boolean Try to fix/complete record automatically * @return boolean True if input is valid, False if not. */ - public function validate($save_data) + public function validate(&$save_data, $autofix = false) { // validate e-mail addresses - $valid = parent::validate($save_data); + $valid = parent::validate($save_data, $autofix); // 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'); + $this->set_error(self::ERROR_VALIDATE, 'noemailwarning'); $valid = false; } diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php index a3f6dc5..3af343f 100644 --- a/program/include/rcube_ldap.php +++ b/program/include/rcube_ldap.php @@ -448,13 +448,6 @@ return $this->result; } - // add general filter to query - if (!empty($this->prop['filter']) && empty($this->filter)) - { - $filter = $this->prop['filter']; - $this->set_search_set($filter); - } - // query URL is given by the selected group if ($this->group_id && $this->group_url) { @@ -463,9 +456,13 @@ { $this->base_dn = $m[1]; $this->prop['scope'] = $m[2]; - $this->filter = $m[3]; + $this->filter = $this->filter ? '(&(' . $m[3] . ')(' . $this->filter . '))' : $m[3]; } } + + // add general filter to query + if (!empty($this->prop['filter']) && empty($this->filter)) + $this->set_search_set($this->prop['filter']); // exec LDAP search if no result resource is stored if ($this->conn && !$this->ldap_result) @@ -689,19 +686,49 @@ * If input not valid, the message to display can be fetched using get_error() * * @param array Assoziative array with data to save - * + * @param boolean Try to fix/complete record automatically * @return boolean True if input is valid, False if not. */ - public function validate($save_data) + public function validate(&$save_data, $autofix = false) { // check for name input if (empty($save_data['name'])) { - $this->set_error('warning', 'nonamewarning'); + $this->set_error(self::ERROR_VALIDATE, 'nonamewarning'); + return false; + } + + // Verify that the required fields are set. + $missing = null; + $ldap_data = $this->_map_data($save_data); + foreach ($this->prop['required_fields'] as $fld) { + if (!isset($ldap_data[$fld])) { + $missing[$fld] = 1; + } + } + + if ($missing) { + // try to complete record automatically + if ($autofix) { + $reverse_map = array_flip($this->fieldmap); + $name_parts = preg_split('/[\s,.]+/', $save_data['name']); + if ($missing['sn']) { + $sn_field = $reverse_map['sn']; + $save_data[$sn_field] = array_pop ($name_parts); + } + if ($missing[($fn_field = $this->fieldmap['firstname'])]) { + $save_data['firstname'] = array_shift($name_parts); + } + + return $this->validate($save_data, false); + } + + // TODO: generate message saying which fields are missing + $this->set_error(self::ERROR_VALIDATE, 'formincomplete'); return false; } // validate e-mail addresses - return parent::validate($save_data); + return parent::validate($save_data, $autofix); } @@ -715,17 +742,8 @@ function insert($save_cols) { // Map out the column names to their LDAP ones to build the new entry. - $newentry = array(); + $newentry = $this->_map_data($save_cols); $newentry['objectClass'] = $this->prop['LDAP_Object_Classes']; - foreach ($this->fieldmap as $col => $fld) { - $val = $save_cols[$col]; - if (is_array($val)) - $val = array_filter($val); // remove empty entries - if ($fld && $val) { - // The field does exist, add it to the entry. - $newentry[$fld] = $val; - } // end if - } // end foreach // Verify that the required fields are set. $missing = null; @@ -738,7 +756,7 @@ // abort process if requiered fields are missing // TODO: generate message saying which fields are missing if ($missing) { - $this->set_error(self::ERROR_INCOMPLETE, 'formincomplete'); + $this->set_error(self::ERROR_VALIDATE, 'formincomplete'); return false; } @@ -1052,6 +1070,26 @@ /** + * Convert a record data set into LDAP field attributes + */ + private function _map_data($save_cols) + { + $ldap_data = array(); + foreach ($this->fieldmap as $col => $fld) { + $val = $save_cols[$col]; + if (is_array($val)) + $val = array_filter($val); // remove empty entries + if ($fld && $val) { + // The field does exist, add it to the entry. + $ldap_data[$fld] = $val; + } + } + + return $ldap_data; + } + + + /** * Returns unified attribute name (resolving aliases) */ private static function _attr_name($name) diff --git a/program/steps/mail/addcontact.inc b/program/steps/mail/addcontact.inc index b74d95f..dafb276 100644 --- a/program/steps/mail/addcontact.inc +++ b/program/steps/mail/addcontact.inc @@ -60,6 +60,16 @@ $contact['email'] = rcube_idn_to_utf8($contact['email']); $contact['name'] = rcube_addressbook::compose_display_name($contact); + // validate contact record + if (!$CONTACTS->validate($contact, true)) { + $error = $CONTACTS->get_error(); + // TODO: show dialog to complete record + // if ($error['type'] == rcube_addressbook::ERROR_VALIDATE) { } + + $OUTPUT->show_message($error['message'] ? $error['message'] : 'errorsavingcontact', 'error'); + $OUTPUT->send(); + } + // check for existing contacts $existing = $CONTACTS->search('email', $contact['email'], true, false); -- Gitblit v1.9.1