NEW feature : RSS feeds. See POD & koha-devel for details
[koha.git] / opac / opac-rss.pl
1 #!/usr/bin/perl
2
3 use strict;    # always use
4
5 use XML::RSS;
6 use Digest::MD5 qw(md5_base64);
7 use POSIX qw(ceil floor);
8 use Date::Calc qw(Today_and_Now Delta_YMDHMS);
9 use C4::Context;
10 use C4::Search;
11 use C4::Koha;
12 use C4::Biblio;
13
14 =head1 NAME
15
16 opac-search.pl : script to have RSS feeds automatically on each OPAC search
17
18 =head1 SYNOPSIS
19
20 on each query (on OPAC), a link to this script is automatically added. The user can save it's queries as RSS feeds.
21 This script :
22
23 =over 4
24
25   - build the RDF file from the query
26   - save the RDF file in a opac/rss directory for caching : the RDF is calculated only once every 30mn, and the cache file name is calculated by a md5_base64 of the query (each user registering the same query will use the same cache : speed improvement)
27   - let the user specify it's query (q parameter : opac-rss.pl?q=ti:hugo)
28   - let the user specify the number of results returned (by default 20, but there are no limits : opac-rss.pl?q=ti:hugo&size=9999)
29
30 This script auto calculates the website URL
31
32 the RDF contains : 
33
34 =over 4
35
36   - Koha: $query as RSS title
37   - Koha as subject
38   - LibraryName systempreference as RDF description and creator
39   - copyright currentyear
40   - biblio title as RSS "title" and biblio author as RSS description
41
42 =cut
43
44 # create a new CGI object
45 # not sure undef_params option is working, need to test
46 use CGI qw('-no_undef_params');
47 my $cgi = new CGI;
48
49 # the query to use
50 my $query = $cgi->param('q');
51 $query =~ s/:/=/g;
52
53 # the number of lines to retrieve
54 my $size=$cgi->param('size') || 20;
55
56 # the filename of the cached rdf file.
57 my $filename = md5_base64($query);
58 my $rss = new XML::RSS (version => '1.0');
59
60 # the site URL
61 my $url = $cgi->url();
62 $url =~ s/opac-rss\.pl.*//;
63 $url =~ /(http:\/\/.*?)\//;
64 my $short_url=$1;
65
66 my $RDF_update_needed=1;
67     my ($year,$month,$day, $hour,$min,$sec) = Today_and_Now();
68
69 if (-e "rss/$filename") {
70     $rss->parsefile("rss/$filename");
71     # check if we have to rebuild the RSS feed (once every 30mn), or just return the actual rdf
72     my $rdf_stamp = $rss->{'channel'}->{'dc'}->{'date'};
73     $rdf_stamp =~ /(.*)-(.*)-(.*):(.*):(.*):(.*)/;
74     my ($stamp_year,$stamp_month,$stamp_day,$stamp_hour,$stamp_min,$stamp_sec) = ($1,$2,$3,$4,$5,$6);
75     # if less than 30 mn since the last RDF update, rebuild the RDF. Otherwise, just return it
76     unless (($year-$stamp_year >0) or ($month-$stamp_month >0) or ($day-$stamp_day >0) or ($hour-$stamp_hour >0) or ($min-$stamp_min >30)) {
77         $RDF_update_needed =0;
78     }
79 }
80
81 if ($RDF_update_needed) {
82 #     warn "RDF update in progress";
83     $rss->channel(
84                 title        => "Koha : $query",
85                 description  => C4::Context->preference("LibraryName"),
86                 link => $short_url,
87                 dc => {
88                     date       => "$year-$month-$day:$hour:$min:$sec",
89                     subject    => "Koha",
90                     creator    => C4::Context->preference("LibraryName"),
91                     rights     => "Copyright $year" ,
92                     language   => C4::Context->preference("opaclanguages"),
93                 },
94     );
95     
96     my $total;    # the total results for the whole set
97     my ($error, $marcresults) = SimpleSearch($query);
98     
99     my $hits = scalar @$marcresults;
100     $hits=$size if $hits > $size;
101     my @results;
102     for(my $i=0;$i<$hits;$i++) {
103         my %resultsloop;
104         my $marcrecord = MARC::File::USMARC::decode($marcresults->[$i]);
105         my $biblio = TransformMarcToKoha(C4::Context->dbh,$marcrecord,'');
106         # check if the entry is already in the feed. Otherwise, pop the $line th line and add this new one.
107         my $already_in_feed=0;
108         foreach (@{$rss->{'items'}}) {
109             if ($_->{'link'} =~ /biblionumber=$biblio->{'biblionumber'}/) {
110                 $already_in_feed=1;
111             }
112         }
113         unless ($already_in_feed) {
114             pop(@{$rss->{'items'}}) if (@{$rss->{'items'}} >= $size);
115             $rss->add_item(title => $biblio->{'title'},
116                             description => $biblio->{'author'},
117                             link        => "$url/opac-detail.pl?biblionumber=".$biblio->{'biblionumber'},
118                             mode =>'insert',
119             );
120         }
121     }
122     # save the rss feed.
123     $rss->save("rss/$filename");
124 } else {
125 #     warn "RDF CACHE used"
126 }
127 print $cgi->header(-type => "application/rss+xml");
128 print $rss->as_string;