Changeset f21a04c in github
- Timestamp:
- Nov 10, 2011 2:57:56 AM (19 months ago)
- Branches:
- master, HEAD, courier-fix, dev-browser-capabilities, pdo, release-0.8
- Children:
- d617566
- Parents:
- 81f5dd7
- Files:
-
- 12 edited
-
CHANGELOG (modified) (1 diff)
-
config/main.inc.php.dist (modified) (1 diff)
-
program/include/rcube_addressbook.php (modified) (2 diffs)
-
program/include/rcube_contacts.php (modified) (8 diffs)
-
program/include/rcube_ldap.php (modified) (8 diffs)
-
program/steps/addressbook/copy.inc (modified) (1 diff)
-
program/steps/addressbook/import.inc (modified) (1 diff)
-
program/steps/addressbook/mailto.inc (modified) (1 diff)
-
program/steps/addressbook/save.inc (modified) (1 diff)
-
program/steps/addressbook/search.inc (modified) (2 diffs)
-
program/steps/mail/addcontact.inc (modified) (3 diffs)
-
program/steps/mail/autocomplete.inc (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
CHANGELOG
r62c8618 rf21a04c 2 2 =========================== 3 3 4 - Add option to define matching method for addressbook search (#1486564, #1487907) 4 5 - Make email recipients separator configurable 5 6 - Fix so folders with \Noinferiors attribute aren't listed in parent selector -
config/main.inc.php.dist
r62c8618 rf21a04c 628 628 $rcmail_config['address_template'] = '{street}<br/>{locality} {zipcode}<br/>{country} {region}'; 629 629 630 // Matching mode for addressbook search (including autocompletion) 631 // 0 - partial (*abc*), default 632 // 1 - strict (abc) 633 // 2 - prefix (abc*) 634 // Note: For LDAP sources fuzzy_search must be enabled to use 'partial' or 'prefix' mode 635 $rcmail_config['addressbook_search_mode'] = 0; 636 630 637 // ---------------------------------- 631 638 // USER PREFERENCES -
program/include/rcube_addressbook.php
rdc6c4f4 rf21a04c 97 97 * @param array List of fields to search in 98 98 * @param string Search value 99 * @param int Matching mode: 100 * 0 - partial (*abc*), 101 * 1 - strict (=), 102 * 2 - prefix (abc*) 99 103 * @param boolean True if results are requested, False if count only 100 104 * @param boolean True to skip the count query (select only) … … 102 106 * @return object rcube_result_set List of contact records and 'count' value 103 107 */ 104 abstract function search($fields, $value, $ strict=false, $select=true, $nocount=false, $required=array());108 abstract function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array()); 105 109 106 110 /** -
program/include/rcube_contacts.php
r5e90652 rf21a04c 178 178 " AND user_id=?", 179 179 $group_id, $this->user_id); 180 180 181 181 if ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { 182 182 $sql_arr['ID'] = $sql_arr['contactgroup_id']; 183 183 return $sql_arr; 184 184 } 185 185 186 186 return null; 187 187 } … … 269 269 * @param mixed $fields The field name of array of field names to search in 270 270 * @param mixed $value Search value (or array of values when $fields is array) 271 * @param boolean $strict True for strict (=), False for partial (LIKE) matching 271 * @param int $mode Matching mode: 272 * 0 - partial (*abc*), 273 * 1 - strict (=), 274 * 2 - prefix (abc*) 272 275 * @param boolean $select True if results are requested, False if count only 273 276 * @param boolean $nocount True to skip the count query (select only) … … 276 279 * @return object rcube_result_set Contact records and 'count' value 277 280 */ 278 function search($fields, $value, $ strict=false, $select=true, $nocount=false, $required=array())281 function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array()) 279 282 { 280 283 if (!is_array($fields)) … … 284 287 285 288 $where = $and_where = array(); 289 $mode = intval($mode); 286 290 287 291 foreach ($fields as $idx => $col) { … … 296 300 else if ($col == '*') { 297 301 $words = array(); 298 foreach (explode(" ", self::normalize_string($value)) as $word) 299 $words[] = $this->db->ilike('words', '%'.$word.'%'); 302 foreach (explode(" ", self::normalize_string($value)) as $word) { 303 switch ($mode) { 304 case 1: // strict 305 $words[] = '(' . $this->db->ilike('words', $word.' %') 306 . ' OR ' . $this->db->ilike('words', '% '.$word.' %') 307 . ' OR ' . $this->db->ilike('words', '% '.$word) . ')'; 308 break; 309 case 2: // prefix 310 $words[] = '(' . $this->db->ilike('words', $word.'%') 311 . ' OR ' . $this->db->ilike('words', '% '.$word.'%') . ')'; 312 break; 313 default: // partial 314 $words[] = $this->db->ilike('words', '%'.$word.'%'); 315 } 316 } 300 317 $where[] = '(' . join(' AND ', $words) . ')'; 301 318 } … … 304 321 // table column 305 322 if (in_array($col, $this->table_cols)) { 306 if ($strict) { 323 switch ($mode) { 324 case 1: // strict 307 325 $where[] = $this->db->quoteIdentifier($col).' = '.$this->db->quote($val); 308 } 309 else { 326 break; 327 case 2: // prefix 328 $where[] = $this->db->ilike($col, $val.'%'); 329 break; 330 default: // partial 310 331 $where[] = $this->db->ilike($col, '%'.$val.'%'); 311 332 } … … 314 335 else { 315 336 if (in_array($col, $this->fulltext_cols)) { 316 foreach (explode(" ", self::normalize_string($val)) as $word) 317 $words[] = $this->db->ilike('words', '%'.$word.'%'); 337 foreach (explode(" ", self::normalize_string($val)) as $word) { 338 switch ($mode) { 339 case 1: // strict 340 $words[] = '(' . $this->db->ilike('words', $word.' %') 341 . ' OR ' . $this->db->ilike('words', '% '.$word.' %') 342 . ' OR ' . $this->db->ilike('words', '% '.$word) . ')'; 343 break; 344 case 2: // prefix 345 $words[] = '(' . $this->db->ilike('words', $word.'%') 346 . ' OR ' . $this->db->ilike('words', ' '.$word.'%') . ')'; 347 break; 348 default: // partial 349 $words[] = $this->db->ilike('words', '%'.$word.'%'); 350 } 351 } 318 352 $where[] = '(' . join(' AND ', $words) . ')'; 319 353 } … … 363 397 foreach ((array)$row[$col] as $value) { 364 398 // composite field, e.g. address 365 if (is_array($value)) { 366 $value = implode($value); 367 } 368 $value = mb_strtolower($value); 369 if (($strict && $value == $search) || (!$strict && strpos($value, $search) !== false)) { 370 $found[$colname] = true; 371 break; 399 foreach ((array)$value as $val) { 400 $val = mb_strtolower($val); 401 switch ($mode) { 402 case 1: 403 $got = ($val == $search); 404 break; 405 case 2: 406 $got = ($search == substr($val, 0, strlen($search))); 407 break; 408 default: 409 $got = (strpos($val, $search) !== false); 410 break; 411 } 412 413 if ($got) { 414 $found[$colname] = true; 415 break 2; 416 } 372 417 } 373 418 } -
program/include/rcube_ldap.php
r06744da rf21a04c 699 699 * @param mixed $fields The field name of array of field names to search in 700 700 * @param mixed $value Search value (or array of values when $fields is array) 701 * @param boolean $strict True for strict, False for partial (fuzzy) matching 701 * @param int $mode Matching mode: 702 * 0 - partial (*abc*), 703 * 1 - strict (=), 704 * 2 - prefix (abc*) 702 705 * @param boolean $select True if results are requested, False if count only 703 706 * @param boolean $nocount (Not used) … … 706 709 * @return array Indexed list of contact records and 'count' value 707 710 */ 708 function search($fields, $value, $strict=false, $select=true, $nocount=false, $required=array()) 709 { 711 function search($fields, $value, $mode=0, $select=true, $nocount=false, $required=array()) 712 { 713 $mode = intval($mode); 714 710 715 // special treatment for ID-based search 711 716 if ($fields == 'ID' || $fields == $this->primary_key) … … 739 744 740 745 // get all entries of this page and post-filter those that really match the query 746 $search = mb_strtolower($value); 741 747 $this->result = new rcube_result_set(0); 742 748 $entries = ldap_get_entries($this->conn, $this->ldap_result); 749 743 750 for ($i = 0; $i < $entries['count']; $i++) { 744 751 $rec = $this->_ldap2result($entries[$i]); 745 if (stripos($rec['name'] . $rec['email'], $value) !== false) { 746 $this->result->add($rec); 747 $this->result->count++; 752 foreach (array('email', 'name') as $f) { 753 $val = mb_strtolower($rec[$f]); 754 switch ($mode) { 755 case 1: 756 $got = ($val == $search); 757 break; 758 case 2: 759 $got = ($search == substr($val, 0, strlen($search))); 760 break; 761 default: 762 $got = (strpos($val, $search) !== false); 763 break; 764 } 765 766 if ($got) { 767 $this->result->add($rec); 768 $this->result->count++; 769 break; 770 } 748 771 } 749 772 } … … 754 777 // use AND operator for advanced searches 755 778 $filter = is_array($value) ? '(&' : '(|'; 756 $wc = !$strict && $this->prop['fuzzy_search'] ? '*' : ''; 779 // set wildcards 780 $wp = $ws = ''; 781 if (!empty($this->prop['fuzzy_search']) && $mode != 1) { 782 $ws = '*'; 783 if (!$mode) { 784 $wp = '*'; 785 } 786 } 757 787 758 788 if ($fields == '*') … … 768 798 { 769 799 foreach ($this->prop['search_fields'] as $field) { 770 $filter .= "($field=$w c" . $this->_quote_string($value) . "$wc)";800 $filter .= "($field=$wp" . $this->_quote_string($value) . "$ws)"; 771 801 } 772 802 } … … 777 807 $val = is_array($value) ? $value[$idx] : $value; 778 808 if ($f = $this->_map_field($field)) { 779 $filter .= "($f=$w c" . $this->_quote_string($val) . "$wc)";809 $filter .= "($f=$wp" . $this->_quote_string($val) . "$ws)"; 780 810 } 781 811 } … … 1434 1464 $groups = array(); 1435 1465 if ($search) { 1436 $search = strtolower($search);1466 $search = mb_strtolower($search); 1437 1467 foreach ($group_cache as $group) { 1438 if (str str(strtolower($group['name']), $search))1468 if (strpos(mb_strtolower($group['name']), $search) !== false) 1439 1469 $groups[] = $group; 1440 1470 } … … 1512 1542 } 1513 1543 1514 $group_sortnames[] = strtolower($ldap_data[$i][$sort_attr][0]);1544 $group_sortnames[] = mb_strtolower($ldap_data[$i][$sort_attr][0]); 1515 1545 } 1516 1546 -
program/steps/addressbook/copy.inc
r2d761bb rf21a04c 61 61 // Note: Some addressbooks allows empty email address field 62 62 if (!empty($a_record['email'])) 63 $result = $TARGET->search('email', $a_record['email'], true, true, true);63 $result = $TARGET->search('email', $a_record['email'], 1, true, true); 64 64 else if (!empty($a_record['name'])) 65 $result = $TARGET->search('name', $a_record['name'], true, true, true);65 $result = $TARGET->search('name', $a_record['name'], 1, true, true); 66 66 else 67 67 $result = new rcube_result_set(); -
program/steps/addressbook/import.inc
r4d4a2fa rf21a04c 175 175 if (!$replace && $email) { 176 176 // compare e-mail address 177 $existing = $CONTACTS->search('email', $email, false, false);177 $existing = $CONTACTS->search('email', $email, 1, false); 178 178 if (!$existing->count && $vcard->displayname) { // compare display name 179 $existing = $CONTACTS->search('name', $vcard->displayname, false, false);179 $existing = $CONTACTS->search('name', $vcard->displayname, 1, false); 180 180 } 181 181 if ($existing->count) { -
program/steps/addressbook/mailto.inc
rdc6c4f4 rf21a04c 32 32 $CONTACTS->set_page(1); 33 33 $CONTACTS->set_pagesize(count($cid) + 2); // +2 to skip counting query 34 $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, false, true, true, 'email');34 $recipients = $CONTACTS->search($CONTACTS->primary_key, $cid, 0, true, true, 'email'); 35 35 } 36 36 } -
program/steps/addressbook/save.inc
r5db6f96 rf21a04c 163 163 $existing = false; 164 164 foreach ($CONTACTS->get_col_values('email', $a_record, true) as $email) { 165 if ($email && ($res = $CONTACTS->search('email', $email, false, false, true)) && $res->count) {165 if ($email && ($res = $CONTACTS->search('email', $email, 1, false, true)) && $res->count) { 166 166 $OUTPUT->show_message('contactexists', 'notice', null, false); 167 167 break; -
program/steps/addressbook/search.inc
rb104e39 rf21a04c 138 138 } 139 139 140 // Values matching mode 141 $mode = (int) $RCMAIL->config->get('addressbook_search_mode'); 142 140 143 // get sources list 141 144 $sources = $RCMAIL->get_address_sources(); … … 169 172 170 173 // get contacts count 171 $result = $source->search($fields, $search, false, false);174 $result = $source->search($fields, $search, $mode, false); 172 175 173 176 if (!$result->count) { -
program/steps/mail/addcontact.inc
r39cafac rf21a04c 51 51 $OUTPUT->send(); 52 52 } 53 53 54 54 $email = rcube_idn_to_ascii($contact['email']); 55 55 if (!check_email($email, false)) { … … 66 66 // TODO: show dialog to complete record 67 67 // if ($error['type'] == rcube_addressbook::ERROR_VALIDATE) { } 68 68 69 69 $OUTPUT->show_message($error['message'] ? $error['message'] : 'errorsavingcontact', 'error'); 70 70 $OUTPUT->send(); … … 72 72 73 73 // check for existing contacts 74 $existing = $CONTACTS->search('email', $contact['email'], true, false);74 $existing = $CONTACTS->search('email', $contact['email'], 1, false); 75 75 76 76 if ($done = $existing->count) -
program/steps/mail/autocomplete.inc
r62c8618 rf21a04c 42 42 43 43 $MAXNUM = (int)$RCMAIL->config->get('autocomplete_max', 15); 44 $mode = (int) $RCMAIL->config->get('addressbook_search_mode'); 44 45 $search = get_input_value('_search', RCUBE_INPUT_GPC, true); 45 46 $source = get_input_value('_source', RCUBE_INPUT_GPC); … … 59 60 $abook->set_pagesize($MAXNUM); 60 61 61 if ($result = $abook->search(array('email','name'), $search, false, true, true, 'email')) {62 if ($result = $abook->search(array('email','name'), $search, $mode, true, true, 'email')) { 62 63 while ($sql_arr = $result->iterate()) { 63 64 // Contact can have more than one e-mail address … … 83 84 84 85 // also list matching contact groups 85 if ($abook->groups ) {86 if ($abook->groups && count($contacts) < $MAXNUM) { 86 87 foreach ($abook->list_groups($search) as $group) { 87 88 $abook->reset();
Note: See TracChangeset
for help on using the changeset viewer.
