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 time => output_pref( { dt => $now, dateformat => 'iso', timeformat => '24hr' } ),
58 shift @recent_searches if ( @recent_searches > 15 );
59 set_to_session( { cgi => $cgi, search_history => \@recent_searches } );
64 my $id = $params->{id};
65 my $userid = $params->{userid};
66 my $sessionid = $params->{sessionid};
67 my $type = $params->{type} || q{};
68 my $previous = $params->{previous} || 0;
69 my $interval = $params->{interval} || 0;
71 unless ( ref( $id ) ) {
72 $id = $id ? [ $id ] : [];
75 unless ( $userid or @$id or $interval ) {
76 warn "ERROR: userid, id or interval is required for history deletion";
80 my $dbh = C4::Context->dbh;
82 DELETE FROM search_history
86 $query .= q{ AND id IN ( } . join( q{,}, (q{?}) x @$id ) . q{ )}
96 ? q{ AND sessionid != ?}
97 : q{ AND sessionid = ?};
100 $query .= q{ AND type = ?}
103 # FIXME DATE_SUB is a Mysql-ism. Postgres uses: datefield - INTERVAL '6 months'
104 $query .= q{ AND time < DATE_SUB( NOW(), INTERVAL ? DAY )}
109 ( @$id ? ( @$id ) : () ),
110 ( $userid ? $userid : () ),
111 ( $sessionid ? $sessionid : () ),
112 ( $type ? $type : () ),
113 ( $interval ? $interval : () ),
117 sub delete_from_cookie {
119 my $cookie = $params->{cookie};
120 my $id = $params->{id};
122 return unless $cookie;
124 unless ( ref( $id ) ) {
125 $id = $id ? [ $id ] : [];
131 $cookie = uri_unescape( $cookie );
132 if (decode_json( $cookie )) {
133 @searches = @{decode_json( $cookie )}
139 ( grep { $_ != $search->{id} } @$id ) ? $search : ()
142 return uri_escape( encode_json( \@searches ) );
148 my $id = $params->{id};
149 my $userid = $params->{userid};
150 my $sessionid = $params->{sessionid};
151 my $type = $params->{type};
152 my $previous = $params->{previous};
154 unless ( ref( $id ) ) {
155 $id = $id ? [ $id ] : [];
158 unless ( $userid or @$id ) {
159 warn "ERROR: userid is required for history search";
169 $query .= q{ AND id IN ( } . join( q{,}, (q{?}) x @$id ) . q{ )}
179 ? q{ AND sessionid != ?}
180 : q{ AND sessionid = ?};
183 $query .= q{ AND type = ?}
186 my $dbh = C4::Context->dbh;
187 my $sth = $dbh->prepare($query);
189 ( @$id ? ( @$id ) : () ),
190 ( $userid ? $userid : () ),
191 ( $sessionid ? $sessionid : () ),
192 ( $type ? $type : () )
194 return $sth->fetchall_arrayref( {} );
197 sub get_from_session {
199 my $cgi = $params->{cgi};
200 my $sessionID = $cgi->cookie('CGISESSID');
201 return () unless $sessionID;
202 my $session = C4::Auth::get_session($sessionID);
203 return () unless $session and $session->param('search_history');
205 eval { decode_json( uri_unescape( $session->param('search_history') ) ) };
206 return () unless defined $obj;
207 return () unless ref $obj eq 'ARRAY';
213 my $cgi = $params->{cgi};
214 my $search_history = $params->{search_history};
215 my $sessionID = $cgi->cookie('CGISESSID');
216 return () unless $sessionID;
217 my $session = C4::Auth::get_session($sessionID);
218 return () unless $session;
219 $session->param( 'search_history',
220 uri_escape( encode_json($search_history) ) );
232 C4::Search::History - Manage search history
236 This module provides some routines for the search history management.
237 It deals with session or database.
243 C4::Search::History::add({
245 sessionid => $cgi->cookie("CGIESSID"),
246 query_desc => $query_desc,
247 query_cgi => $query_cgi,
252 type is "biblio" or "authority".
254 Add a new search to the user's history.
256 =head2 add_to_session
258 my $value = C4::Search::History::add_to_session({
260 query_desc => $query_desc,
261 query_cgi => $query_cgi,
266 Add a search to the session. The number of searches to keep is hardcoded to 15.
270 C4::Search::History::delete({
271 userid => $loggedinuser,
272 sessionid => $sessionid,
274 previous => $previous
277 Delete searches in the database.
278 If the sessionid is missing all searches for all sessions will be deleted.
279 It is possible to delete searches for current session or all previous sessions using the previous flag.
280 If the type ("biblio" or "authority") is missing, all type will be deleted.
281 To delete *all* searches for a given userid, just pass a userid.
285 my $searches C4::Search::History::get({
287 sessionsid => $sessionid,
289 previous => $previous
292 Return a list of searches for a given userid.
293 If a sessionid is given, searches are limited to the matching session.
294 type and previous follow the same behavior as the delete routine.
296 =head2 get_from_session
298 my $searches = C4::Search::History::get_from_session({
302 Return all searches present for the given session.
304 =head2 set_to_session
306 C4::Search::History::set_to_session({
308 search_history => $search_history
311 Store searches into the session.
315 Jonathan Druart <jonathan.druart@biblibre.com>
319 This file is part of Koha.
321 Copyright 2013 BibLibre SARL
323 Koha is free software; you can redistribute it and/or modify it
324 under the terms of the GNU General Public License as published by
325 the Free Software Foundation; either version 3 of the License, or
326 (at your option) any later version.
328 Koha is distributed in the hope that it will be useful, but
329 WITHOUT ANY WARRANTY; without even the implied warranty of
330 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
331 GNU General Public License for more details.
333 You should have received a copy of the GNU General Public License
334 along with Koha; if not, see <http://www.gnu.org/licenses>.