More intelligent ordering of autocomplete search results
authorMichael M Slusarz <slusarz@curecanti.org>
Fri, 11 Sep 2009 20:26:36 +0000 (14:26 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Fri, 11 Sep 2009 20:28:48 +0000 (14:28 -0600)
Uses the php levenshtein() function.
This only works with results from the server (not autocomplete results
done via the js code).
Might change this in the future to a QuickSilver inspired sort (see,
e.g., http://github.com/rmm5t/liquidmetal) since this would result in a
sort order that is consistent if done either server-side or
browser-side.

imp/docs/CHANGES
imp/lib/Ajax/Imple/ContactAutoCompleter.php
imp/lib/Compose.php

index ccba766..64e23b6 100644 (file)
@@ -2,6 +2,7 @@
 v5.0-git
 --------
 
+[mms] More intelligent ordering of autocomplete search results.
 [mms] Add a mini search query interface (Request #6875).
 [mms] Make DIMP quicksearch field selection persist across sessions.
 [mms] Move JS/CSS caching to Horde framework.
index 27f55ee..d51ad98 100644 (file)
@@ -126,7 +126,7 @@ class IMP_Ajax_Imple_ContactAutoCompleter extends Horde_Ajax_Imple_Base
             return array();
         }
 
-        return array_map('htmlspecialchars', IMP_Compose::expandAddresses($input));
+        return array_map('htmlspecialchars', IMP_Compose::expandAddresses($input, array('levenshtein' => true)));
     }
 
 }
index dd0c45c..abfa1a1 100644 (file)
@@ -2459,14 +2459,34 @@ class IMP_Compose
      * will not search if the address string is empty.
      *
      * @param string $addrString  The name(s) or address(es) to expand.
+     * @param array $options      Additional options:
+     * <pre>
+     * 'levenshtein' - (boolean) If true, will sort the results using the
+     *                 PHP levenshtein() scoring function.
+     * </pre>
      *
      * @return array  All matching addresses.
      */
-    static public function expandAddresses($addrString)
+    static public function expandAddresses($addrString, $options = array())
     {
-        return preg_match('|[^\s]|', $addrString)
-            ? self::getAddressList(reset(array_filter(array_map('trim', Horde_Mime_Address::explode($addrString, ',;')))))
-            : '';
+        if (!preg_match('|[^\s]|', $addrString)) {
+            return array();
+        }
+
+        $addrString = reset(array_filter(array_map('trim', Horde_Mime_Address::explode($addrString, ',;'))));
+        $addr_list = self::getAddressList($addrString);
+
+        if (empty($options['levenshtein'])) {
+            return $addr_list;
+        }
+
+        $sort_list = array();
+        foreach ($addr_list as $val) {
+            $sort_list[$val] = levenshtein($addrString, $val);
+        }
+        asort($sort_list, SORT_NUMERIC);
+
+        return array_keys($sort_list);
     }
 
     /**
@@ -2481,7 +2501,7 @@ class IMP_Compose
     {
         $sparams = self::getAddressSearchParams();
         try {
-            $res = $GLOBALS['registry']->call('contacts/search', array($search, $sparams['sources'], $sparams['fields'], true));
+            $res = $GLOBALS['registry']->call('contacts/search', array($search, $sparams['sources'], $sparams['fields'], false));
         } catch (Horde_Exception $e) {
             Horde::logMessage($e, __FILE__, __LINE__, PEAR_LOG_ERR);
             return array();