thomascube
2011-10-07 39cafac3f5e9cff676b379c1ecb1c847eec558e2
Autocomplete LDAP records when adding contacts from mail (#1488073)

5 files modified
109 ■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/include/rcube_addressbook.php 7 ●●●●● patch | view | raw | blame | history
program/include/rcube_contacts.php 7 ●●●●● patch | view | raw | blame | history
program/include/rcube_ldap.php 84 ●●●● patch | view | raw | blame | history
program/steps/mail/addcontact.inc 10 ●●●●● patch | view | raw | blame | history
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)
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;
                }
            }
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;
        }
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)
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);