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) ) );
231 C4::Search::History - Manage search history
235 This module provides some routines for the search history management.
236 It deals with session or database.
242 C4::Search::History::add({
244 sessionid => $cgi->cookie("CGIESSID"),
245 query_desc => $query_desc,
246 query_cgi => $query_cgi,
251 type is "biblio" or "authority".
253 Add a new search to the user's history.
255 =head2 add_to_session
257 my $value = C4::Search::History::add_to_session({
259 query_desc => $query_desc,
260 query_cgi => $query_cgi,
265 Add a search to the session. The number of searches to keep is hardcoded to 15.
269 C4::Search::History::delete({
270 userid => $loggedinuser,
271 sessionid => $sessionid,
273 previous => $previous
276 Delete searches in the database.
277 If the sessionid is missing all searches for all sessions will be deleted.
278 It is possible to delete searches for current session or all previous sessions using the previous flag.
279 If the type ("biblio" or "authority") is missing, all type will be deleted.
280 To delete *all* searches for a given userid, just pass a userid.
284 my $searches C4::Search::History::get({
286 sessionsid => $sessionid,
288 previous => $previous
291 Return a list of searches for a given userid.
292 If a sessionid is given, searches are limited to the matching session.
293 type and previous follow the same behavior as the delete routine.
295 =head2 get_from_session
297 my $searches = C4::Search::History::get_from_session({
301 Return all searches present for the given session.
303 =head2 set_to_session
305 C4::Search::History::set_to_session({
307 search_history => $search_history
310 Store searches into the session.
314 Jonathan Druart <jonathan.druart@biblibre.com>
318 This file is part of Koha.
320 Copyright 2013 BibLibre SARL
322 Koha is free software; you can redistribute it and/or modify it
323 under the terms of the GNU General Public License as published by
324 the Free Software Foundation; either version 3 of the License, or
325 (at your option) any later version.
327 Koha is distributed in the hope that it will be useful, but
328 WITHOUT ANY WARRANTY; without even the implied warranty of
329 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
330 GNU General Public License for more details.
332 You should have received a copy of the GNU General Public License
333 along with Koha; if not, see <http://www.gnu.org/licenses>.