1 package C4::Search::History;
5 use C4::Auth qw( get_session );
7 use Koha::DateUtils qw( dt_from_string output_pref );
9 use JSON qw( decode_json encode_json );
10 use URI::Escape qw( uri_escape uri_unescape );
14 my $userid = $params->{userid};
15 my $sessionid = $params->{sessionid};
16 my $query_desc = $params->{query_desc};
17 my $query_cgi = $params->{query_cgi};
18 my $total = $params->{total} // 0;
19 my $type = $params->{type} || 'biblio';
20 my $time = $params->{time};
22 my $dbh = C4::Context->dbh;
24 # Add the request the user just made
26 INSERT INTO search_history(
27 userid, sessionid, query_desc, query_cgi, type, total} . ( $time ? ', time' : '' ) . q{
29 ?, ?, ?, ?, ?, ?} . ( $time ? ', ?' : '' ) . q{
32 my $sth = $dbh->prepare($query);
33 $sth->execute( $userid, $sessionid, $query_desc, $query_cgi, $type,
34 $total, ( $time ? $time : () ) );
39 my $cgi = $params->{cgi};
40 my $query_desc = $params->{query_desc} || "unknown";
41 my $query_cgi = $params->{query_cgi} || "unknown";
42 my $total = $params->{total};
43 my $type = $params->{type} || 'biblio';
45 # To a cookie (the user is not logged in)
46 my $now = dt_from_string;
47 my $id = $now->year . $now->month . $now->day . $now->hour . $now->minute . $now->second . int(rand(100));
48 my @recent_searches = get_from_session( { cgi => $cgi } );
49 push @recent_searches, {
50 query_desc => $query_desc,
51 query_cgi => $query_cgi,
54 # FIXME We shouldn't store the formatted date
55 time => output_pref( { dt => $now, dateformat => 'iso', timeformat => '24hr' } ),
59 shift @recent_searches if ( @recent_searches > 15 );
60 set_to_session( { cgi => $cgi, search_history => \@recent_searches } );
65 my $id = $params->{id};
66 my $userid = $params->{userid};
67 my $sessionid = $params->{sessionid};
68 my $type = $params->{type} || q{};
69 my $previous = $params->{previous} || 0;
70 my $interval = $params->{interval} || 0;
72 unless ( ref( $id ) ) {
73 $id = $id ? [ $id ] : [];
76 unless ( $userid or @$id or $interval ) {
77 warn "ERROR: userid, id or interval is required for history deletion";
81 my $dbh = C4::Context->dbh;
83 DELETE FROM search_history
87 $query .= q{ AND id IN ( } . join( q{,}, (q{?}) x @$id ) . q{ )}
97 ? q{ AND sessionid != ?}
98 : q{ AND sessionid = ?};
101 $query .= q{ AND type = ?}
104 # FIXME DATE_SUB is a Mysql-ism. Postgres uses: datefield - INTERVAL '6 months'
105 $query .= q{ AND time < DATE_SUB( NOW(), INTERVAL ? DAY )}
110 ( @$id ? ( @$id ) : () ),
111 ( $userid ? $userid : () ),
112 ( $sessionid ? $sessionid : () ),
113 ( $type ? $type : () ),
114 ( $interval ? $interval : () ),
118 sub delete_from_cookie {
120 my $cookie = $params->{cookie};
121 my $id = $params->{id};
123 return unless $cookie;
125 unless ( ref( $id ) ) {
126 $id = $id ? [ $id ] : [];
132 $cookie = uri_unescape( $cookie );
133 if (decode_json( $cookie )) {
134 @searches = @{decode_json( $cookie )}
140 ( grep { $_ != $search->{id} } @$id ) ? $search : ()
143 return uri_escape( encode_json( \@searches ) );
149 my $id = $params->{id};
150 my $userid = $params->{userid};
151 my $sessionid = $params->{sessionid};
152 my $type = $params->{type};
153 my $previous = $params->{previous};
155 unless ( ref( $id ) ) {
156 $id = $id ? [ $id ] : [];
159 unless ( $userid or @$id ) {
160 warn "ERROR: userid is required for history search";
170 $query .= q{ AND id IN ( } . join( q{,}, (q{?}) x @$id ) . q{ )}
180 ? q{ AND sessionid != ?}
181 : q{ AND sessionid = ?};
184 $query .= q{ AND type = ?}
187 my $dbh = C4::Context->dbh;
188 my $sth = $dbh->prepare($query);
190 ( @$id ? ( @$id ) : () ),
191 ( $userid ? $userid : () ),
192 ( $sessionid ? $sessionid : () ),
193 ( $type ? $type : () )
195 return $sth->fetchall_arrayref( {} );
198 sub get_from_session {
200 my $cgi = $params->{cgi};
201 my $sessionID = $cgi->cookie('CGISESSID');
202 return () unless $sessionID;
203 my $session = C4::Auth::get_session($sessionID);
204 return () unless $session and $session->param('search_history');
206 eval { decode_json( uri_unescape( $session->param('search_history') ) ) };
207 return () unless defined $obj;
208 return () unless ref $obj eq 'ARRAY';
214 my $cgi = $params->{cgi};
215 my $search_history = $params->{search_history};
216 my $sessionID = $cgi->cookie('CGISESSID');
217 return () unless $sessionID;
218 my $session = C4::Auth::get_session($sessionID);
219 return () unless $session;
220 $session->param( 'search_history',
221 uri_escape( encode_json($search_history) ) );
233 C4::Search::History - Manage search history
237 This module provides some routines for the search history management.
238 It deals with session or database.
244 C4::Search::History::add({
246 sessionid => $cgi->cookie("CGIESSID"),
247 query_desc => $query_desc,
248 query_cgi => $query_cgi,
253 type is "biblio" or "authority".
255 Add a new search to the user's history.
257 =head2 add_to_session
259 my $value = C4::Search::History::add_to_session({
261 query_desc => $query_desc,
262 query_cgi => $query_cgi,
267 Add a search to the session. The number of searches to keep is hardcoded to 15.
271 C4::Search::History::delete({
272 userid => $loggedinuser,
273 sessionid => $sessionid,
275 previous => $previous
278 Delete searches in the database.
279 If the sessionid is missing all searches for all sessions will be deleted.
280 It is possible to delete searches for current session or all previous sessions using the previous flag.
281 If the type ("biblio" or "authority") is missing, all type will be deleted.
282 To delete *all* searches for a given userid, just pass a userid.
286 my $searches C4::Search::History::get({
288 sessionsid => $sessionid,
290 previous => $previous
293 Return a list of searches for a given userid.
294 If a sessionid is given, searches are limited to the matching session.
295 type and previous follow the same behavior as the delete routine.
297 =head2 get_from_session
299 my $searches = C4::Search::History::get_from_session({
303 Return all searches present for the given session.
305 =head2 set_to_session
307 C4::Search::History::set_to_session({
309 search_history => $search_history
312 Store searches into the session.
316 Jonathan Druart <jonathan.druart@biblibre.com>
320 This file is part of Koha.
322 Copyright 2013 BibLibre SARL
324 Koha is free software; you can redistribute it and/or modify it
325 under the terms of the GNU General Public License as published by
326 the Free Software Foundation; either version 3 of the License, or
327 (at your option) any later version.
329 Koha is distributed in the hope that it will be useful, but
330 WITHOUT ANY WARRANTY; without even the implied warranty of
331 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
332 GNU General Public License for more details.
334 You should have received a copy of the GNU General Public License
335 along with Koha; if not, see <http://www.gnu.org/licenses>.