Ticket #6875: Re-add OR searches to advanced search
authorMichael M Slusarz <slusarz@curecanti.org>
Tue, 29 Sep 2009 19:04:25 +0000 (13:04 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Tue, 29 Sep 2009 19:42:54 +0000 (13:42 -0600)
imp/js/search.js
imp/lib/LoginTasks/SystemTask/UpgradeFromImp4.php
imp/lib/Search.php
imp/lib/UI/Search.php
imp/search.php
imp/templates/search/search.html

index 614870b..dbfc7c9 100644 (file)
@@ -62,6 +62,11 @@ var ImpSearch = {
         this.resetCriteria();
 
         criteria.each(function(c) {
+            if (c.t == 'or') {
+                this.insertOr();
+                return;
+            }
+
             switch (this.data.types[c.t]) {
             case 'header':
             case 'body':
@@ -110,11 +115,6 @@ var ImpSearch = {
         // TODO: type
     },
 
-    resetCriteria: function()
-    {
-        $('search_criteria_table').childElements().invoke('remove');
-    },
-
     changeHandler: function(e)
     {
         var elt = e.element(), val = $F(elt);
@@ -126,6 +126,11 @@ var ImpSearch = {
             break;
 
         case 'search_criteria':
+            if (val == 'or') {
+                this.insertOr();
+                break;
+            }
+
             switch (this.data.types[val]) {
             case 'header':
             case 'body':
@@ -164,15 +169,36 @@ var ImpSearch = {
         return $('search_criteria').down('[value=' + id + ']').getText() + ': ';
     },
 
-    insertCriteria: function(tds)
+    deleteCriteria: function(tr)
+    {
+        delete this.criteria[tr.identify()];
+        tr.remove();
+        if ($('search_criteria_table').childElements().size()) {
+            $('search_criteria_table').down('TR TD').update('');
+        } else {
+            $('search_criteria').down('[value="or"]').hide().next().hide();
+        }
+    },
+
+    resetCriteria: function()
+    {
+        $('search_criteria_table').childElements().each(this.deleteCriteria.bind(this));
+    },
+
+    insertCriteria: function(tds, or)
     {
         var tr = new Element('TR'),
             td = new Element('TD');
 
-        if ($('search_criteria_table').childElements().size()) {
+        if (!or &&
+            $('search_criteria_table').childElements().size() &&
+            this.criteria[$('search_criteria_table').childElements().last().readAttribute('id')].t != 'or') {
             tds.unshift(new Element('EM', { className: 'join' }).insert(this.text.and));
         } else {
             tds.unshift('');
+            if (!or) {
+                $('search_criteria').down('[value="or"]').show().next().show();
+            }
         }
 
         tds.each(function(node) {
@@ -187,6 +213,11 @@ var ImpSearch = {
         return tr.identify();
     },
 
+    insertOr: function()
+    {
+        this.criteria[this.insertCriteria([ new Element('EM', { className: 'join' }).insert(this.text.or + ' ') ], true)] = { t: 'or' };
+    },
+
     insertText: function(id, text, not)
     {
         var tmp = [
@@ -278,6 +309,11 @@ var ImpSearch = {
                 tmp.each(function(c) {
                     var tmp2;
 
+                    if (this.criteria[c].t == 'or') {
+                        data.push(this.criteria[c]);
+                        return;
+                    }
+
                     switch (this.data.types[this.criteria[c].t]) {
                     case 'header':
                     case 'body':
@@ -377,12 +413,7 @@ var ImpSearch = {
                         elt.next('SPAN.searchuiFoldersActions').toggle();
                     }
                 } else if (elt.hasClassName('searchuiDelete')) {
-                    tmp = elt.up('TR');
-                    delete this.criteria[tmp.identify()];
-                    tmp.remove();
-                    if ($('search_criteria_table').childElements().size()) {
-                        $('search_criteria_table').down('TR TD').update('');
-                    }
+                    this.deleteCriteria(elt.up('TR'));
                     e.stop();
                     return;
                 } else if (elt.hasClassName('searchuiCalendar')) {
index 438a57a..5ba8b7a 100644 (file)
@@ -78,11 +78,7 @@ class IMP_LoginTasks_SystemTask_UpgradeFromImp4 extends Horde_LoginTasks_SystemT
 
             $ui = $vfolder['uiinfo'];
 
-            // TODO: match == 'or' ($ob['match']
-            if ($ui['match'] == 'or') {
-                $GLOBALS['imp_search']->deleteSearchQuery($id);
-                continue;
-            }
+            $or_match = ($ui['match'] == 'or');
 
             /* BC: Convert old (IMP < 4.2.1) style w/separate flag entry to
              * new style where flags are part of the fields to query. */
@@ -151,6 +147,12 @@ class IMP_LoginTasks_SystemTask_UpgradeFromImp4 extends Horde_LoginTasks_SystemT
                 }
 
                 $rules[] = $tmp;
+
+                if ($or_match) {
+                    $tmp = new stdClass;
+                    $tmp->t = 'or';
+                    $rules[] = $tmp;
+                }
             }
 
             /* This will overwrite the existing entry. */
index 3791402..1381aeb 100644 (file)
@@ -24,7 +24,7 @@
  * array(
  *     stdClass object {
  *         't' => (string) 'Type' - The criteria type
- *                Values: Keys from self::searchFields() and 'flag'.
+ *                Values: Keys from self::searchFields(), 'flag', and 'or'.
  *         'v' => (mixed) 'Value' - The data used to build the search
  *                'header' - (string) The value to search for in the header
  *                'customhdr' - (stdClass object) Contains 2 elements:
@@ -677,6 +677,12 @@ class IMP_Search
                 ? $searchfields[$field]['type']
                 : $field;
 
+            if ($field == 'or') {
+                $text .= implode(' ' . _("and") . ' ', $text_array) . ' ' . _("OR") . ' ';
+                $text_array = array();
+                continue;
+            }
+
             switch ($searchfields[$field]['type']) {
             case 'flag':
                 if (isset($flagfields[$rule->v])) {
index 34adf34..489ed77 100644 (file)
@@ -28,6 +28,7 @@ class IMP_UI_Search
         $search_fields = $GLOBALS['imp_search']->searchFields();
         $flag_fields = $GLOBALS['imp_search']->flagFields();
         $imp_flags = IMP_Imap_Flags::singleton();
+        $or_search = false;
 
         foreach ($search as $rule) {
             $ob = new Horde_Imap_Client_Search_Query();
@@ -37,6 +38,12 @@ class IMP_UI_Search
                 : $rule->t;
 
             switch ($type) {
+            case 'or':
+                $query->orSearch($search_array);
+                $search_array = array();
+                $or_search = true;
+                break;
+
             case 'flag':
                 if (isset($flag_fields[$rule->v])) {
                     $val = $imp_flags->parseFormId($rule->t);
@@ -105,7 +112,11 @@ class IMP_UI_Search
             }
         }
 
-        $query->andSearch($search_array);
+        if ($or_search) {
+            $query->orSearch($search_array);
+        } else {
+            $query->andSearch($search_array);
+        }
 
         return $query;
     }
index 68fd343..765b1ef 100644 (file)
@@ -179,7 +179,7 @@ Horde_UI_JsCalendar::init();
 
 /* Gettext strings for this page. */
 $gettext_strings = array(
-    'and' => _("AND"),
+    'and' => _("and"),
     'customhdr' => _("Custom Header:"),
     'dateselection' => _("Date Selection"),
     'flag' => _("Flag:"),
@@ -188,6 +188,7 @@ $gettext_strings = array(
     'need_folder' => _("Please select at least one folder to search."),
     'need_label' => _("Saved searches require a label."),
     'not_match' => _("Do NOT Match"),
+    'or' => _("OR"),
     'search_term' => _("Search Term:")
 );
 
index bd7da23..409b652 100644 (file)
@@ -30,6 +30,8 @@
    <select id="search_criteria">
     <option value=""><gettext>Add search criteria:</gettext></option>
     <option value="" disabled="disabled">- - - - - - - - -</option>
+    <option value="or" style="display:none"><gettext>Add OR clause</gettext></option>
+    <option value="" disabled="disabled" style="display:none">- - - - - - - - -</option>
 <loop:s_fields>
     <option value="<tag:s_fields.val />"><tag:s_fields.label /></option>
 </loop:s_fields>