Support for boolean operators in advanced search
authorBill Erickson <berick@esilibrary.com>
Mon, 1 Aug 2011 21:34:35 +0000 (17:34 -0400)
committerBill Erickson <berick@esilibrary.com>
Tue, 2 Aug 2011 13:14:53 +0000 (09:14 -0400)
Implements a new column with And/Or selectors.  Terms are grouped from
top to bottom in the UI as left to right in the compiled query.

A && B || C && D  => ((A && B) || C) && D

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
Open-ILS/web/templates/default/opac/parts/advanced/global_row.tt2

index 6397d84..62ad13c 100644 (file)
@@ -17,12 +17,13 @@ sub _prepare_biblio_search_basics {
     return $cgi->param('query') unless $cgi->param('qtype');
 
     my %parts;
-    my @part_names = qw/qtype contains query/;
+    my @part_names = qw/qtype contains query bool/;
     $parts{$_} = [ $cgi->param($_) ] for (@part_names);
 
+    my $full_query = '';
     my @chunks = ();
     for (my $i = 0; $i < scalar @{$parts{'qtype'}}; $i++) {
-        my ($qtype, $contains, $query) = map { $parts{$_}->[$i] } @part_names;
+        my ($qtype, $contains, $query, $bool) = map { $parts{$_}->[$i] } @part_names;
 
         next unless $query =~ /\S/;
         push(@chunks, $qtype . ':') unless $qtype eq 'keyword' and $i == 0;
@@ -41,10 +42,13 @@ sub _prepare_biblio_search_basics {
             $query =~ s/[\^\$]//g;
             $query = '^' . $query . '$';
         }
+
+        $bool = ($bool and $bool eq 'or') ? '||' : '&&';
+        $full_query = $full_query ? "($full_query $bool $query)" : $query;
         push @chunks, $query;
     }
 
-    return join(' ', @chunks);
+    return $full_query;
 }
 
 sub _prepare_biblio_search {
index f2fbbe6..3e5dec5 100644 (file)
@@ -7,21 +7,33 @@
     ];
     contains = CGI.param('contains');
     queries = CGI.param('query');
+    bools = CGI.param('bool') || ['and' x 3];
     qtypes = CGI.param('qtype') || ['keyword' x 3];
     FOR qtype IN qtypes;
         c = contains.shift;
+        b = bools.shift;
         q = queries.shift; %]
-<tr[% IF loop.first %] id="adv_global_row"[% END %]>
+
+<!-- tag the second row so the bool column won't be hidden -->
+<tr[% IF loop.index == 1 %] id="adv_global_row"[% END %]>
     <td align='left' width='100%' nowrap='nowrap'>
+
+        <!-- bool selector.  hide for first row.  safe to ignore first bool value in form submission -->
+        <select name='bool' [% IF loop.first %] class='invisible' [% END %]>
+            <option value='and' [% b == 'and' ? 'selected="selected"' : '' %]>[% l('And') %]</option>
+            <option value='or' [% b == 'or' ? 'selected="selected"' : '' %]>[% l('Or') %]</option>
+        </select>
+
+        <!-- keyword, subject, etc. selector -->
         <span class="opac-auto-078">
             [% INCLUDE "default/opac/parts/qtype_selector.tt2"
                 query_type=qtype %]
         </span>
+
         <select name='contains' style='margin-right: 7px;'>
-            [% FOR o IN contains_options;
-                |l(o.value, o.label) -%]
-            <option value="[_1]"[% c == o.value ? ' selected="selected"' : '' %]>[_2]</option>
-            [% END; END %]
+            [% FOR o IN contains_options; -%]
+            <option value="[% o.value %]" [% c == o.value ? ' selected="selected"' : '' %]>[% o.label %]</option>
+            [% END %]
         </select>
         <input type='text' size='18' name='query' value="[% q | html %]" />
         <a href="javascript:;" class="row-remover"