Bug 10860: DBRev 3.17.00.044
[koha.git] / C4 / Search / History.pm
1 package C4::Search::History;
2
3 use Modern::Perl;
4
5 use C4::Auth qw( get_session );
6 use C4::Context;
7 use Koha::DateUtils;
8
9 use JSON qw( encode_json decode_json );
10 use URI::Escape;
11 use Encode;
12
13 sub add {
14     my ($params)   = @_;
15     my $userid     = $params->{userid};
16     my $sessionid  = $params->{sessionid};
17     my $query_desc = $params->{query_desc};
18     my $query_cgi  = $params->{query_cgi};
19     my $total      = $params->{total} // 0;
20     my $type       = $params->{type} || 'biblio';
21
22     my $dbh = C4::Context->dbh;
23
24     # Add the request the user just made
25     my $query = q{
26         INSERT INTO search_history(
27             userid, sessionid, query_desc, query_cgi, type, total, time
28         ) VALUES(
29             ?, ?, ?, ?, ?, ?, NOW()
30         )
31     };
32     my $sth = $dbh->prepare($query);
33     $sth->execute( $userid, $sessionid, $query_desc, $query_cgi, $type,
34         $total );
35 }
36
37 sub add_to_session {
38     my ($params) = @_;
39     my $cgi = $params->{cgi};
40     my $query_desc = Encode::decode_utf8( $params->{query_desc} ) || "unknown";
41     my $query_cgi  = Encode::decode_utf8( $params->{query_cgi} )  || "unknown";
42     my $total      = $params->{total};
43     my $type       = $params->{type}                              || 'biblio';
44
45     my @recent_searches = get_from_session( { cgi => $cgi } );
46     push @recent_searches,
47       {
48         query_desc => $query_desc,
49         query_cgi  => $query_cgi,
50         total      => "$total",
51         type       => $type,
52         time       => output_pref( { dt => dt_from_string(), dateformat => 'iso', timeformat => '24hr' } ),
53       };
54
55     shift @recent_searches if ( @recent_searches > 15 );
56     set_to_session( { cgi => $cgi, search_history => \@recent_searches } );
57 }
58
59 sub delete {
60     my ($params)  = @_;
61     my $userid    = $params->{userid};
62     my $sessionid = $params->{sessionid};
63     my $type      = $params->{type}     || q{};
64     my $previous  = $params->{previous} || 0;
65
66     unless ($userid) {
67         warn "ERROR: userid is required for history search";
68         return;
69     }
70
71     my $dbh   = C4::Context->dbh;
72     my $query = q{
73         DELETE FROM search_history
74         WHERE userid = ?
75     };
76
77     if ($sessionid) {
78         $query .=
79           $previous
80           ? q{ AND sessionid != ?}
81           : q{ AND sessionid = ?};
82     }
83
84     $query .= q{ AND type = ?}
85       if $type;
86
87     $dbh->do(
88         $query, {}, $userid,
89         ( $sessionid ? $sessionid : () ),
90         ( $type      ? $type      : () )
91     );
92 }
93
94 sub get {
95     my ($params)  = @_;
96     my $userid    = $params->{userid};
97     my $sessionid = $params->{sessionid};
98     my $type      = $params->{type};
99     my $previous  = $params->{previous};
100
101     unless ($userid) {
102         warn "ERROR: userid is required for history search";
103         return;
104     }
105
106     my $query = q{
107         SELECT *
108         FROM search_history
109         WHERE userid = ?
110     };
111
112     if ($sessionid) {
113         $query .=
114           $previous
115           ? q{ AND sessionid != ?}
116           : q{ AND sessionid = ?};
117     }
118
119     $query .= q{ AND type = ?}
120       if $type;
121
122     my $dbh = C4::Context->dbh;
123     my $sth = $dbh->prepare($query);
124     $sth->execute(
125         $userid,
126         ( $sessionid ? $sessionid : () ),
127         ( $type      ? $type      : () )
128     );
129     return $sth->fetchall_arrayref( {} );
130 }
131
132 sub get_from_session {
133     my ($params)  = @_;
134     my $cgi       = $params->{cgi};
135     my $sessionID = $cgi->cookie('CGISESSID');
136     return () unless $sessionID;
137     my $session = C4::Auth::get_session($sessionID);
138     return () unless $session and $session->param('search_history');
139     my $obj =
140       eval { decode_json( uri_unescape( $session->param('search_history') ) ) };
141     return () unless defined $obj;
142     return () unless ref $obj eq 'ARRAY';
143     return @{$obj};
144 }
145
146 sub set_to_session {
147     my ($params)       = @_;
148     my $cgi            = $params->{cgi};
149     my $search_history = $params->{search_history};
150     my $sessionID      = $cgi->cookie('CGISESSID');
151     return () unless $sessionID;
152     my $session = C4::Auth::get_session($sessionID);
153     return () unless $session;
154     $session->param( 'search_history',
155         uri_escape( encode_json($search_history) ) );
156 }
157
158 1;
159
160 __END__
161
162 =pod
163
164 =head1 NAME
165
166 C4::Search::History - Manage search history
167
168 =head1 DESCRIPTION
169
170 This module provides some routines for the search history management.
171 It deals with session or database.
172
173 =head1 ROUTINES
174
175 =head2 add
176
177     C4::Search::History::add({
178         userid => $userid,
179         sessionid => $cgi->cookie("CGIESSID"),
180         query_desc => $query_desc,
181         query_cgi => $query_cgi,
182         total => $total,
183         type => $type,
184     });
185
186 type is "biblio" or "authority".
187
188 Add a new search to the user's history.
189
190 =head2 add_to_session
191
192     my $value = C4::Search::History::add_to_session({
193         cgi => $cgi,
194         query_desc => $query_desc,
195         query_cgi => $query_cgi,
196         total => $total,
197         type => $type,
198     });
199
200 Add a search to the session. The number of searches to keep is hardcoded to 15.
201
202 =head2 delete
203
204     C4::Search::History::delete({
205         userid => $loggedinuser,
206         sessionid => $sessionid,
207         type => $type,
208         previous => $previous
209     });
210
211 Delete searches in the database.
212 If the sessionid is missing all searches for all sessions will be deleted.
213 It is possible to delete searches for current session or all previous sessions using the previous flag.
214 If the type ("biblio" or "authority") is missing, all type will be deleted.
215 To delete *all* searches for a given userid, just pass a userid.
216
217 =head2 get
218
219     my $searches C4::Search::History::get({
220         userid => $userid,
221         sessionsid => $sessionid,
222         type => $type,
223         previous => $previous
224     });
225
226 Return a list of searches for a given userid.
227 If a sessionid is given, searches are limited to the matching session.
228 type and previous follow the same behavior as the delete routine.
229
230 =head2 get_from_session
231
232     my $searches = C4::Search::History::get_from_session({
233         cgi => $cgi
234     });
235
236 Return all searches present for the given session.
237
238 =head2 set_to_session
239
240     C4::Search::History::set_to_session({
241         cgi => $cgi,
242         search_history => $search_history
243     });
244
245 Store searches into the session.
246
247 =head1 AUTHORS
248
249 Jonathan Druart <jonathan.druart@biblibre.com>
250
251 =head1 LICENSE
252
253 This file is part of Koha.
254
255 Copyright 2013 BibLibre SARL
256
257 Koha is free software; you can redistribute it and/or modify it
258 under the terms of the GNU General Public License as published by
259 the Free Software Foundation; either version 3 of the License, or
260 (at your option) any later version.
261
262 Koha is distributed in the hope that it will be useful, but
263 WITHOUT ANY WARRANTY; without even the implied warranty of
264 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
265 GNU General Public License for more details.
266
267 You should have received a copy of the GNU General Public License
268 along with Koha; if not, see <http://www.gnu.org/licenses>.