[Koha-patches] [PATCH] [SIGNED-OFF] Bug 6772 - recommendation system

Frédéric Demians f.demians at tamil.fr
Thu Sep 1 13:52:33 CEST 2011


From: Chris Cormack <chris at bigballofwax.co.nz>

This allows Koha to link similar books to provide recommendations to
users. It provides a cron job that should be run regularly (daily or
weekly perhaps) to build a recommendation index. When viewing books in
the OPAC, those items with the closest match will be displayed.

Author: Chris Cormack <chris at bigballofwax.co.nz>
Author: Robin Sheat <robin at catalyst.net.nz>
Signed-off-by: Frédéric Demians <f.demians at tamil.fr>
---
 C4/Recommendations.pm                              |  204 ++++++++++++++++++++
 debian/koha-common.cron.daily                      |    4 +
 installer/data/mysql/de-DE/mandatory/sysprefs.sql  |    2 +-
 installer/data/mysql/en/mandatory/sysprefs.sql     |    1 +
 .../1-Obligatoire/unimarc_standard_systemprefs.sql |    1 +
 installer/data/mysql/it-IT/necessari/sysprefs.sql  |    1 +
 installer/data/mysql/kohastructure.sql             |   11 +
 .../data/mysql/nb-NO/1-Obligatorisk/sysprefs.sql   |    1 +
 installer/data/mysql/pl-PL/mandatory/sysprefs.sql  |    1 +
 ...m_preferences_full_optimal_for_install_only.sql |    1 +
 ...m_preferences_full_optimal_for_install_only.sql |    1 +
 installer/data/mysql/updatedatabase.pl             |   17 ++
 .../prog/en/modules/admin/preferences/opac.pref    |    6 +
 koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt |   11 +
 misc/cronjobs/recommendations.pl                   |   53 +++++
 opac/opac-detail.pl                                |    8 +
 16 files changed, 322 insertions(+), 1 deletions(-)
 create mode 100644 C4/Recommendations.pm
 create mode 100755 misc/cronjobs/recommendations.pl

