TPAC: Search Filter Groups
authorBill Erickson <berick@esilibrary.com>
Thu, 23 Feb 2012 22:01:28 +0000 (17:01 -0500)
committerMike Rylander <mrylander@gmail.com>
Tue, 22 May 2012 19:04:58 +0000 (15:04 -0400)
Adds support for a new CGI param:

fg:<filter_group_code>=filter_group_entry

Each filter group entry will be mapped to a filter_group_entry()
filter and appended to the current search query.

This includes a new filter selector builder at
parts/filter_group_selector.tt2.

Usage, assuming a filter_group with code "audience":

<span>[% ctx.filter_groups.audience.label %]<span>
<span>
[%
    INCLUDE 'opac/parts/filter_group_selector.tt2'
    filter_group=audience
    none_ok=1
%]
<span>

The set of filter groups available to the TPAC are those defined at the
search org unit and its ancestors.  If multiple filters have the same
code name, the filter owned closest to the context org unit is used.
This allows for global filters with local overrides.

Signed-off-by: Bill Erickson <berick@esilibrary.com>
Signed-off-by: Mike Rylander <mrylander@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Util.pm
Open-ILS/src/templates/opac/parts/filter_group_selector.tt2 [new file with mode: 0644]

index 7791cf8..63f919a 100644 (file)
@@ -270,6 +270,7 @@ sub load_common {
     $self->load_eg_cache_hash;
     $self->load_copy_location_groups;
     $self->staff_saved_searches_set_expansion_state if $ctx->{is_staff};
+    $self->load_search_filter_groups($ctx->{search_ou});
 
     return Apache2::Const::OK;
 }
index 1bf8b61..e4e23e5 100644 (file)
@@ -65,6 +65,15 @@ sub _prepare_biblio_search {
         $query .= " $1($term)" if length $term;
     }
 
+    # filter group entries.  Entries from like filters are grouped into a single 
+    # filter_group_entry() filter (ORed).  Each collection is ANDed together.
+    # fg:foo_group=foo_entry_id
+    foreach (grep /^fg:/, $cgi->param) {
+        /:(-?\w+)$/ or next;
+        my $term = join(",", $cgi->param($_));
+        $query .= " filter_group_entry($term)" if length $term;
+    }
+
     if ($cgi->param("bookbag")) {
         $query .= " container(bre,bookbag," . int($cgi->param("bookbag")) . ")";
     }
index d973947..db660fe 100644 (file)
@@ -15,7 +15,8 @@ our %cache = ( # cached data
     list => {},
     search => {},
     org_settings => {},
-    eg_cache_hash => undef
+    eg_cache_hash => undef,
+    search_filter_groups => {}
 );
 
 sub init_ro_object_cache {
@@ -513,4 +514,35 @@ sub apache_log_if_event {
     return;
 }
 
+sub load_search_filter_groups {
+    my $self = shift;
+    my $ctx_org = shift;
+    my $org_list = $U->get_org_ancestors($ctx_org, 1);
+
+    my %seen;
+    for my $org_id (@$org_list) {
+
+        my $grps;
+        if (!$cache{search_filter_groups}{$org_id}) {
+            $grps = $self->editor->search_actor_search_filter_group([
+                {owner => $org_id},
+                {   flesh => 2, 
+                    flesh_fields => {
+                        asfg => ['entries'],
+                        asfge => ['query']
+                    }
+                }
+            ]);
+            $cache{search_filter_groups}{$org_id} = $grps;
+        }
+            
+        # for the current context, if a descendant org has a group 
+        # with a matching code replace the group from the parent.
+        $seen{$_->code} = $_ for @$grps;
+    }
+
+    return $self->ctx->{search_filter_groups} = \%seen;
+}
+
+
 1;
diff --git a/Open-ILS/src/templates/opac/parts/filter_group_selector.tt2 b/Open-ILS/src/templates/opac/parts/filter_group_selector.tt2
new file mode 100644 (file)
index 0000000..3b8f730
--- /dev/null
@@ -0,0 +1,31 @@
+[%- 
+    # If caller passes a list of possible filter_groups
+    # search all until we find some values
+    IF !filter_group.size; filter_group = [filter_group]; END;
+    group = '';
+    FOR code IN filter_group;
+        group = ctx.search_filter_groups.$code;
+        LAST IF group AND group.entries.size;
+    END;
+    name = name || "fg:" _ group.code;
+    id = id || group.code _ "_selector";
+    values = values || CGI.param(name); 
+-%]
+
+<select id='[% id %]' name='[% name %]'[%
+    multiple ? ' multiple="multiple"' : '';
+    size ? (' size="' _ size _ '"') : ''; %]>
+[% IF none_ok %]
+    <option value=''>[% none_label ? none_label : l('-- Any --') %]</option>
+[% END;
+# turn the list of objects into a list of hashes to 
+# leverage TT's array.sort('<hashkey>') behavior
+sorter = [];
+FOR o IN group.entries;
+    sorter.push({id => o.id, label => o.query.label}); 
+END;
+FOR o IN sorter.sort('label') %]
+    <option value='[% o.id %]'[% values.grep(o.id).size ? ' selected="selected"' : '' %]>[% o.label | html %]</option>
+[%  END -%]
+</select>
+