[Koha-patches] [PATCH] Fix for Bug 4473 - Recent comments view for the OPAC

Owen Leonard oleonard at myacpl.org
Tue Dec 7 18:52:53 CET 2010


- modifies opac-showreviews.pl to display recent comments for all
  titles, sorted in descending order by date.
- includes RSS feed
- includes (thanks to Chris N.):

[Enhancement][3.4] Add RFC822 Format to C4::Dates

This patch adds RFC822 formatting to C4::Dates. It also updates Dates.t
appropriately. Consult the POD for this module for how to use
this format.

Please note that this module *does not* handle TZ conversion at this point.
This means that the TZ portion of a RFC822 time will be truncated and the converted
time will be in the same TZ as was passed in. When generating an RFC822 time,
the local TZ offset will be included since none of the other supported formats
provide a means for including their TZ. This is not a problem introduced by the
addition of RFC822 formatting. Rather it is due to this module not having TZ
support to begin with.

Also note that the dow, moy abbreviations are English as required by
RFC822 section 3.3 (thanks to self for pointing that out).
---
 C4/Dates.pm                                        |  274 ++++++++++++--------
 C4/Review.pm                                       |   20 +-
 koha-tmpl/opac-tmpl/prog/en/css/opac.css           |   28 ++-
 .../prog/en/modules/opac-showreviews-rss.tmpl      |   36 +++
 .../prog/en/modules/opac-showreviews.tmpl          |  100 ++++++--
 opac/opac-showreviews.pl                           |  128 +++++++++-
 t/Dates.t                                          |  115 ++++----
 7 files changed, 494 insertions(+), 207 deletions(-)
 create mode 100644 koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews-rss.tmpl

diff --git a/C4/Dates.pm b/C4/Dates.pm
index 451e2d3..335de1c 100644
--- a/C4/Dates.pm
+++ b/C4/Dates.pm
@@ -1,4 +1,5 @@
 package C4::Dates;
+
 # This file is part of Koha.
 #
 # Koha is free software; you can redistribute it and/or modify it under the
@@ -26,154 +27,198 @@ use vars qw($VERSION @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS);
 use vars qw($debug $cgi_debug);
 
 BEGIN {
-	$VERSION = 0.04;
-	@ISA = qw(Exporter);
-	@EXPORT_OK = qw(format_date_in_iso format_date);
+    $VERSION   = 0.04;
+    @ISA       = qw(Exporter);
+    @EXPORT_OK = qw(format_date_in_iso format_date);
 }
 
 use vars qw($prefformat);
