Aleksander Machniak
2013-01-07 83f7077ec930952cdc9cfc8982b80cd4dad06b5f
Fix searching by date in address book (#1488888)
6 files modified
110 ■■■■■ changed files
CHANGELOG 1 ●●●● patch | view | raw | blame | history
program/js/app.js 11 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_addressbook.php 50 ●●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_contacts.php 25 ●●●● patch | view | raw | blame | history
program/lib/Roundcube/rcube_ldap.php 17 ●●●● patch | view | raw | blame | history
program/steps/addressbook/search.inc 6 ●●●● patch | view | raw | blame | history
CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
- Fix searching by date in address book (#1488888)
- Improve charset detection by prioritizing charset according to user language (#1485669)
- Fix handling of escaped separator in vCard file (#1488896)
- Fix #countcontrols issue in IE<=8 when text is very long (#1488890)
program/js/app.js
@@ -361,7 +361,7 @@
        if (this.gui_objects.editform) {
          this.enable_command('save', true);
          if (this.env.action == 'add' || this.env.action == 'edit')
          if (this.env.action == 'add' || this.env.action == 'edit' || this.env.action == 'search')
              this.init_contact_form();
        }
@@ -4396,10 +4396,11 @@
  {
    var ref = this, col;
    this.set_photo_actions($('#ff_photo').val());
    for (col in this.env.coltypes)
      this.init_edit_field(col, null);
    if (this.env.coltypes) {
      this.set_photo_actions($('#ff_photo').val());
      for (col in this.env.coltypes)
        this.init_edit_field(col, null);
    }
    $('.contactfieldgroup .row a.deletebutton').click(function() {
      ref.delete_edit_field(this);
program/lib/Roundcube/rcube_addressbook.php
@@ -46,6 +46,7 @@
    public $sort_order = 'ASC';
    public $coltypes = array('name' => array('limit'=>1), 'firstname' => array('limit'=>1), 'surname' => array('limit'=>1), 'email' => array('limit'=>1));
    protected $date_types = array();
    protected $error;
    /**
@@ -221,7 +222,6 @@
        return true;
    }
    /**
     * Create a new contact record
@@ -407,7 +407,6 @@
        return array();
    }
    /**
     * Utility function to return all values of a certain data column
     * either as flat list or grouped by subtype
@@ -439,7 +438,6 @@
        return $out;
    }
    /**
     * Normalize the given string for fulltext search.
@@ -488,7 +486,6 @@
        return $fn;
    }
    /**
     * Compose the name to display in the contacts list for the given contact record.
     * This respects the settings parameter how to list conacts.
@@ -526,5 +523,50 @@
        return $fn;
    }
    /**
     * Compare search value with contact data
     *
     * @param string       $colname Data name
     * @param string|array $value   Data value
     * @param string       $search  Search value
     * @param int          $mode    Search mode
     *
     * @return bool Comparision result
     */
    protected function compare_search_value($colname, $value, $search, $mode)
    {
        // The value is a date string, for date we'll
        // use only strict comparison (mode = 1)
        // @TODO: partial search, e.g. match only day and month
        if (in_array($colname, $this->date_types)) {
            return (($value = rcube_utils::strtotime($value))
                && ($search = rcube_utils::strtotime($search))
                && date('Ymd', $value) == date('Ymd', $search));
        }
        // composite field, e.g. address
        foreach ((array)$value as $val) {
            $val = mb_strtolower($val);
            switch ($mode) {
            case 1:
                $got = ($val == $search);
                break;
            case 2:
                $got = ($search == substr($val, 0, strlen($search)));
                break;
            default:
                $got = (strpos($val, $search) !== false);
            }
            if ($got) {
                return true;
            }
        }
        return false;
    }
}
program/lib/Roundcube/rcube_contacts.php
@@ -45,6 +45,7 @@
    private $fulltext_cols = array('name', 'firstname', 'surname', 'middlename', 'nickname',
      'jobtitle', 'organization', 'department', 'maidenname', 'email', 'phone',
      'address', 'street', 'locality', 'zipcode', 'region', 'country', 'website', 'im', 'notes');
    protected $date_types = array('birthday', 'anniversary');
    // public properties
    public $primary_key = 'contact_id';
@@ -401,32 +402,16 @@
            for ($i=0; $i<$pages; $i++) {
                $this->list_records(null, $i, true);
                while ($row = $this->result->next()) {
                    $id = $row[$this->primary_key];
                    $id    = $row[$this->primary_key];
                    $found = array();
                    foreach (preg_grep($regexp, array_keys($row)) as $col) {
                        $pos     = strpos($col, ':');
                        $colname = $pos ? substr($col, 0, $pos) : $col;
                        $search  = $post_search[$colname];
                        foreach ((array)$row[$col] as $value) {
                            // composite field, e.g. address
                            foreach ((array)$value as $val) {
                                $val = mb_strtolower($val);
                                switch ($mode) {
                                case 1:
                                    $got = ($val == $search);
                                    break;
                                case 2:
                                    $got = ($search == substr($val, 0, strlen($search)));
                                    break;
                                default:
                                    $got = (strpos($val, $search) !== false);
                                    break;
                                }
                                if ($got) {
                                    $found[$colname] = true;
                                    break 2;
                                }
                            if ($this->compare_search_value($colname, $value, $search, $mode)) {
                                $found[$colname] = true;
                                break 2;
                            }
                        }
                    }
program/lib/Roundcube/rcube_ldap.php
@@ -794,27 +794,14 @@
            $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)");
            // get all entries of this page and post-filter those that really match the query
            $search = mb_strtolower($value);
            $search  = mb_strtolower($value);
            $entries = ldap_get_entries($this->conn, $this->ldap_result);
            for ($i = 0; $i < $entries['count']; $i++) {
                $rec = $this->_ldap2result($entries[$i]);
                foreach ($fields as $f) {
                    foreach ((array)$rec[$f] as $val) {
                        $val = mb_strtolower($val);
                        switch ($mode) {
                        case 1:
                            $got = ($val == $search);
                            break;
                        case 2:
                            $got = ($search == substr($val, 0, strlen($search)));
                            break;
                        default:
                            $got = (strpos($val, $search) !== false);
                            break;
                        }
                        if ($got) {
                        if ($this->compare_search_value($f, $val, $search, $mode)) {
                            $this->result->add($rec);
                            $this->result->count++;
                            break 2;
program/steps/addressbook/search.inc
@@ -300,9 +300,13 @@
            $label    = isset($colprop['label']) ? $colprop['label'] : rcube_label($col);
            $category = $colprop['category'] ? $colprop['category'] : 'other';
            if ($ftype == 'text')
            // load jquery UI datepicker for date fields
            if ($colprop['type'] == 'date')
                $colprop['class'] .= ($colprop['class'] ? ' ' : '') . 'datepicker';
            else if ($ftype == 'text')
                $colprop['size'] = $i_size;
            $content  = html::div('row', html::div('contactfieldlabel label', Q($label))
                . html::div('contactfieldcontent', rcmail_get_edit_field('search_'.$col, '', $colprop, $ftype)));