]> git.evergreen-ils.org Git - working/Evergreen.git/blob - Open-ILS/src/perlmods/lib/OpenILS/WWW/EGCatLoader/Search.pm
big ol' commit making advanced search work, albeit with issues
[working/Evergreen.git] / Open-ILS / src / perlmods / lib / OpenILS / WWW / EGCatLoader / Search.pm
1 package OpenILS::WWW::EGCatLoader;
2 use strict; use warnings;
3 use Apache2::Const -compile => qw(OK DECLINED FORBIDDEN HTTP_INTERNAL_SERVER_ERROR REDIRECT HTTP_BAD_REQUEST);
4 use OpenSRF::Utils::Logger qw/$logger/;
5 use OpenILS::Utils::CStoreEditor qw/:funcs/;
6 use OpenILS::Utils::Fieldmapper;
7 use OpenILS::Application::AppUtils;
8 my $U = 'OpenILS::Application::AppUtils';
9
10
11 sub _prepare_biblio_search_basics {
12     my ($cgi) = @_;
13
14     my %parts;
15     my @part_names = qw/class contains query/;
16     $parts{$_} = [ $cgi->param($_) ] for (@part_names);
17
18     my @chunks = ();
19     for (my $i = 0; $i < scalar @{$parts{'class'}}; $i++) {
20         my ($class, $contains, $query) = map { $parts{$_}->[$i] } @part_names;
21
22         push(@chunks, $class . ':') unless $class eq 'keyword' and $i == 0;
23
24         # This stuff probably will need refined or rethought to better handle
25         # the weird things Real Users will surely type in.
26         if ($contains eq 'nocontains') {
27             $query =~ s/"//g;
28             $query = ('"' . $query . '"') if index $query, ' ';
29             $query = '-' . $query;
30         } elsif ($contains eq 'exact') {
31             $query =~ s/"//g;
32             $query = ('"' . $query . '"') if index $query, ' ';
33         }
34         push @chunks, $query;
35     }
36
37     return join(' ', @chunks);
38 }
39
40 sub _prepare_biblio_search {
41     my ($cgi, $ctx) = @_;
42
43     my $query = _prepare_biblio_search_basics($cgi);
44     my $args = {};
45
46     $args->{'org_unit'} = $cgi->param('loc') || $ctx->{aou_tree}->()->id;
47     $args->{'depth'} = defined $cgi->param('depth') ?
48         $cgi->param('depth') :
49         $ctx->{find_aou}->($args->{'org_unit'})->ou_type->depth;
50
51     if ($cgi->param('available')) {
52         $query = '#available ' . $query;
53     }
54
55     if ($cgi->param('format')) {
56         $args->{'format'} = join('', $cgi->param('format'));
57     }
58
59     if ($cgi->param('lang')) {
60         # XXX TODO find out how to build query with multiple langs, if that
61         # even needs to be a feature of adv search.
62         $query .= ' lang:' . $cgi->param('lang');
63     }
64
65     if ($cgi->param('audience')) {
66         $query .= ' audience(' . $cgi->param('audience') . ')';
67     }
68
69     if (defined $cgi->param('sort')) {
70         my $sort = $cgi->param('sort');
71         my $sort_order = $cgi->param('sort_order');
72         $query .= " sort($sort)";
73         $query .= '#' . $sort_order if $sort_order and $sort ne 'rel';
74     }
75
76     if ($cgi->param('pubyear_how') && $cgi->param('pubyear1')) {
77         if ($cgi->param('pubyear_how') eq 'between') {
78             $query .= ' between(' . $cgi->param('pubyear1');
79             $query .= ',' .  $cgi->param('pubyear2') if $cgi->param('pubyear2');
80             $query .= ')';
81         } else {
82             $query .= ' ' . $cgi->param('pubyear_how') .
83                 '(' . $cgi->param('pubyear1') . ')';
84         }
85     }
86
87     return ($args, $query);
88 }
89
90 # context additions: 
91 #   page_size
92 #   hit_count
93 #   records : list of bre's and copy-count objects
94 sub load_rresults {
95     my $self = shift;
96     my $cgi = $self->cgi;
97     my $ctx = $self->ctx;
98     my $e = $self->editor;
99
100     $ctx->{page} = 'rresult';
101     my $page = $cgi->param('page') || 0;
102     my $facet = $cgi->param('facet');
103     my $limit = $cgi->param('limit') || 10; # TODO user settings
104
105     my ($args, $query) = _prepare_biblio_search($cgi, $ctx);
106
107     # Stuff these into the TT context so that templates can use them in redrawing forms
108     $ctx->{processed_search_query} = $query;
109     $ctx->{processed_search_args} = $args;
110
111     $args->{'limit'} = $limit;
112     $args->{'offset'} = $page * $limit;
113
114     $query = "$query $facet" if $facet; # TODO
115
116     my $results;
117
118     try {
119
120         my $method = 'open-ils.search.biblio.multiclass.query';
121         $method .= '.staff' if $ctx->{is_staff};
122         $results = $U->simplereq('open-ils.search', $method, $args, $query, 1);
123
124     } catch Error with {
125         my $err = shift;
126         $logger->error("multiclass search error: $err");
127         $results = {count => 0, ids => []};
128     };
129
130     my $rec_ids = [map { $_->[0] } @{$results->{ids}}];
131
132     $ctx->{records} = [];
133     $ctx->{search_facets} = {};
134     $ctx->{page_size} = $limit;
135     $ctx->{hit_count} = $results->{count};
136
137     return Apache2::Const::OK if @$rec_ids == 0;
138
139     my $cstore1 = OpenSRF::AppSession->create('open-ils.cstore');
140     my $bre_req = $cstore1->request(
141         'open-ils.cstore.direct.biblio.record_entry.search', {id => $rec_ids});
142
143     my $search = OpenSRF::AppSession->create('open-ils.search');
144     my $facet_req = $search->request('open-ils.search.facet_cache.retrieve', $results->{facet_key}, 10);
145
146     my @data;
147     while(my $resp = $bre_req->recv) {
148         my $bre = $resp->content; 
149
150         # XXX farm out to multiple cstore sessions before loop, then collect after
151         my $copy_counts = $e->json_query(
152             {from => ['asset.record_copy_count', 1, $bre->id, 0]})->[0];
153
154         push(@data,
155             {
156                 bre => $bre,
157                 marc_xml => XML::LibXML->new->parse_string($bre->marc),
158                 copy_counts => $copy_counts
159             }
160         );
161     }
162
163     $cstore1->kill_me;
164
165     # shove recs into context in search results order
166     for my $rec_id (@$rec_ids) { 
167         push(
168             @{$ctx->{records}},
169             grep { $_->{bre}->id == $rec_id } @data
170         );
171     }
172
173     my $facets = $facet_req->gather(1);
174
175     $facets->{$_} = {cmf => $ctx->{find_cmf}->($_), data => $facets->{$_}} for keys %$facets;  # quick-n-dirty
176     $ctx->{search_facets} = $facets;
177
178     return Apache2::Const::OK;
179 }
180
181 1;