+
 sub _prefformat {
-    unless (defined $prefformat) {
+    unless ( defined $prefformat ) {
         $prefformat = C4::Context->preference('dateformat');
     }
     return $prefformat;
 }
 
-our %format_map = ( 
-	  iso  => 'yyyy-mm-dd', # plus " HH:MM:SS"
-	metric => 'dd/mm/yyyy', # plus " HH:MM:SS"
-	  us   => 'mm/dd/yyyy', # plus " HH:MM:SS"
-	  sql  => 'yyyymmdd    HHMMSS',
+our %format_map = (
+    iso    => 'yyyy-mm-dd',           # plus " HH:MM:SS"
+    metric => 'dd/mm/yyyy',           # plus " HH:MM:SS"
+    us     => 'mm/dd/yyyy',           # plus " HH:MM:SS"
+    sql    => 'yyyymmdd    HHMMSS',
+    rfc822 => 'a, dd b y HH:MM:SS z ',
 );
 our %posix_map = (
-	  iso  => '%Y-%m-%d',	# or %F, "Full Date"
-	metric => '%d/%m/%Y',
-	  us   => '%m/%d/%Y',
-	  sql  => '%Y%m%d    %H%M%S',
+    iso    => '%Y-%m-%d',             # or %F, "Full Date"
+    metric => '%d/%m/%Y',
+    us     => '%m/%d/%Y',
+    sql    => '%Y%m%d    %H%M%S',
+    rfc822 => '%a, %d %b %Y %H:%M:%S %z',
 );
 
-our %dmy_subs = (			# strings to eval  (after using regular expression returned by regexp below)
-							# make arrays for POSIX::strftime()
-	  iso  => '[(($6||0),($5||0),($4||0),$3, $2 - 1, $1 - 1900)]',		
-	metric => '[(($6||0),($5||0),($4||0),$1, $2 - 1, $3 - 1900)]',
-	  us   => '[(($6||0),($5||0),($4||0),$2, $1 - 1, $3 - 1900)]',
-	  sql  => '[(($6||0),($5||0),($4||0),$3, $2 - 1, $1 - 1900)]',
+our %dmy_subs = (                     # strings to eval  (after using regular expression returned by regexp below)
+                                      # make arrays for POSIX::strftime()
+    iso    => '[(($6||0),($5||0),($4||0),$3, $2 - 1, $1 - 1900)]',
+    metric => '[(($6||0),($5||0),($4||0),$1, $2 - 1, $3 - 1900)]',
+    us     => '[(($6||0),($5||0),($4||0),$2, $1 - 1, $3 - 1900)]',
+    sql    => '[(($6||0),($5||0),($4||0),$3, $2 - 1, $1 - 1900)]',
+    rfc822 => '[($7, $6, $5, $2, $3, $4 - 1900, $8)]',
 );
 
+our @months = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec);
+
+our @days = qw(Sun Mon Tue Wed Thu Fri Sat);
+
 sub regexp ($;$) {
-	my $self = shift;
-	my $delim = qr/:?\:|\/|-/;	# "non memory" cluster: no backreference
-	my $format = (@_) ? _recognize_format(shift) : ($self->{'dateformat'} || _prefformat());
+    my $self   = shift;
+    my $delim  = qr/:?\:|\/|-/;                                                                  # "non memory" cluster: no backreference
+    my $format = (@_) ? _recognize_format(shift) : ( $self->{'dateformat'} || _prefformat() );
 
     # Extra layer of checking $self->{'dateformat'}.
     # Why?  Because it is assumed you might want to check regexp against an *instantiated* Dates object as a
     # way of saying "does this string match *whatever* format that Dates object is?"
 
-	($format eq 'sql') and 
-	return qr/^(\d{4})(\d{1,2})(\d{1,2})(?:\s{4}(\d{2})(\d{2})(\d{2}))?/;
-	($format eq 'iso') and 
-	return qr/^(\d{4})$delim(\d{1,2})$delim(\d{1,2})(?:(?:\s{1}|T)(\d{2})\:?(\d{2})\:?(\d{2}))?Z?/;
-	return qr/^(\d{1,2})$delim(\d{1,2})$delim(\d{4})(?:\s{1}(\d{1,2})\:?(\d{1,2})\:?(\d{1,2}))?/;  # everything else
+    ( $format eq 'sql' )
+      and return qr/^(\d{4})(\d{1,2})(\d{1,2})(?:\s{4}(\d{2})(\d{2})(\d{2}))?/;
+    ( $format eq 'iso' )
+      and return qr/^(\d{4})$delim(\d{1,2})$delim(\d{1,2})(?:(?:\s{1}|T)(\d{2})\:?(\d{2})\:?(\d{2}))?Z?/;
+    ( $format eq 'rfc822' )
+      and return qr/^([a-zA-Z]{3}),\s{1}(\d{1,2})\s{1}([a-zA-Z]{3})\s{1}(\d{4})\s{1}(\d{1,2})\:(\d{1,2})\:(\d{1,2})\s{1}(([\-|\+]\d{4})|([A-Z]{3}))/;
+    return qr/^(\d{1,2})$delim(\d{1,2})$delim(\d{4})(?:\s{1}(\d{1,2})\:?(\d{1,2})\:?(\d{1,2}))?/;    # everything else
 }
 
 sub dmy_map ($$) {
-	my $self = shift;
-	my $val  = shift 					or return undef;
-	my $dformat = $self->{'dateformat'} or return undef;
-	my $re = $self->regexp();
-	my $xsub = $dmy_subs{$dformat};
-	$debug and print STDERR "xsub: $xsub \n";
-	if ($val =~ /$re/) {
-		my $aref = eval $xsub;
+    my $self    = shift;
+    my $val     = shift or return undef;
+    my $dformat = $self->{'dateformat'} or return undef;
+    my $re      = $self->regexp();
+    my $xsub    = $dmy_subs{$dformat};
+    $debug and print STDERR "xsub: $xsub \n";
+    if ( $val =~ /$re/ ) {
+        my $aref = eval $xsub;
+        if ($dformat eq 'rfc822') {
+            $aref = _abbr_to_numeric($aref, $dformat);
+            pop(@{$aref}); #pop off tz offset because we are not setup to handle tz conversions just yet
+        }
         _check_date_and_time($aref);
-		return  @{$aref}; 
-	}
-	# $debug and 
-	carp "Illegal Date '$val' does not match '$dformat' format: " . $self->visual();
-	return 0;
+        push @{$aref}, (-1,-1,1); # for some reason unknown to me, setting isdst to -1 or undef causes strftime to fail to return the tz offset which is required in RFC822 format -chris_n
+        return @{$aref};
+    }
+
+    # $debug and
+    carp "Illegal Date '$val' does not match '$dformat' format: " . $self->visual();
+    return 0;
+}
+
+sub _abbr_to_numeric {
+    my $aref    = shift;
+    my $dformat = shift;
+    my ($month_abbr, $day_abbr) = ($aref->[4], $aref->[3]) if $dformat eq 'rfc822';
+
+    for( my $i = 0; $i < scalar(@months); $i++ ) {
+        if ( $months[$i] =~ /$month_abbr/ ) {
+            $aref->[4] = $i-1;
+            last;
+        }
+    };
+
+    for( my $i = 0; $i < scalar(@days); $i++ ) {
+        if ( $days[$i] =~ /$day_abbr/ ) {
+            $aref->[3] = $i;
+            last;
+        }
+    };
+    return $aref;
 }
 
 sub _check_date_and_time {
     my $chron_ref = shift;
-    my ($year, $month, $day) = _chron_to_ymd($chron_ref);
-    unless (check_date($year, $month, $day)) {
+    my ( $year, $month, $day ) = _chron_to_ymd($chron_ref);
+    unless ( check_date( $year, $month, $day ) ) {
         carp "Illegal date specified (year = $year, month = $month, day = $day)";
     }
-    my ($hour, $minute, $second) = _chron_to_hms($chron_ref);
-    unless (check_time($hour, $minute, $second)) {
+    my ( $hour, $minute, $second ) = _chron_to_hms($chron_ref);
+    unless ( check_time( $hour, $minute, $second ) ) {
         carp "Illegal time specified (hour = $hour, minute = $minute, second = $second)";
     }
 }
 
 sub _chron_to_ymd {
     my $chron_ref = shift;
-    return ($chron_ref->[5] + 1900, $chron_ref->[4] + 1, $chron_ref->[3]);
+    return ( $chron_ref->[5] + 1900, $chron_ref->[4] + 1, $chron_ref->[3] );
 }
 
 sub _chron_to_hms {
     my $chron_ref = shift;
-    return ($chron_ref->[2], $chron_ref->[1], $chron_ref->[0]);
+    return ( $chron_ref->[2], $chron_ref->[1], $chron_ref->[0] );
 }
 
 sub new {
-	my $this = shift;
-	my $class = ref($this) || $this;
-	my $self = {};
-	bless $self, $class;
-	return $self->init(@_);
+    my $this  = shift;
+    my $class = ref($this) || $this;
+    my $self  = {};
+    bless $self, $class;
+    return $self->init(@_);
 }
+
 sub init ($;$$) {
-	my $self = shift;
-	my $dformat;
-	$self->{'dateformat'} = $dformat = (scalar(@_) >= 2) ? $_[1] : _prefformat();
-	($format_map{$dformat}) or croak 
-		"Invalid date format '$dformat' from " . ((scalar(@_) >= 2) ? 'argument' : 'system preferences');
-	$self->{'dmy_arrayref'} = [((@_) ? $self->dmy_map(shift) : localtime )] ;
-	$debug and warn "(during init) \@\$self->{'dmy_arrayref'}: " . join(' ',@{$self->{'dmy_arrayref'}}) . "\n";
-	return $self;
+    my $self = shift;
+    my $dformat;
+    $self->{'dateformat'} = $dformat = ( scalar(@_) >= 2 ) ? $_[1] : _prefformat();
+    ( $format_map{$dformat} ) or croak "Invalid date format '$dformat' from " . ( ( scalar(@_) >= 2 ) ? 'argument' : 'system preferences' );
+    $self->{'dmy_arrayref'} = [ ( (@_) ? $self->dmy_map(shift) : localtime ) ];
+    $debug and warn "(during init) \@\$self->{'dmy_arrayref'}: " . join( ' ', @{ $self->{'dmy_arrayref'} } ) . "\n";
+    return $self;
 }
+
 sub output ($;$) {
-	my $self = shift;
-	my $newformat = (@_) ? _recognize_format(shift) : _prefformat();
-	return (eval {POSIX::strftime($posix_map{$newformat}, @{$self->{'dmy_arrayref'}})} || undef);
+    my $self = shift;
+    my $newformat = (@_) ? _recognize_format(shift) : _prefformat();
+    return ( eval { POSIX::strftime( $posix_map{$newformat}, @{ $self->{'dmy_arrayref'} } ) } || undef );
 }
-sub today ($;$) {		# NOTE: sets date value to today (and returns it in the requested or current format)
-	my $class = shift;
-	$class = ref($class) || $class;
-	my $format = (@_) ? _recognize_format(shift) : _prefformat();
-	return $class->new()->output($format);
+
+sub today ($;$) {    # NOTE: sets date value to today (and returns it in the requested or current format)
+    my $class = shift;
+    $class = ref($class) || $class;
+    my $format = (@_) ? _recognize_format(shift) : _prefformat();
+    return $class->new()->output($format);
 }
+
 sub _recognize_format($) {
-	my $incoming = shift;
-	($incoming eq 'syspref') and return _prefformat();
-	(scalar grep (/^$incoming$/, keys %format_map) == 1) or croak "The format you asked for ('$incoming') is unrecognized.";
-	return $incoming;
+    my $incoming = shift;
+    ( $incoming eq 'syspref' ) and return _prefformat();
+    ( scalar grep ( /^$incoming$/, keys %format_map ) == 1 ) or croak "The format you asked for ('$incoming') is unrecognized.";
+    return $incoming;
 }
-sub DHTMLcalendar ($;$) {	# interface to posix_map
-	my $class = shift;
-	my $format = (@_) ? shift : _prefformat();
-	return $posix_map{$format};	
+
+sub DHTMLcalendar ($;$) {    # interface to posix_map
+    my $class = shift;
+    my $format = (@_) ? shift : _prefformat();
+    return $posix_map{$format};
 }
-sub format {	# get or set dateformat: iso, metric, us, etc.
-	my $self = shift;
-	(@_) or return $self->{'dateformat'}; 
-	$self->{'dateformat'} = _recognize_format(shift);
+
+sub format {                 # get or set dateformat: iso, metric, us, etc.
+    my $self = shift;
+    (@_) or return $self->{'dateformat'};
+    $self->{'dateformat'} = _recognize_format(shift);
 }
+
 sub visual {
-	my $self = shift;
-	if (@_) {
-		return $format_map{ _recognize_format(shift) };
-	}
-	$self eq __PACKAGE__ and return $format_map{_prefformat()};
-	return $format_map{ eval { $self->{'dateformat'} } || _prefformat()} ;
+    my $self = shift;
+    if (@_) {
+        return $format_map{ _recognize_format(shift) };
+    }
+    $self eq __PACKAGE__ and return $format_map{ _prefformat() };
+    return $format_map{ eval { $self->{'dateformat'} } || _prefformat() };
 }
 
 # like the functions from the old C4::Date.pm
 sub format_date {
-	return __PACKAGE__ -> new(shift,'iso')->output((@_) ? shift : _prefformat());
+    return __PACKAGE__->new( shift, 'iso' )->output( (@_) ? shift : _prefformat() );
 }
+
 sub format_date_in_iso {
-	return __PACKAGE__ -> new(shift,_prefformat())->output('iso');
+    return __PACKAGE__->new( shift, _prefformat() )->output('iso');
 }
 
 1;
@@ -192,6 +237,7 @@ The formats supported by Koha are:
     us - U.S. standard
     metric - European standard (slight misnomer, not really decimalized metric)
     sql - log format, not really for human consumption
+    rfc822 - Standard for using with RSS feeds, etc.
 
 =head2 ->new([string_date,][date_format])
 
@@ -200,19 +246,19 @@ used.  If date_format is not supplied, the system preference from C4::Context is
 
 Examples:
 
-		my $now   = C4::Dates->new();
-		my $date1 = C4::Dates->new("09-21-1989","us");
-		my $date2 = C4::Dates->new("19890921    143907","sql");
+        my $now   = C4::Dates->new();
+        my $date1 = C4::Dates->new("09-21-1989","us");
+        my $date2 = C4::Dates->new("19890921    143907","sql");
 
 =head2 ->output([date_format])
 
 The date value is stored independent of any specific format.  Therefore any format can be 
 invoked when displaying it. 
 
-		my $date = C4::Dates->new();    # say today is July 12th, 2010
-		print $date->output("iso");     # prints "2010-07-12"
-		print "\n";
-		print $date->output("metric");  # prints "12-07-2010"
+        my $date = C4::Dates->new();    # say today is July 12th, 2010
+        print $date->output("iso");     # prints "2010-07-12"
+        print "\n";
+        print $date->output("metric");  # prints "12-07-2010"
 
 However, it is still necessary to know the format of any incoming date value (e.g., 
 setting the value of an object with new()).  Like new(), output() assumes the system preference
@@ -228,32 +274,32 @@ method/function to tell you whether or not a Dates.pm object is of the 'iso' typ
 can see by this example that such a test is trivial to accomplish, and not necessary to 
 include in the module:
 
-		sub is_iso {
-			my $self = shift;
-			return ($self->format() eq "iso");
-		}
+        sub is_iso {
+            my $self = shift;
+            return ($self->format() eq "iso");
+        }
 
 Note: A similar function would need to be included for each format. 
 
 Instead a dependent script can retrieve the format of the object directly and decide what to
 do with it from there:
 
-		my $date = C4::Dates->new();
-		my $format = $date->format();
-		($format eq "iso") or do_something($date);
+        my $date = C4::Dates->new();
+        my $format = $date->format();
+        ($format eq "iso") or do_something($date);
 
 Or if you just want to print a given value and format, no problem:
 
-		my $date = C4::Dates->new("1989-09-21", "iso");
-		print $date->output;
+        my $date = C4::Dates->new("1989-09-21", "iso");
+        print $date->output;
 
 Alternatively:
 
-		print C4::Dates->new("1989-09-21", "iso")->output;
+        print C4::Dates->new("1989-09-21", "iso")->output;
 
 Or even:
 
-		print C4::Dates->new("21-09-1989", "metric")->output("iso");
+        print C4::Dates->new("21-09-1989", "metric")->output("iso");
 
 =head2 "syspref" -- System Preference(s)
 
@@ -263,24 +309,24 @@ psuedo-format argument "syspref".
 
 For example, to print an ISO date (from the database) in the <systempreference> format:
 
-		my $date = C4::Dates->new($date_from_database,"iso");
-		my $datestring_for_display = $date->output("syspref");
-		print $datestring_for_display;
+        my $date = C4::Dates->new($date_from_database,"iso");
+        my $datestring_for_display = $date->output("syspref");
+        print $datestring_for_display;
 
 Or even:
 
-		print C4::Dates->new($date_from_database,"iso")->output("syspref");
+        print C4::Dates->new($date_from_database,"iso")->output("syspref");
 
 If you just want to know what the <systempreferece> is, a default Dates object can tell you:
 
-		C4::Dates->new()->format();
+        C4::Dates->new()->format();
 
 =head2 ->DHMTLcalendar([date_format])
 
 Returns the format string for DHTML Calendar Display based on date_format.  
 If date_format is not supplied, the return is based on system preference.
 
-		C4::Dates->DHTMLcalendar();	#  e.g., returns "%m/%d/%Y" for 'us' system preference
+        C4::Dates->DHTMLcalendar(); #  e.g., returns "%m/%d/%Y" for 'us' system preference
 
 =head3 Error Handling
 
@@ -290,12 +336,12 @@ fatal error (because it is programmer error, not user error, typically).
 Scripts must still perform validation of user input.  Attempting to set an invalid value will 
 return 0 or undefined, so a script might check as follows:
 
-		my $date = C4::Dates->new($input) or deal_with_it("$input didn't work");
+        my $date = C4::Dates->new($input) or deal_with_it("$input didn't work");
 
 To validate before creating a new object, use the regexp method of the class:
 
-		$input =~ C4::Dates->regexp("iso") or deal_with_it("input ($input) invalid as iso format");
-		my $date = C4::Dates->new($input,"iso");
+        $input =~ C4::Dates->regexp("iso") or deal_with_it("input ($input) invalid as iso format");
+        my $date = C4::Dates->new($input,"iso");
 
 More verbose debugging messages are sent in the presence of non-zero $ENV{"DEBUG"}.
 
diff --git a/C4/Review.pm b/C4/Review.pm
index 0b7dbc3..f94dbc8 100644
--- a/C4/Review.pm
+++ b/C4/Review.pm
@@ -29,7 +29,7 @@ BEGIN {
 	$VERSION = 3.00;
 	require Exporter;
 	@ISA    = qw(Exporter);
-	@EXPORT = qw(getreview savereview updatereview numberofreviews
+	@EXPORT = qw(getreview savereview updatereview numberofreviews numberofreviewsbybiblionumber
 		getreviews getallreviews approvereview deletereview);
 }
 
@@ -91,6 +91,15 @@ sub updatereview {
 }
 
 sub numberofreviews {
+    my $dbh            = C4::Context->dbh;
+    my $query          =
+      "SELECT count(*) FROM reviews WHERE approved=?";
+    my $sth = $dbh->prepare($query);
+    $sth->execute( 1 );
+  return $sth->fetchrow;
+}
+
+sub numberofreviewsbybiblionumber {
     my ($biblionumber) = @_;
     my $dbh            = C4::Context->dbh;
     my $query          =
@@ -111,12 +120,13 @@ sub getreviews {
 }
 
 sub getallreviews {
-    my ($status) = @_;
+    my ($status, $offset, $row_count) = @_;
+    my @params = ($status,($offset ? $offset : 0),($row_count ? $row_count : 20));
     my $dbh      = C4::Context->dbh;
     my $query    =
-      "SELECT * FROM reviews WHERE approved=? order by datereviewed desc";
-    my $sth = $dbh->prepare($query);
-    $sth->execute($status);
+      "SELECT * FROM reviews WHERE approved=? order by datereviewed desc LIMIT ?, ?";
+    my $sth = $dbh->prepare($query) || warn $dbh->err_str;
+    $sth->execute(@params);
 	return $sth->fetchall_arrayref({});
 }
 
diff --git a/koha-tmpl/opac-tmpl/prog/en/css/opac.css b/koha-tmpl/opac-tmpl/prog/en/css/opac.css
index f47c8c2..1132ca6 100644
--- a/koha-tmpl/opac-tmpl/prog/en/css/opac.css
+++ b/koha-tmpl/opac-tmpl/prog/en/css/opac.css
@@ -1021,8 +1021,7 @@ a.cancel {
 
 .searchresults p {
 	margin: 0;
-	padding: 0;
-	padding-top : .6em;
+	padding: 0 0 .6em 0;
 }
 
 td.resultscontrol img {
@@ -1970,3 +1969,28 @@ div.ft {
 	list-style:disc outside url("../../images/item-bullet.gif");
 	padding:0.2em 0;
 }
+
+#recentcomments {
+	margin:auto;
+	max-width:750px;
+}
+
+.searchresults .commentline {
+	background-color : rgb(255, 255, 204);
+	background-color : rgba(255, 255, 204, 0.4);
+	border : 1px solid #CCC;
+	display: inline-block;
+	-webkit-border-radius: 4px;
+	-moz-border-radius: 4px;
+	border-radius: 4px;
+	-webkit-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
+	-moz-box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
+	box-shadow: 1px 1px 1px rgba(0, 0, 0, 0.2);
+	margin : .3em;
+	padding : .4em;
+}
+
+.searchresults .commentline.yours {
+	background-color : rgb(239, 254, 213);
+	background-color : rgba(239, 254, 213, 0.4);
+}
\ No newline at end of file
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews-rss.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews-rss.tmpl
new file mode 100644
index 0000000..1a81e2e
--- /dev/null
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews-rss.tmpl
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+<channel>
+     <title><![CDATA[<!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog Recent Comments]]></title>
+     <link><!-- TMPL_VAR NAME="OPACBaseURL" -->/cgi-bin/koha/opac-showreviews.pl&amp;format=rss2</link>
+     <description><![CDATA[ The most recent comments from <!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog. Comments can be made by logged in users and are moderated by library staff.]]></description>
+     <atom:link href="<!-- TMPL_VAR NAME="OPACBaseURL" -->/cgi-bin/koha/opac-showreviews.pl&amp;format=rss2" rel="self" type="application/rss+xml" />
+     <lastBuildDate><!-- TMPL_VAR NAME="timestamp" --></lastBuildDate>
+	 <!--TMPL_LOOP NAME="reviews"-->
+     <item>
+       <title>New comment on <!-- TMPL_VAR NAME="title" ESCAPE="html" --> <!-- TMPL_LOOP NAME="subtitle" -->, <!-- TMPL_VAR ESCAPE="HTML" NAME="subfield" --><!-- /TMPL_LOOP --></title>
+       <link><!-- TMPL_VAR NAME="OPACBaseURL" -->/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->#comments</link>
+       <description><![CDATA[
+<!-- TMPL_IF NAME="OPACAmazonEnabled" --><!-- TMPL_IF NAME="OPACAmazonCoverImages" --><!-- TMPL_IF NAME="normalized_isbn" --><img src="http://images.amazon.com/images/P/<!-- TMPL_VAR NAME="normalized_isbn" -->.01.TZZZZZZZ.jpg" alt="" /><!-- /TMPL_IF --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+
+<!-- TMPL_IF NAME="SyndeticsEnabled" --><!-- TMPL_IF NAME="SyndeticsCoverImages" --><!-- TMPL_IF NAME="content_identifier_exists" --><!-- TMPL_IF NAME="using_https" --><img src="https://secure.syndetics.com/index.aspx?isbn=<!-- TMPL_VAR NAME="normalized_isbn" -->/SC.GIF&amp;client=<!-- TMPL_VAR NAME="SyndeticsClientCode" -->&amp;type=xw10&amp;upc=<!-- TMPL_VAR NAME="normalized_upc" -->&amp;oclc=<!-- TMPL_VAR NAME="normalized_oclc" -->" alt="" />
+<!-- TMPL_ELSE -->
+<img src="http://www.syndetics.com/index.aspx?isbn=<!-- TMPL_VAR NAME="normalized_isbn" -->/SC.GIF&amp;client=<!-- TMPL_VAR NAME="SyndeticsClientCode" -->&amp;type=xw10&amp;upc=<!-- TMPL_VAR NAME="normalized_upc" -->&amp;oclc=<!-- TMPL_VAR NAME="normalized_oclc" -->" alt="" />
+<!-- /TMPL_IF --><!-- /TMPL_IF --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+
+<!-- TMPL_IF NAME="BakerTaylorEnabled" --><!-- TMPL_IF NAME="normalized_isbn" --><a href="https://<!-- TMPL_VAR name="BakerTaylorBookstoreURL" ESCAPE="HTML" --><!-- TMPL_VAR name="normalized_isbn" -->"><img alt="See Baker &amp; Taylor" src="<!-- TMPL_VAR name="BakerTaylorImageURL" ESCAPE="HTML" --><!-- TMPL_VAR name="normalized_isbn" -->" /></a><!-- /TMPL_IF --><!-- /TMPL_IF -->
+	   <!-- TMPL_IF NAME="author" --><p>By <!-- TMPL_VAR NAME="author"  ESCAPE="html" -->.</p> <!-- /TMPL_IF -->
+	   <p><!-- TMPL_IF name="place" --><!-- TMPL_VAR name="place"  ESCAPE="html" --> <!-- /TMPL_IF --><!-- TMPL_IF name="publishercode" --><!-- TMPL_VAR name="publishercode"  ESCAPE="html" --><!-- /TMPL_IF --><!-- TMPL_IF name="publicationyear" --> <!-- TMPL_VAR name="publicationyear"  ESCAPE="html" -->
+                    <!-- TMPL_ELSE --><!-- TMPL_IF name="copyrightdate" --> <!-- TMPL_VAR name="copyrightdate"  ESCAPE="html" --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+                        <!-- TMPL_IF name="pages" -->. <!-- TMPL_VAR name="pages"  ESCAPE="html" --><!-- /TMPL_IF -->
+                        <!-- TMPL_IF name="notes" -->, <!-- TMPL_VAR name="notes"  ESCAPE="html" --><!-- /TMPL_IF -->
+                        <!-- TMPL_IF name="size" --> <!-- TMPL_VAR name="size"  ESCAPE="html" -->. <!-- /TMPL_IF -->
+                        <!-- TMPL_IF name="isbn" --> <!-- TMPL_VAR name="isbn"  ESCAPE="html" --><!-- /TMPL_IF --> </p>
+<p><!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --> commented on <!-- TMPL_VAR NAME="datereviewed" -->: <!--TMPL_VAR NAME="review" ESCAPE="HTML"--></p>
+						]]></description>
+       <guid><!-- TMPL_VAR NAME="OPACBaseURL" -->/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->&amp;reviewid=<!-- TMPL_VAR NAME="reviewid" --></guid>
+       <pubDate><!-- TMPL_VAR NAME="timestamp" --></pubDate>
+     </item>
+	 <!-- /TMPL_LOOP -->
+   </channel>
+</rss>
\ No newline at end of file
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews.tmpl
index c8c7260..42ea224 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-showreviews.tmpl
@@ -1,39 +1,97 @@
-<!-- TMPL_INCLUDE name="doc-head-open.inc" --><!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog &rsaquo;   
+<!-- TMPL_INCLUDE name="doc-head-open.inc" --><!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog &rsaquo; Recent Comments
 <!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+<link rel="alternate" type="application/rss+xml" title="<!-- TMPL_IF NAME="LibraryNameTitle" --><!-- TMPL_VAR NAME="LibraryNameTitle" --><!-- TMPL_ELSE -->Koha Online<!-- /TMPL_IF --> Catalog Recent Comments" href="<!-- TMPL_VAR NAME="OPACBaseURL" -->/cgi-bin/koha/opac-showreviews.pl?format=rss" />
+<script type="text/javascript">
+//<![CDATA[
+$(document).ready(function(){
+    <!-- TMPL_IF NAME="GoogleJackets" -->KOHA.Google.GetCoverFromIsbn();<!-- /TMPL_IF -->
+});
+//]]>
+</script>
 </head>
 <body id="opac-showreviews">
-
-<!-- TMPL_INCLUDE name="masthead.inc" -->
-
-<div id="doc3" class="yui-t1">
+<!-- TMPL_IF EXPR="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="container">
-
+    <div id="recentcomments" class="searchresults">
+<h3>Recent comments</h3>
 <table>
     <!--TMPL_LOOP NAME="reviews"-->
-    <tr>
-        <th>
-                <b><!--TMPL_VAR NAME="title"--></b>
-        </th>
-    </tr>
-    <tr>
+    <!-- TMPL_UNLESS NAME="__odd__" --><tr class="highlight"><!-- TMPL_ELSE --><tr><!-- /TMPL_UNLESS -->
         <td>
-            <!--TMPL_VAR NAME="review" ESCAPE="HTML"-->
-            <p><!--TMPL_VAR NAME="datereviewed"--></p>
+
+<p><!-- TMPL_IF name="BiblioDefaultViewmarc" --><a class="title" href="/cgi-bin/koha/opac-MARCdetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->" title="View details for this title">
+    <!-- TMPL_ELSE -->
+    <!-- TMPL_IF name="BiblioDefaultViewisbd" --><a class="title" href="/cgi-bin/koha/opac-ISBDdetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->" title="View details for this title">
+    <!-- TMPL_ELSE --><a class="title" href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->#comments" title="View details for this title">
+    <!-- /TMPL_IF -->
+    <!-- /TMPL_IF -->
+    <!-- TMPL_IF NAME="title" --><!-- TMPL_VAR NAME="title" ESCAPE="html" --><!-- TMPL_ELSE -->No title<!-- /TMPL_IF --> <!-- TMPL_LOOP NAME="subtitle"  --> <!--TMPL_VAR Name="subfield"--><!--/TMPL_LOOP--></a>
+    <!-- TMPL_IF NAME="author" -->by <a href="/cgi-bin/koha/opac-search.pl?q=au:<!-- TMPL_VAR NAME="author" ESCAPE="URL" -->" title="Search for works by this author" class="author"><!-- TMPL_VAR NAME="author" --></a></p>
+    <!-- /TMPL_IF -->
+    <p>
+    <span class="results_summary"><span class="label">Publication:</span>
+            <!-- TMPL_IF name="place" --><!-- TMPL_VAR name="place" --> <!-- /TMPL_IF --><!-- TMPL_IF name="publishercode" --><!-- TMPL_VAR name="publishercode" --><!-- /TMPL_IF --><!-- TMPL_IF name="publicationyear" --> <!-- TMPL_VAR name="publicationyear" -->
+        <!-- TMPL_ELSE --><!-- TMPL_IF name="copyrightdate" --> <!-- TMPL_VAR name="copyrightdate" --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+            <!-- TMPL_IF name="pages" -->. <!-- TMPL_VAR name="pages" --><!-- /TMPL_IF -->
+            <!-- TMPL_IF name="notes" -->, <!-- TMPL_VAR name="notes" --><!-- /TMPL_IF -->
+            <!-- TMPL_IF name="size" --> <!-- TMPL_VAR name="size" --><!-- /TMPL_IF -->
+    </span>
+    <!-- TMPL_IF NAME="summary" -->
+    <span class="result_summary">
+        <!-- TMPL_VAR name="summary" -->
+    </span>
+    <!-- /TMPL_IF -->
+    <!-- TMPL_IF NAME="copyrightdate" --><span class="results_summary"><span class="label">Date:</span><!-- TMPL_VAR NAME="copyrightdate" --></span><!-- /TMPL_IF --></p>
+
+            <p class="commentline<!-- TMPL_IF NAME="your_comment" --> yours<!-- /TMPL_IF -->"><!--TMPL_VAR NAME="review" ESCAPE="HTML"-->
+            <span style="font-size:87%;font-color:#CCC;">Added <!--TMPL_VAR NAME="datereviewed"--> by <!-- TMPL_IF NAME="your_comment" --><strong>you</strong><!-- TMPL_ELSE --><!-- TMPL_VAR NAME="firstname" --> <!-- TMPL_VAR NAME="surname" --><!-- /TMPL_IF --></span></p>
+        </td>
+        <td>
+            <a class="p1" href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" -->">
+
+<!-- TMPL_IF name="BiblioDefaultViewmarc" --><a class="title" href="/cgi-bin/koha/opac-MARCdetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->" title="View details for this title">
+    <!-- TMPL_ELSE -->
+    <!-- TMPL_IF name="BiblioDefaultViewisbd" --><a class="title" href="/cgi-bin/koha/opac-ISBDdetail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->" title="View details for this title">
+    <!-- TMPL_ELSE --><a class="title" href="/cgi-bin/koha/opac-detail.pl?biblionumber=<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->#comments" title="View details for this title">
+    <!-- /TMPL_IF -->
+    <!-- /TMPL_IF -->
+
+
+            <!-- TMPL_IF NAME="OPACAmazonEnabled" --><!-- TMPL_IF NAME="OPACAmazonCoverImages" --><!-- TMPL_IF NAME="normalized_isbn" --><img src="http://images.amazon.com/images/P/<!-- TMPL_VAR NAME="normalized_isbn" -->.01.TZZZZZZZ.jpg" alt="" class="thumbnail" /><!-- TMPL_ELSE --><span class="no-image">No cover image available</span><!-- /TMPL_IF --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+
+            <!-- TMPL_IF NAME="SyndeticsEnabled" --><!-- TMPL_IF NAME="SyndeticsCoverImages" --><!-- TMPL_IF NAME="using_https" -->
+        <img src="https://secure.syndetics.com/index.aspx?isbn=<!-- TMPL_VAR NAME="normalized_isbn" -->/SC.GIF&amp;client=<!-- TMPL_VAR NAME="SyndeticsClientCode" -->&amp;type=xw10&amp;upc=<!-- TMPL_VAR NAME="normalized_upc" -->&amp;oclc=<!-- TMPL_VAR NAME="normalized_oclc" -->" alt="" class="thumbnail" />
+        <!--TMPL_ELSE -->
+        <img src="http://www.syndetics.com/index.aspx?isbn=<!-- TMPL_VAR NAME="normalized_isbn" -->/SC.GIF&amp;client=<!-- TMPL_VAR NAME="SyndeticsClientCode" -->&amp;type=xw10&amp;upc=<!-- TMPL_VAR NAME="normalized_upc" -->&amp;oclc=<!-- TMPL_VAR NAME="normalized_oclc" -->" alt="" class="thumbnail" /><!-- /TMPL_IF --><!-- /TMPL_IF --><!-- /TMPL_IF -->
+
+        <!-- TMPL_IF NAME="GoogleJackets" --><!-- TMPL_IF NAME="normalized_isbn" --><div style="block" title="<!-- TMPL_VAR NAME="biblionumber" ESCAPE="URL" -->" class="<!-- TMPL_VAR name="normalized_isbn" -->" id="gbs-thumbnail<!--TMPL_VAR NAME="__counter__"-->"></div><!-- TMPL_ELSE --><span class="no-image">No cover image available</span><!-- /TMPL_IF --><!-- /TMPL_IF -->
+        </a>
+        <!-- TMPL_IF NAME="BakerTaylorEnabled" --><!-- TMPL_IF NAME="normalized_isbn" --><a href="https://<!-- TMPL_VAR name="BakerTaylorBookstoreURL" ESCAPE="HTML" --><!-- TMPL_VAR name="normalized_isbn" -->"><img alt="See Baker &amp; Taylor" src="<!-- TMPL_VAR name="BakerTaylorImageURL" ESCAPE="HTML" --><!-- TMPL_VAR name="normalized_isbn" -->" /></a><!-- TMPL_ELSE --><span class="no-image">No cover image available</span><!-- /TMPL_IF --><!-- /TMPL_IF -->
         </td>
     </tr>
     <!--/TMPL_LOOP-->
 </table>
-
-</div>
+<!-- TMPL_IF NAME="PAGE_NUMBERS" --><div class="pages">
+    <!-- Row of numbers corresponding to showreviews result pages -->
+        <!-- TMPL_IF NAME="previous_page_offset" --><a class="nav" href="/cgi-bin/koha/opac-showreviews.pl?offset=<!-- TMPL_VAR NAME="previous_page_offset" -->">&lt;&lt; Previous</a>
+        <!-- TMPL_ELSE -->
+        <!-- TMPL_IF NAME="previous_page_first" --><a class="nav" href="/cgi-bin/koha/opac-showreviews.pl?offset=0">&lt;&lt; Previous</a><!-- /TMPL_IF -->
+        <!-- /TMPL_IF -->
+    <!-- TMPL_LOOP NAME="PAGE_NUMBERS" --><!-- TMPL_IF NAME="highlight" --><span class="current"><!-- TMPL_VAR NAME="pg" --></span><!-- TMPL_ELSE --><a class="nav" href="/cgi-bin/koha/opac-showreviews.pl?offset=<!-- TMPL_VAR NAME="offset" -->"><!-- TMPL_VAR NAME="pg" --></a><!-- /TMPL_IF -->
+    <!-- /TMPL_LOOP -->
+        <!-- TMPL_IF NAME="next_page_offset" --><a class="nav" href="/cgi-bin/koha/opac-showreviews.pl?offset=<!-- TMPL_VAR NAME="next_page_offset" -->">Next &gt;&gt;</a><!-- /TMPL_IF -->
+</div><!-- /TMPL_IF -->
 </div>
 </div>
-<div class="yui-b">
-<div class="container">
-<!--TMPL_INCLUDE NAME="navigation.inc" -->
-<!-- TMPL_INCLUDE name="usermenu.inc" -->
 </div>
 </div>
+<!-- TMPL_IF EXPR="OpacNav" -->
+<div class="yui-b"><div class="container">
+<!--TMPL_INCLUDE NAME="navigation.inc" -->
+</div></div>
+<!-- /TMPL_IF -->
 </div>
-<!-- TMPL_INCLUDE NAME="opac-bottom.inc" -->
+<!-- TMPL_INCLUDE NAME="opac-bottom.inc" -->
\ No newline at end of file
diff --git a/opac/opac-showreviews.pl b/opac/opac-showreviews.pl
index ac8343a..de39021 100755
--- a/opac/opac-showreviews.pl
+++ b/opac/opac-showreviews.pl
@@ -1,5 +1,8 @@
 #!/usr/bin/perl
 
+# Copyright 2000-2002 Katipo Communications
+# Parts copyright 2010 Nelsonville Public Library
+#
 # This file is part of Koha.
 #
 # Koha is free software; you can redistribute it and/or modify it under the
@@ -25,26 +28,135 @@ use C4::Output;
 use C4::Circulation;
 use C4::Review;
 use C4::Biblio;
+use C4::Dates qw/format_date/;
+use C4::Members qw/GetMemberDetails/;
+use POSIX qw(ceil strftime);
+
+my $template_name;
+my $query = new CGI;
+my $format = $query->param("format") || '';
+my $count = C4::Context->preference('OPACnumSearchResults') || 20;
+my $results_per_page = $query->param('count') || $count;
+my $offset = $query->param('offset') || 0;
+my $page = $query->param('page') || 1;
+$offset = ($page-1)*$results_per_page if $page>1;
 
-my $query        = new CGI;
-my $biblionumber = $query->param('biblionumber');
+if ($format eq "rss") {
+    $template_name = "opac-showreviews-rss.tmpl";
+} else {
+    $template_name = "opac-showreviews.tmpl",
+}
 
 my ( $template, $borrowernumber, $cookie ) = &get_template_and_user(
     {
-        template_name   => "opac-showreviews.tmpl",
+        template_name   => $template_name,
         query           => $query,
         type            => "opac",
         authnotrequired => 1,
     }
 );
 
-my $biblio  = GetBiblioData( $biblionumber );
-my $reviews = getreviews( $biblionumber, 1 );
+if($format eq "rss"){
+    my $lastbuilddate = C4::Dates->new();
+    my $lastbuilddate_output = $lastbuilddate->output("rfc822");
+    $template->param(
+        rss => 1,
+        timestamp => $lastbuilddate_output
+        );
+}
+
+my $reviews = getallreviews(1,$offset,$results_per_page);
+my $marcflavour      = C4::Context->preference("marcflavour");
+my $hits = numberofreviews();
+my $i = 0;
+my $latest_comment_date;
+for my $result (@$reviews){
+    my $biblionumber = $result->{biblionumber};
+	my $bib = &GetBiblioData($biblionumber);
+    my $record = GetMarcBiblio($biblionumber);
+    my $frameworkcode = GetFrameworkCode($biblionumber);
+	my ( $borr ) = GetMemberDetails( $result->{borrowernumber} );
+	$result->{normalized_upc} = GetNormalizedUPC($record,$marcflavour);
+	$result->{normalized_ean} = GetNormalizedEAN($record,$marcflavour);
+	$result->{normalized_oclc} = GetNormalizedOCLCNumber($record,$marcflavour);
+	$result->{normalized_isbn} = GetNormalizedISBN(undef,$record,$marcflavour);
+	$result->{title} = $bib->{'title'};
+	$result->{subtitle} = GetRecordValue('subtitle', $record, $frameworkcode);
+	$result->{author} = $bib->{'author'};
+	$result->{place} = $bib->{'place'};
+	$result->{publishercode} = $bib->{'publishercode'};
+	$result->{copyrightdate} = $bib->{'copyrightdate'};
+	$result->{pages} = $bib->{'pages'};
+	$result->{size} = $bib->{'size'};
+	$result->{notes} = $bib->{'notes'};
+	$result->{timestamp} = $bib->{'timestamp'};
+	$result->{firstname} = $borr->{'firstname'};
+	$result->{surname} = $borr->{'surname'};
+    if ($result->{borrowernumber} eq $borrowernumber) {
+		$result->{your_comment} = 1;
+	}
+
+    if($format eq "rss"){
+        my $rsstimestamp = C4::Dates->new($result->{datereviewed},"iso");
+        my $rsstimestamp_output = $rsstimestamp->output("rfc822");
+        $result->{timestamp} = $rsstimestamp_output;
+        $result->{datereviewed} = format_date($result->{datereviewed});
+    } else {
+        $result->{datereviewed} = format_date($result->{datereviewed});
+    }
+}
+## Build the page numbers on the bottom of the page
+            my @page_numbers;
+            my $previous_page_first;
+            my $previous_page_offset;
+            # total number of pages there will be
+            my $pages = ceil($hits / $results_per_page);
+            # default page number
+            my $current_page_number = 1;
+            $current_page_number = ($offset / $results_per_page + 1) if $offset;
+            if($offset - $results_per_page == 0){
+            	$previous_page_first = 1;
+            } elsif ($offset - $results_per_page > 0){
+            	$previous_page_offset = $offset - $results_per_page;
+            }
+            my $next_page_offset = $offset + $results_per_page;
+            # If we're within the first 10 pages, keep it simple
+            if ($current_page_number < 10) {
+                # just show the first 10 pages
+                # Loop through the pages
+                my $pages_to_show = 10;
+                $pages_to_show = $pages if $pages<10;
+                for ($i=1; $i<=$pages_to_show;$i++) {
+                    # the offset for this page
+                    my $this_offset = (($i*$results_per_page)-$results_per_page);
+                    # the page number for this page
+                    my $this_page_number = $i;
+                    # it should only be highlighted if it's the current page
+                    my $highlight = 1 if ($this_page_number == $current_page_number);
+                    # put it in the array
+                    push @page_numbers, { offset => $this_offset, pg => $this_page_number, highlight => $highlight };
+                                
+                }
+                        
+            }
+            # now, show twenty pages, with the current one smack in the middle
+            else {
+                for ($i=$current_page_number; $i<=($current_page_number + 20 );$i++) {
+                    my $this_offset = ((($i-9)*$results_per_page)-$results_per_page);
+                    my $this_page_number = $i-9;
+                    my $highlight = 1 if ($this_page_number == $current_page_number);
+                    if ($this_page_number <= $pages) {
+                        push @page_numbers, { offset => $this_offset, pg => $this_page_number, highlight => $highlight };
+                    }
+                }
+            }
+$template->param(   PAGE_NUMBERS => \@page_numbers,
+					previous_page_first => $previous_page_first,
+                    previous_page_offset => $previous_page_offset) unless $pages < 2;
+$template->param(next_page_offset => $next_page_offset) unless $pages eq $current_page_number;
 
 $template->param(
     reviews => $reviews,
-    title   => $biblio->{'title'},
 );
 
-output_html_with_http_headers $query, $cookie, $template->output;
-
+output_html_with_http_headers $query, $cookie, $template->output;
\ No newline at end of file
diff --git a/t/Dates.t b/t/Dates.t
index da6f377..148bb3e 100644
--- a/t/Dates.t
+++ b/t/Dates.t
@@ -3,44 +3,43 @@
 use strict;
 use warnings;
 
-use Test::More tests => 276;
+use Test::More tests => 327;
+
 BEGIN {
-	use FindBin;
-	use lib $FindBin::Bin;
-	use_ok('C4::Dates', qw(format_date format_date_in_iso));
+    use FindBin;
+    use lib $FindBin::Bin;
+    use_ok( 'C4::Dates', qw(format_date format_date_in_iso) );
 }
 
 sub describe ($$) {
-	my $front = sprintf("%-25s", shift);
-	my $tail = shift || 'FAILED';
-	return  "$front : $tail";
+    my $front = sprintf( "%-25s", shift );
+    my $tail = shift || 'FAILED';
+    return "$front : $tail";
 }
 
-# Keep the number of test elements per [array] equal or the predicted number of tests 
+# Keep the number of test elements per [array] equal or the predicted number of tests
 # needs to be different for different (fake) sysprefs.
 my %thash = (
-	  iso  => ['2001-1-1','1989-9-21','1952-1-0', '1989-9-21 13:46:02','2001-01-01','1989-09-21','1952-01-00', '1989-09-21 13:46:02'],
-	metric => ["1-1-2001",'21-9-1989','00-1-1952', '21-9-1989 13:46:02',"01-01-2001",'21-09-1989','00-01-1952', '21-09-1989 13:46:02'],
-	   us  => ["01-01-2001",'09-21-1989','01-00-1952', '09-21-1989 13:46:02'],
-	  sql  => ['20010101    010101',
-	  		   '19890921    143907',
-	  		   '19520100    000000',
-	  		   '19890921    134602'     ],
+    iso    => [ '2001-1-1',           '1989-9-21',          '1952-1-0',           '1989-9-21 13:46:02', '2001-01-01', '1989-09-21', '1952-01-00', '1989-09-21 13:46:02' ],
+    metric => [ "1-1-2001",           '21-9-1989',          '00-1-1952',          '21-9-1989 13:46:02', "01-01-2001", '21-09-1989', '00-01-1952', '21-09-1989 13:46:02' ],
+    us     => [ "01-01-2001",         '09-21-1989',         '01-00-1952',         '09-21-1989 13:46:02' ],
+    sql    => [ '20010101    010101', '19890921    143907', '19520100    000000', '19890921    134602' ],
+    rfc822 => [ 'Wed, 02 Oct 2002 15:00:00 +0200', 'Fri, 10 Sep 2010 08:00:00 +0500' ],
 );
 
-my ($date, $format, $today, $today0, $val, $re, $syspref);
-my @formats = sort keys %thash;
+my ( $date, $format, $today, $today0, $val, $re, $syspref );
+my @formats              = sort keys %thash;
 my $fake_syspref_default = 'us';
-my $fake_syspref = (@ARGV) ? shift : $ENV{KOHA_TEST_DATE_FORMAT};
+my $fake_syspref         = (@ARGV) ? shift : $ENV{KOHA_TEST_DATE_FORMAT};
 if ($fake_syspref) {
     diag "You asked for date format '$fake_syspref'.";
-    unless (scalar grep {/^$fake_syspref$/} @formats) {
+    unless ( scalar grep { /^$fake_syspref$/ } @formats ) {
         diag "Warning: Unkown date format '$fake_syspref', reverting to default '$fake_syspref_default'.";
         $fake_syspref = $fake_syspref_default;
     }
 }
 $fake_syspref or $fake_syspref = $fake_syspref_default;
-$C4::Dates::prefformat = $fake_syspref;     # So Dates doesn't have to ask the DB anything.
+$C4::Dates::prefformat = $fake_syspref;    # So Dates doesn't have to ask the DB anything.
 
 diag <<EndOfDiag;
 
@@ -56,57 +55,59 @@ Testing Legacy Functions: format_date and format_date_in_iso
 
 EndOfDiag
 
-ok($syspref = C4::Dates->new->format(),         "Your system preference is: $syspref");
+ok( $syspref = C4::Dates->new->format(), "Your system preference is: $syspref" );
 print "\n";
-foreach (@{$thash{'iso'}}) {
-	ok($val = format_date($_),                  "format_date('$_'): $val"            );
+foreach ( @{ $thash{'iso'} } ) {
+    ok( $val = format_date($_), "format_date('$_'): $val" );
 }
-foreach (@{$thash{$syspref}}) {
-	ok($val = format_date_in_iso($_),           "format_date_in_iso('$_'): $val"     );
+foreach ( @{ $thash{$syspref} } ) {
+    ok( $val = format_date_in_iso($_), "format_date_in_iso('$_'): $val" );
 }
-ok($today0 = C4::Dates->today(),                "(default) CLASS ->today : $today0" );
+ok( $today0 = C4::Dates->today(), "(default) CLASS ->today : $today0" );
 diag "\nTesting " . scalar(@formats) . " formats.\nTesting no input (defaults):\n";
 print "\n";
 foreach (@formats) {
-	my $pre = sprintf '(%-6s)', $_;
-	ok($date = C4::Dates->new(),                "$pre Date Creation   : new()");
-	ok($_ eq ($format = $date->format($_)),     "$pre format($_)      : " . ($format|| 'FAILED') );
-	ok($format = $date->visual(),  				"$pre visual()        : " . ($format|| 'FAILED') );
-	ok($today  = $date->output(),               "$pre output()        : " . ($today || 'FAILED') );
-	ok($today  = $date->today(),                "$pre object->today   : " . ($today || 'FAILED') );
-	print "\n";
+    my $pre = sprintf '(%-6s)', $_;
+    ok( $date = C4::Dates->new(), "$pre Date Creation   : new()" );
+    ok( $_ eq ( $format = $date->format($_) ), "$pre format($_)      : " . ( $format || 'FAILED' ) );
+    ok( $format = $date->visual(), "$pre visual()        : " . ( $format || 'FAILED' ) );
+    ok( $today  = $date->output(), "$pre output()        : " . ( $today  || 'FAILED' ) );
+    ok( $today  = $date->today(),  "$pre object->today   : " . ( $today  || 'FAILED' ) );
+    print "\n";
 }
 
 diag "\nTesting with valid inputs:\n";
 foreach $format (@formats) {
-	my $pre = sprintf '(%-6s)', $format;
-  foreach my $testval (@{$thash{ $format }}) {
-	ok($date = C4::Dates->new($testval,$format),         "$pre Date Creation   : new('$testval','$format')");
-	ok($re   = $date->regexp,                            "$pre has regexp()" );
-	ok($testval =~ /^$re$/,                              "$pre has regexp() match $testval");
-	ok($val  = $date->output(),                 describe("$pre output()", $val) );
-    SKIP: {
-        skip("special case with explicit regexp('syspref') because $format isn't $syspref", 1) unless ($format eq $syspref);
-        my $re_syspref = C4::Dates->regexp('syspref');
-        ok($testval =~ /^$re_syspref$/,                  "$pre has regexp('syspref') match $testval");
+    my $pre = sprintf '(%-6s)', $format;
+    foreach my $testval ( @{ $thash{$format} } ) {
+        ok( $date = C4::Dates->new( $testval, $format ), "$pre Date Creation   : new('$testval','$format')" );
+        ok( $re = $date->regexp, "$pre has regexp()" );
+        ok( $testval =~ /^$re$/, "$pre has regexp() match $testval" );
+        ok( $val = $date->output(), describe( "$pre output()", $val ) );
+      SKIP: {
+            skip( "special case with explicit regexp('syspref') because $format isn't $syspref", 1 ) unless ( $format eq $syspref );
+            my $re_syspref = C4::Dates->regexp('syspref');
+            ok( $testval =~ /^$re_syspref$/, "$pre has regexp('syspref') match $testval" );
+        }
+        foreach ( grep { !/$format/ } @formats ) {
+            ok( $today = $date->output($_), describe( sprintf( "$pre output(%8s)", "'$_'" ), $today ) );
+        }
+        ok( $today = $date->today(), describe( "$pre object->today", $today ) );
+
+        # ok($today == ($today = C4::Dates->today()), "$pre CLASS ->today   : $today" );
+        ok( $val = $date->output(), describe( "$pre output()", $val ) );
+
+        # ok($format eq ($format = $date->format()),  "$pre format()        : $format" );
+        print "\n";
     }
-	foreach (grep {!/$format/} @formats) {
-		ok($today = $date->output($_),          describe(sprintf("$pre output(%8s)","'$_'"), $today) );
-	}
-	ok($today  = $date->today(),                describe("$pre object->today", $today) );
-	# ok($today == ($today = C4::Dates->today()), "$pre CLASS ->today   : $today" );
-	ok($val  = $date->output(),                 describe("$pre output()", $val) );
-	# ok($format eq ($format = $date->format()),  "$pre format()        : $format" );
-	print "\n";
-  }
 }
 
 diag "\nTesting object independence from class\n";
-my $in1 = '12/25/1952';	# us
-my $in2 = '13/01/2001'; # metric
-my $d1 = C4::Dates->new($in1, 'us');
-my $d2 = C4::Dates->new($in2, 'metric');
+my $in1  = '12/25/1952';                       # us
+my $in2  = '13/01/2001';                       # metric
+my $d1   = C4::Dates->new( $in1, 'us' );
+my $d2   = C4::Dates->new( $in2, 'metric' );
 my $out1 = $d1->output('iso');
 my $out2 = $d2->output('iso');
-ok($out1 ne $out2,                             "subsequent constructors get different dataspace ($out1 != $out2)");
+ok( $out1 ne $out2, "subsequent constructors get different dataspace ($out1 != $out2)" );
 diag "done.\n";
-- 
1.7.1



More information about the Koha-patches mailing list