Enables ppl to store their search history and delete the whole history Adding Storable required by Opac-Search-History --- C4/Auth.pm | 65 +++++++++ C4/Search.pm | 22 +++ Makefile.PL | 1 + .../mysql/atomicupdate/0007-Opac-search-history.pl | 24 +++ koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc | 4 +- .../prog/en/modules/opac-search-history.tmpl | 80 +++++++++++ opac/opac-search-history.pl | 147 ++++++++++++++++++++ opac/opac-search.pl | 53 +++++++- 8 files changed, 392 insertions(+), 4 deletions(-) create mode 100644 installer/data/mysql/atomicupdate/0007-Opac-search-history.pl create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-search-history.tmpl create mode 100755 opac/opac-search-history.pl
diff --git a/C4/Auth.pm b/C4/Auth.pm index 871c124..04e0b35 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -19,6 +19,8 @@ package C4::Auth; use strict; use Digest::MD5 qw(md5_base64); +use Storable qw(thaw freeze); +use URI::Escape; use CGI::Session; require Exporter; @@ -225,6 +227,58 @@ sub get_template_and_user { } } } + # Logged-in opac search history + # If the requested template is an opac one and opac search history is enabled + if ($in->{'type'} == "opac" && C4::Context->preference('EnableOpacSearchHistory')) { + my $dbh = C4::Context->dbh; + my $query = "SELECT COUNT(*) FROM search_history WHERE userid=?"; + my $sth = $dbh->prepare($query); + $sth->execute($borrowernumber); + + # If at least one search has already been performed + if ($sth->fetchrow_array > 0) { + # We show the link in opac + $template->param(ShowOpacRecentSearchLink => 1); + } + + # And if there's a cookie with searches performed when the user was not logged in, + # we add them to the logged-in search history + my @recentSearches; + my $searchcookie = $in->{'query'}->cookie('KohaOpacRecentSearches'); + if ($searchcookie){ + $searchcookie = uri_unescape($searchcookie); + if (thaw($searchcookie)) { + @recentSearches = @{thaw($searchcookie)}; + } + + if (@recentSearches > 0) { + my $query = "INSERT INTO search_history(userid, sessionid, query_desc, query_cgi, total, time) VALUES"; + my $icount = 1; + foreach my $asearch (@recentSearches) { + $query .= "("; + $query .= $borrowernumber . ", "; + $query .= '"' . $in->{'query'}->cookie("CGISESSID") . "\", "; + $query .= '"' . $asearch->{'query_desc'} . "\", "; + $query .= '"' . $asearch->{'query_cgi'} . "\", "; + $query .= $asearch->{'total'} . ", "; + $query .= 'FROM_UNIXTIME(' . $asearch->{'time'} . "))"; + if ($icount < @recentSearches) { $query .= ", ";} + $icount++; + } + + my $sth = $dbh->prepare($query); + $sth->execute; + + # And then, delete the cookie's content + my $newsearchcookie = $in->{'query'}->cookie( + -name => 'KohaOpacRecentSearches', + -value => freeze([]), + -expires => '' + ); + $cookie = [$cookie, $newsearchcookie]; + } + } + } } else { # if this is an anonymous session, setup to display public lists... @@ -250,6 +304,17 @@ sub get_template_and_user { } } + # Anonymous opac search history + # If opac search history is enabled and at least one search has already been performed + if (C4::Context->preference('EnableOpacSearchHistory') && $in->{'query'}->cookie('KohaOpacRecentSearches')) { + # We show the link in opac + if (thaw(uri_unescape($in->{'query'}->cookie('KohaOpacRecentSearches')))) { + my @recentSearches = @{thaw(uri_unescape($in->{'query'}->cookie('KohaOpacRecentSearches')))}; + if (@recentSearches > 0) { + $template->param(ShowOpacRecentSearchLink => 1); + } + } + } # these template parameters are set the same regardless of $in->{'type'} $template->param( diff --git a/C4/Search.pm b/C4/Search.pm index f72bb11..b6bec0f 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -61,6 +61,7 @@ This module provides searching functions for Koha's bibliographic databases &getRecords &buildQuery &NZgetRecords + &AddSearchHistory ); # make all your functions, whether exported or not; @@ -2051,6 +2052,27 @@ sub enabled_staff_search_views ); } +sub AddSearchHistory{ + my ($borrowernumber,$session,$query_desc,$query_cgi, $total)=...@_; + my $dbh = C4::Context->dbh; + + # Add the request the user just made + my $sql = "INSERT INTO search_history(userid, sessionid, query_desc, query_cgi, total, time) VALUES(?, ?, ?, ?, ?, NOW())"; + my $sth = $dbh->prepare($sql); + $sth->execute($borrowernumber, $session, $query_desc, $query_cgi, $total); + return $dbh->last_insert_id(undef, 'search_history', undef,undef,undef); +} + +sub GetSearchHistory{ + my ($borrowernumber,$session)=...@_; + my $dbh = C4::Context->dbh; + + # Add the request the user just made + my $query = "SELECT FROM search_history WHERE (userid=? OR sessionid=?)"; + my $sth = $dbh->prepare($query); + $sth->execute($borrowernumber, $session); + return $sth->fetchall_hashref({}); +} =head2 z3950_search_args diff --git a/Makefile.PL b/Makefile.PL index a3775f0..635683a 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -588,6 +588,7 @@ WriteMakefile( 'POE' => 0.9999, 'POSIX' => 1.09, 'Schedule::At' => 1.06, + 'Storable' => 2.21, 'SMS::Send' => 0.05, # optional 'Term::ANSIColor' => 1.10, 'Test' => 1.25, diff --git a/installer/data/mysql/atomicupdate/0007-Opac-search-history.pl b/installer/data/mysql/atomicupdate/0007-Opac-search-history.pl new file mode 100644 index 0000000..db902a9 --- /dev/null +++ b/installer/data/mysql/atomicupdate/0007-Opac-search-history.pl @@ -0,0 +1,24 @@ +#! /usr/bin/perl +use strict; +use warnings; +use C4::Context; +my $dbh=C4::Context->dbh; + +$dbh->do("INSERT INTO `systempreferences` (`variable`, `value`, `options`, `explanation`, `type`) VALUES ('EnableOpacSearchHistory', '1', '', 'Enable or disable opac search history', 'YesNo')"); + +my $create = << END; +CREATE TABLE IF NOT EXISTS `search_history` ( + `userid` int(11) NOT NULL, + `sessionid` varchar(32) NOT NULL, + `query_desc` varchar(255) NOT NULL, + `query_cgi` varchar(255) NOT NULL, + `total` int(11) NOT NULL, + `time` timestamp NOT NULL default CURRENT_TIMESTAMP, + KEY `userid` (`userid`), + KEY `sessionid` (`sessionid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Opac search history results'; +END + +$dbh->do($create); + +print "Upgrade done (added OPAC search history preference and table)\n"; diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc b/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc index afe34d3..0112166 100644 --- a/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc +++ b/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc @@ -1,7 +1,7 @@ <div id="header-wrapper"><div id="members"> <!-- TMPL_IF NAME="opacuserlogin" --> - <ul><!-- TMPL_IF NAME="loggedinusername" --><li><span class="members">Welcome, <a href="/cgi-bin/koha/opac-user.pl"><span class="loggedinusername"><!-- TMPL_LOOP NAME="USER_INFO" --><!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --><!-- /TMPL_LOOP --></span></a></span></li><li><a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1">Log Out</a></li><!-- TMPL_ELSE --><li><a href="/cgi-bin/koha/opac-user.pl">Log in to Your Account</a></li><!-- /TMPL_IF --> - </ul> + <ul><!-- TMPL_IF NAME="loggedinusername" --><li><span class="members">Welcome, <a href="/cgi-bin/koha/opac-user.pl"><span class="loggedinusername"><!-- TMPL_LOOP NAME="USER_INFO" --><!-- TMPL_VAR NAME="title" --> <!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --><!-- /TMPL_LOOP --></span></a></span></li><!-- TMPL_IF NAME="ShowOpacRecentSearchLink" --><li><a href="/cgi-bin/koha/opac-search-history.pl" title="View your search history">Search history</a> [<a href="/cgi-bin/koha/opac-search-history.pl?action=delete" title="Delete your search history" onclick="javascript:return confirm(_('Are you sure you want to delete your search history?'));">x</a>]</li> <!-- /TMPL_IF --><li><a class="logout" id="logout" href="/cgi-bin/koha/opac-main.pl?logout.x=1">Log Out</a></li><!-- TMPL_ELSE --><li><a href="/cgi-bin/koha/opac-user.pl">Log in to Your Account</a></li><!-- /TMPL_IF --> + </ul> <!-- /TMPL_IF --> </div> <!-- TMPL_IF NAME="opacheader" --> diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-search-history.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-search-history.tmpl new file mode 100644 index 0000000..2823501 --- /dev/null +++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-search-history.tmpl @@ -0,0 +1,80 @@ +<!-- TMPL_INCLUDE NAME="doc-head-open.inc" --> +<!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog +<!-- TMPL_INCLUDE NAME="doc-head-close.inc" --> +<script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/jquery.tablesorter.min.js"></script> +<script type="text/JavaScript" language="JavaScript"> +//<![CDATA[ + $(document).ready(function() { + // We show table ordered by descending dates by default + // (so that the more recent query is shown first) + $.tablesorter.defaults.sortList = [[0,1]]; + $("#historyt").tablesorter({<!-- TMPL_IF EXPR="dateformat eq 'metric'" --> + dateFormat: 'uk'<!-- /TMPL_IF --> + }); + }); +//]]> + +</script> +</head> +<body> +<!-- TMPL_IF NAME="OpacNav" --><div id="doc3" class="yui-t1"><!-- TMPL_ELSE --><div id="doc3" class="yui-t7"><!-- /TMPL_IF --> + <div id="bd"> +<!--TMPL_INCLUDE NAME="masthead.inc" --> + + <div id="yui-main"> +<div class="yui-b"><div class="yui-g"> + <div class="container"> + <h1>Search history</h1> + <!-- TMPL_IF EXPR="recentSearches || previousSearches" --> + <!-- TMPL_IF NAME="recentSearches" --> + <!-- TMPL_IF NAME="previousSearches" --> + <h2>Current session</h2> + <!-- /TMPL_IF --> + <table id="historyt"> + <thead> + <tr><th>Date</th><th>Search</th><th>Results</th></tr> + </thead> + <tbody> + <!-- TMPL_LOOP NAME="recentSearches" --> + <tr> + <td><!-- TMPL_VAR NAME="time" --></td> + <td><a href="/cgi-bin/koha/opac-search.pl?<!-- TMPL_VAR NAME="query_cgi" -->"><!-- TMPL_VAR NAME="query_desc" --></a></td> + <td><!-- TMPL_VAR NAME="total" --></td> + </tr> + <!-- /TMPL_LOOP --> + </tbody> + </table> + <!-- /TMPL_IF --> + + <!-- TMPL_IF NAME="previousSearches" --> + <h2>Previous sessions</h2> + <table id="historyt"> + <thead> + <tr><th>Date</th><th>Search</th><th>Results</th></tr> + </thead> + <tbody> + <!-- TMPL_LOOP NAME="previousSearches" --> + <tr> + <td><!-- TMPL_VAR NAME="time" --></td> + <td><a href="/cgi-bin/koha/opac-search.pl?<!-- TMPL_VAR NAME="query_cgi" -->"><!-- TMPL_VAR NAME="query_desc" --></a></td> + <td><!-- TMPL_VAR NAME="total" --></td> + </tr> + <!-- /TMPL_LOOP --> + </tbody> + </table> + <!-- /TMPL_IF --> + <!-- TMPL_ELSE --> + <p>Your search history is now empty.</p> + <!-- /TMPL_IF --> + </div> + </div> + </div> + </div> +<!-- TMPL_IF EXPR="OpacNav||loggedinusername" --> +<div class="yui-b"><div class="container"> +<!--TMPL_INCLUDE NAME="navigation.inc" --> +<!--TMPL_INCLUDE NAME="usermenu.inc" --> +</div></div></div> +<!-- /TMPL_IF --> + +<!-- TMPL_INCLUDE NAME="opac-bottom.inc" --> diff --git a/opac/opac-search-history.pl b/opac/opac-search-history.pl new file mode 100755 index 0000000..fdf0701 --- /dev/null +++ b/opac/opac-search-history.pl @@ -0,0 +1,147 @@ +#!/usr/bin/perl + +# Copyright 2009 BibLibre SARL +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 2 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place, +# Suite 330, Boston, MA 02111-1307 USA + +use strict; +use C4::Auth qw(:DEFAULT get_session); +use CGI; +use Storable qw(freeze thaw); +use C4::Context; +use C4::Output; +use C4::Log; +use C4::Items; +use C4::Debug; +use C4::Dates; +use URI::Escape; +use POSIX qw(strftime); + + +my $cgi = new CGI; + +# Getting the template and auth +my ($template, $loggedinuser, $cookie) += get_template_and_user({template_name => "opac-search-history.tmpl", + query => $cgi, + type => "opac", + authnotrequired => 1, + flagsrequired => {borrowers => 1}, + debug => 1, + }); + +$template->param(dateformat => C4::Context->preference("dateformat")); + +# If the user is not logged in, we deal with the cookie +if ($loggedinuser == '') { + + # Deleting search history + if ($cgi->param('action') && $cgi->param('action') eq 'delete') { + # Deleting cookie's content + my $recentSearchesCookie = $cgi->cookie( + -name => 'KohaOpacRecentSearches', + -value => freeze([]), + -expires => '' + ); + + # Redirecting to this same url with the cookie in the headers so it's deleted immediately + my $uri = $cgi->url(); + print $cgi->redirect(-uri => $uri, + -cookie => $recentSearchesCookie); + + # Showing search history + } else { + + # Getting the cookie + my $searchcookie = $cgi->cookie('KohaOpacRecentSearches'); + if ($searchcookie && thaw(uri_unescape($searchcookie))) { + my @recentSearches = @{thaw(uri_unescape($searchcookie))}; + if (@recentSearches) { + + # As the dates are stored as unix timestamps, let's do some formatting + foreach my $asearch (@recentSearches) { + + # We create an iso date from the unix timestamp + my $isodate = strftime "%Y-%m-%d", localtime($asearch->{'time'}); + + # So we can create a C4::Dates object, to get the date formatted according to the dateformat syspref + my $date = C4::Dates->new($isodate, "iso"); + my $sysprefdate = $date->output("syspref"); + + # We also get the time of the day from the unix timestamp + my $time = strftime " %H:%M:%S", localtime($asearch->{'time'}); + + # And we got our human-readable date : + $asearch->{'time'} = $sysprefdate . $time; + } + + $template->param(recentSearches => \...@recentsearches); + } + } + } +} else { +# And if the user is logged in, we deal with the database + + my $dbh = C4::Context->dbh; + + # Deleting search history + if ($cgi->param('action') && $cgi->param('action') eq 'delete') { + my $query = "DELETE FROM search_history WHERE userid = ?"; + my $sth = $dbh->prepare($query); + $sth->execute($loggedinuser); + + # Redirecting to this same url so the user won't see the search history link in the header + my $uri = $cgi->url(); + print $cgi->redirect($uri); + + + # Showing search history + } else { + + my $date = C4::Dates->new(); + my $dateformat = $date->DHTMLcalendar() . " %H:%i:%S"; # Current syspref date format + standard time format + + # Getting the data with date format work done by mysql + my $query = "SELECT userid, sessionid, query_desc, query_cgi, total, DATE_FORMAT(time, \"$dateformat\") as time FROM search_history WHERE userid = ? AND sessionid = ?"; + my $sth = $dbh->prepare($query); + $sth->execute($loggedinuser, $cgi->cookie("CGISESSID")); + my $searches = $sth->fetchall_arrayref({}); + $template->param(recentSearches => $searches); + + # Getting searches from previous sessions + $query = "SELECT COUNT(*) FROM search_history WHERE userid = ? AND sessionid != ?"; + $sth = $dbh->prepare($query); + $sth->execute($loggedinuser, $cgi->cookie("CGISESSID")); + + # If at least one search from previous sessions has been performed + if ($sth->fetchrow_array > 0) { + $query = "SELECT userid, sessionid, query_desc, query_cgi, total, DATE_FORMAT(time, \"$dateformat\") as time FROM search_history WHERE userid = ? AND sessionid != ?"; + $sth = $dbh->prepare($query); + $sth->execute($loggedinuser, $cgi->cookie("CGISESSID")); + my $previoussearches = $sth->fetchall_arrayref({}); + $template->param(previousSearches => $previoussearches); + + } + + $sth->finish; + + + } + +} +output_html_with_http_headers $cgi, $cookie, $template->output; + + diff --git a/opac/opac-search.pl b/opac/opac-search.pl index 176b7ad..08b9c53 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -15,8 +15,10 @@ use C4::Search; use C4::Biblio; # GetBiblioData use C4::Koha; use C4::Tags qw(get_tags); -use POSIX qw(ceil floor strftime); use C4::Branch; # GetBranches +use POSIX qw(ceil floor strftime); +use URI::Escape; +use Storable qw(thaw freeze); # create a new CGI object # FIXME: no_undef_params needs to be tested @@ -437,7 +439,54 @@ for (my $i=0;$i<=...@servers;$i++) { if ($results_hashref->{$server}->{"hits"}){ $total = $total + $results_hashref->{$server}->{"hits"}; } - ## If there's just one result, redirect to the detail page + > + # Opac search history + my $newsearchcookie; + if (C4::Context->preference('EnableOpacSearchHistory')) { + my @recentSearches; + + # Getting the (maybe) already sent cookie + my $searchcookie = $cgi->cookie('KohaOpacRecentSearches'); + if ($searchcookie){ + $searchcookie = uri_unescape($searchcookie); + if (thaw($searchcookie)) { + @recentSearches = @{thaw($searchcookie)}; + } + } + + # Adding the new search if needed + if ($borrowernumber eq '') { + # To a cookie (the user is not logged in) + + if ($params->{'offset'} eq '') { + + push @recentSearches, { + "query_desc" => $query_desc || "unknown", + "query_cgi" => $query_cgi || "unknown", + "time" => time(), + "total" => $total + }; + $template->param(ShowOpacRecentSearchLink => 1); + } + + # Pushing the cookie back + $newsearchcookie = $cgi->cookie( + -name => 'KohaOpacRecentSearches', + # We uri_escape the whole freezed structure so we're sure we won't have any encoding problems + -value => uri_escape(freeze(\...@recentsearches)), + -expires => '' + ); + $cookie = [$cookie, $newsearchcookie]; + } + else { + # To the session (the user is logged in) + if ($params->{'offset'} eq '') { + AddSearchHistory($borrowernumber, $cgi->cookie("CGISESSID"), $query_desc, $query_cgi, $total); + $template->param(ShowOpacRecentSearchLink => 1); + } + } + } + ## If there's just one result, redirect to the detail page if ($total == 1) { my $biblionumber=$newresults[0]->{biblionumber}; if (C4::Context->preference('BiblioDefaultView') eq 'isbd') { -- 1.6.0.4 _______________________________________________ Koha-patches mailing list Koha-patches@lists.koha.org http://lists.koha.org/mailman/listinfo/koha-patches