diff --git a/C4/Recommendations.pm b/C4/Recommendations.pm
new file mode 100644
index 0000000..0cd0e00
--- /dev/null
+++ b/C4/Recommendations.pm
@@ -0,0 +1,204 @@
+package C4::Recommendations;
+
+# Copyright 2009,2011 Catalyst IT
+#
+# 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
+
+=head1 NAME
+
+    C4::Recommendations - Koha module for producing reading recommendations
+
+=head1 SYNOPSIS
+
+    use C4::Recommendations;
+
+    build_recommendations();
+
+    my $recommended_books = get_recommendations($biblio);
+
+=head1 DESCRIPTION
+
+This looks at the issue history, and counts how many times each particular book
+has been taken out by someone who also has taken out another particular book,
+recording that as a hit for each pair.
+
+For example, if 3 people have taken out book A and book B, then this is
+recorded as three "hits" for that combination, and so it'll show as a
+recommendation with that strength.
+
+=head1 EXPORT
+
+None by default, however C<build_recommendations> and C<get_recommendations>
+can be imported optionally.
+
+=head1 FUNCTIONS
+
+=cut
+
+use strict;
+use warnings;
+use C4::Context;
+
+require Exporter;
+
+our @ISA = qw(Exporter);
+
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+our @EXPORT_OK = qw(
+    build_recommendations 
+    get_recommendations
+);
+
+our $VERSION = '0.01';
+
+=head2 build_recommendations
+
+    build_recommendations
+
+This runs through all the issues and generates the tables of recommendations.
+Note that it'll likely take a long time to run, and put stress on the database,
+so do it at a low peak time.
+
+=cut
+
+sub build_recommendations {
+    my $dbh = C4::Context->dbh;
+    $dbh->do("TRUNCATE recommendations");
+    my $all_issues_query = qq/
+SELECT biblio.biblionumber,borrowernumber 
+FROM old_issues,biblio,items 
+WHERE old_issues.itemnumber=items.itemnumber 
+AND items.biblionumber=biblio.biblionumber
+    /;
+    my $all_issues_sth = $dbh->prepare($all_issues_query);
+    my $borrower_issues_query = qq/
+SELECT  biblio.biblionumber,borrowernumber 
+FROM old_issues,biblio,items 
+WHERE old_issues.itemnumber=items.itemnumber 
+AND items.biblionumber=biblio.biblionumber 
+AND old_issues.borrowernumber = ?
+AND items.biblionumber > ?
+    /;
+    my $borrower_issues_sth = $dbh->prepare($borrower_issues_query);
+    my $recommendations_select = $dbh->prepare(qq/
+SELECT * FROM recommendations 
+WHERE biblio_one = ? AND 
+biblio_two = ?
+    /);
+    my $recommendations_update = $dbh->prepare(qq/
+UPDATE recommendations 
+SET hit_count = ? 
+WHERE biblio_one = ? 
+AND biblio_two = ?
+    /);
+    my $recommendations_insert = $dbh->prepare(qq/
+INSERT INTO recommendations (biblio_one,biblio_two,hit_count) VALUES (?,?,?)
+    /);
+
+    $all_issues_sth->execute();
+    while ( my $issue = $all_issues_sth->fetchrow_hashref() ) {
+#	warn $issue->{'borrowernumber'};
+        $borrower_issues_sth->execute( $issue->{'borrowernumber'}, $issue->{biblionumber} );
+        while ( my $borrowers_issue = $borrower_issues_sth->fetchrow_hashref() ) {
+#	    warn $borrowers_issue->{'biblionumber'};
+            $recommendations_select->execute( $issue->{'biblionumber'},
+                $borrowers_issue->{'biblionumber'} );
+            if ( my $recommendation = $recommendations_select->fetchrow_hashref() ) {
+                $recommendation->{'hit_count'}++;
+                $recommendations_update->execute(
+                    $recommendation->{'hit_count'},
+                    $issue->{'biblionumber'},
+                    $borrowers_issue->{'biblionumber'}
+                );
+            } else {
+                $recommendations_insert->execute(
+                    $issue->{'biblionumber'},
+                    $borrowers_issue->{'biblionumber'},
+		            1
+                );
+            }
+        }
+
+    }
+}
+
+=head2 get_recommendations
+
+    my $recommendations = get_recommendations($biblionumber, $limit)
+    foreach my $rec (@$recommendations) {
+    	print $rec->{biblionumber}.": ".$rec->{title}."\n";
+    }
+
+This gets the recommendations for a particular biblio, returning an array of
+hashes containing C<biblionumber> and C<title>. The array is ordered from
+most-recommended to least.
+
+C<$limit> restrictes the amount of results returned. If it's not supplied,
+it defaults to 100.
+
+=cut
+
+sub get_recommendations {
+    my ($biblionumber, $limit) = @_;
+    $limit ||= 100;
+
+    my $dbh = C4::Context->dbh();
+
+    # Two parts: first get the biblio_one side, then get the 
+    # biblio_two side. I'd love to know how to squish this into one query.
+    my $sth = $dbh->prepare(qq/
+SELECT biblio.biblionumber,biblio.title, hit_count
+FROM biblio,recommendations 
+WHERE biblio.biblionumber = biblio_two
+AND biblio_one = ?
+ORDER BY hit_count DESC
+LIMIT ?
+    /);
+    $sth->execute($biblionumber, $limit);
+    my $res = $sth->fetchall_arrayref({});
+
+    $sth = $dbh->prepare(qq/
+SELECT biblio.biblionumber,biblio.title, hit_count
+FROM biblio,recommendations 
+WHERE biblio.biblionumber = biblio_one
+AND biblio_two = ?
+ORDER BY hit_count DESC
+LIMIT ?
+    /);
+    $sth->execute($biblionumber, $limit);
+    push @{ $res }, @{$sth->fetchall_arrayref({})};
+
+    $res = \@{ @{$res}[0..$limit] } if (@$res > $limit);
+
+    my @res = sort { $b->{hit_count} <=> $a->{hit_count} } @$res;
+    return \@res;
+}
+
+1;
+__END__
+
+=head1 AUTHOR
+
+=over
+
+=item Chris Cormack, E<lt>chrisc at catalyst.net.nzE<gt>
+
+=item Robin Sheat, E<lt>robin at catalyst.net.nzE<gt>
+
+=back
+
diff --git a/debian/koha-common.cron.daily b/debian/koha-common.cron.daily
index e2c7a80..86a7fe5 100644
--- a/debian/koha-common.cron.daily
+++ b/debian/koha-common.cron.daily
@@ -23,3 +23,7 @@ koha-foreach --enabled /usr/share/koha/bin/cronjobs/services_throttle.pl > /dev/
 koha-foreach --enabled /usr/share/koha/bin/cronjobs/cleanup_database.pl --sessions --zebraqueue 10
 koha-foreach --enabled --noemail /usr/share/koha/bin/cronjobs/cleanup_database.pl --mail
 koha-run-backups --days 2 --output /var/spool/koha
+
+# If recommendations are enabled, this may take a while to run. However, it'll
+# stop pretty much immediately if it doesn't need to do anything.
+koha-foreach --enabled /usr/share/koha/bin/cronjobs/recommendations.pl
diff --git a/installer/data/mysql/de-DE/mandatory/sysprefs.sql b/installer/data/mysql/de-DE/mandatory/sysprefs.sql
index 6df6a9f..1107703 100755
--- a/installer/data/mysql/de-DE/mandatory/sysprefs.sql
+++ b/installer/data/mysql/de-DE/mandatory/sysprefs.sql
@@ -317,4 +317,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0, 'If ON Openlibrary book covers will be show',NULL,'YesNo');
-
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
diff --git a/installer/data/mysql/en/mandatory/sysprefs.sql b/installer/data/mysql/en/mandatory/sysprefs.sql
index 8407505..3d17252 100755
--- a/installer/data/mysql/en/mandatory/sysprefs.sql
+++ b/installer/data/mysql/en/mandatory/sysprefs.sql
@@ -317,3 +317,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0,'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
diff --git a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql
index d46502c..d13cc73 100755
--- a/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql
+++ b/installer/data/mysql/fr-FR/1-Obligatoire/unimarc_standard_systemprefs.sql
@@ -318,4 +318,5 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0,'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
 
diff --git a/installer/data/mysql/it-IT/necessari/sysprefs.sql b/installer/data/mysql/it-IT/necessari/sysprefs.sql
index 3448738..17cc120 100755
--- a/installer/data/mysql/it-IT/necessari/sysprefs.sql
+++ b/installer/data/mysql/it-IT/necessari/sysprefs.sql
@@ -304,4 +304,5 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0,'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
 
diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql
index 13fa53d..ce4bc37 100644
--- a/installer/data/mysql/kohastructure.sql
+++ b/installer/data/mysql/kohastructure.sql
@@ -2613,6 +2613,17 @@ CREATE TABLE `fieldmapping` (
   PRIMARY KEY  (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
+DROP TABLE IF EXISTS `recommendations`;
+CREATE TABLE `recommendations` (
+  `id` int(11) NOT NULL auto_increment,
+  `biblio_one` int(11),
+  `biblio_two` int(11),
+  `hit_count` int(11),
+  PRIMARY KEY  (`id`),
+  KEY `biblio_one_idx` (`biblio_one`),
+  KEY `biblio_two_idx` (`biblio_two`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
+
 
 /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
 /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
diff --git a/installer/data/mysql/nb-NO/1-Obligatorisk/sysprefs.sql b/installer/data/mysql/nb-NO/1-Obligatorisk/sysprefs.sql
index ac4c3e2..37eca0f 100644
--- a/installer/data/mysql/nb-NO/1-Obligatorisk/sysprefs.sql
+++ b/installer/data/mysql/nb-NO/1-Obligatorisk/sysprefs.sql
@@ -324,3 +324,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0,'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
diff --git a/installer/data/mysql/pl-PL/mandatory/sysprefs.sql b/installer/data/mysql/pl-PL/mandatory/sysprefs.sql
index 3087f3c..6e9a72a 100755
--- a/installer/data/mysql/pl-PL/mandatory/sysprefs.sql
+++ b/installer/data/mysql/pl-PL/mandatory/sysprefs.sql
@@ -316,3 +316,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0, 'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
diff --git a/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql b/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql
index c0912ba..8e82624 100755
--- a/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql
+++ b/installer/data/mysql/ru-RU/mandatory/system_preferences_full_optimal_for_install_only.sql
@@ -371,3 +371,4 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0,'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
diff --git a/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql b/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql
index d334469..afc93e7 100755
--- a/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql
+++ b/installer/data/mysql/uk-UA/mandatory/system_preferences_full_optimal_for_install_only.sql
@@ -396,4 +396,5 @@ INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES (
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('BasketConfirmations', '1', 'When closing or reopening a basket,', 'always ask for confirmation.|do not ask for confirmation.', 'Choice');
 INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES ('MARCAuthorityControlField008', '|| aca||aabn           | a|a     d', NULL, NULL, 'Textarea');
 INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('OpenLibraryCovers',0, 'If ON Openlibrary book covers will be show',NULL,'YesNo');
+INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');
 
diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl
index bdfc9ac..272a0c1 100755
--- a/installer/data/mysql/updatedatabase.pl
+++ b/installer/data/mysql/updatedatabase.pl
@@ -4440,6 +4440,23 @@ if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
 }
 
 
+$DBversion = "3.05.00.011";
+if (C4::Context->preference("Version") < TransformToNum($DBversion)) {
+    $dbh->do("
+        CREATE TABLE `recommendations` (
+          `id` int(11) NOT NULL auto_increment,
+          `biblio_one` int(11),
+          `biblio_two` int(11),
+          `hit_count` int(11),
+          PRIMARY KEY  (`id`),
+          KEY `biblio_one_idx` (`biblio_one`),
+          KEY `biblio_two_idx` (`biblio_two`)
+        ) ENGINE=InnoDB DEFAULT CHARSET=utf8
+    ");
+    $dbh->do("INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES('ShowRecommendations',0,'If ON recommendation information will be generated and displayed',NULL,'YesNo');");
+    print "Add table and syspref track the recommended reading data.\n";
+    SetVersion($DBversion);
+}
 =head1 FUNCTIONS
 
 =head2 DropAllForeignKeys($table)
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref
index 4a7c652..cd00daa 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref
@@ -268,6 +268,12 @@ OPAC:
             - pref: numSearchRSSResults
               class: long
             -  search results in the RSS feed.
+        -
+            - pref: ShowRecommendations
+              choices:
+                  yes: Do
+                  no: "Don't"
+            - "generate and display reading recommendations in the OPAC. <i>(Notes: this requires the <tt>recommendations.pl</tt> cron job to be configured to run regularly. This cron job will take a long time to run on catalogs with a sizable circulation history.)</i>"
     Policy:
         -
             - pref: singleBranchMode
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt b/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt
index 40af8f5..e5243af 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt
@@ -363,6 +363,7 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
     [% IF ( OPACFRBRizeEditions ) %][% IF ( XISBNS ) %]<li><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% biblionumber %]#editions">Editions</a></li>[% END %][% END %]
     
     [% IF ( OPACAmazonEnabled ) %][% IF ( OPACAmazonReviews ) %]<li><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% biblionumber %]#amazonreviews">Amazon Reviews</a></li>[% END %][% END %]
+    [% IF ( Recommendations ) %]<li><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% biblionumber %]#recommendations">Recommendations</a></li>[% END %]
     [% IF ( Babeltheque ) %]<li><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% biblionumber %]#babeltheque">Babelthèque</a></li>[% END %]
 
     [% IF ( serialcollection ) %]
@@ -728,6 +729,16 @@ YAHOO.util.Event.onContentReady("furtherm", function () {
 </div>
 [% END %]
 
+[% IF (Recommendations) %]
+<div id="recommendations">
+<table>
+[% FOREACH recommendation IN recommendation_loop %]
+<tr><td><a href="/cgi-bin/koha/opac-detail.pl?biblionumber=[% recommendation.biblionumber %]">[% recommendation.title | html %]</a></td></tr>
+[% END %]
+</table>
+</div>
+[% END %]
+
 [% IF ( OPACFRBRizeEditions ) %][% IF ( XISBNS ) %]
 <div id="editions">
 
diff --git a/misc/cronjobs/recommendations.pl b/misc/cronjobs/recommendations.pl
new file mode 100755
index 0000000..d2b114f
--- /dev/null
+++ b/misc/cronjobs/recommendations.pl
@@ -0,0 +1,53 @@
+#!/usr/bin/perl
+
+# Copyright 2009,2011 Catalyst IT Ltd.
+#
+# 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
+
+=head1 NAME
+
+recommendations.pl - cron script to populate the recommendations table
+
+=head1 SYNOPSIS
+
+./recommendations.pl
+
+or, in crontab:
+0 1 * * * recommendations.pl
+
+=head1 DESCRIPTION
+
+=cut
+
+use strict;
+use warnings;
+BEGIN {
+    # find Koha's Perl modules
+    # test carefully before changing this
+    use FindBin;
+    eval { require "$FindBin::Bin/../kohalib.pl" };
+}
+
+use C4::Context;
+use C4::Recommendations qw/ build_recommendations /;
+
+if (C4::Context->preference('ShowRecommendations')) {
+    build_recommendations();
+}
+
+1;
+
+__END__
diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl
index e18e046..b17d77a 100755
--- a/opac/opac-detail.pl
+++ b/opac/opac-detail.pl
@@ -42,6 +42,7 @@ use C4::VirtualShelves;
 use C4::XSLT;
 use C4::ShelfBrowser;
 use C4::Charset;
+use C4::Recommendations qw/ get_recommendations /;
 use MARC::Record;
 use MARC::Field;
 use List::MoreUtils qw/any none/;
@@ -66,6 +67,13 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user(
 
 my $biblionumber = $query->param('biblionumber') || $query->param('bib');
 
+if ( C4::Context->preference('ShowRecommendations')){
+    my $recommendations = get_recommendations($biblionumber);
+    $template->param('Recommendations' => 1,
+	'recommendation_loop' => $recommendations
+	);
+}
+
 $template->param( 'AllowOnShelfHolds' => C4::Context->preference('AllowOnShelfHolds') );
 $template->param( 'ItemsIssued' => CountItemsIssued( $biblionumber ) );
 
-- 
1.7.6.1



More information about the Koha-patches mailing list