Add support for RFC 5005 Feed Paging and Archiving in Atom feeds
Jakob Voss [Tue, 10 Apr 2012 13:19:49 +0000 (15:19 +0200)]
Changes
lib/XML/Feed.pm
lib/XML/Feed/Format/Atom.pm
lib/XML/Feed/Format/RSS.pm
t/02-create.t

diff --git a/Changes b/Changes
index ed4a431..3870079 100644 (file)
--- a/Changes
+++ b/Changes
@@ -1,3 +1,7 @@
+2012-04-10  Jakob Voss <voss@gbv.de>
+
+  * Add support for RFC 5005 Feed Paging and Archiving in Atom feeds
+
 2012-04-05  Dave Cross <dave@dave.org.uk>
 
   * lib/XML/Feed.pm: Remove svn tag.
index e131a82..6f3ae01 100644 (file)
@@ -167,6 +167,15 @@ sub id;
 sub tagline { shift->description(@_) }
 sub items   { $_[0]->entries     }
 
+# RFC 5005
+sub first_link;
+sub last_link;
+sub previous_link;
+sub next_link;
+sub current_link;
+sub prev_archive_link;
+sub next_archive_link;
+
 1;
 __END__
 
@@ -350,6 +359,36 @@ object in the correct format for the feed.
 Returns an XML representation of the feed, in the format determined by
 the current format of the I<$feed> object.
 
+=head2 $feed->first_link ([ $uri ])
+
+The Atom First-link for feed paging and archiving (RFC 5005).
+
+L<http://tools.ietf.org/html/rfc5005>
+
+=head2 $feed->last_link ([ $uri ])
+
+The Atom Last-link for feed paging and archiving.
+
+=head2 $feed->next_link ([ $uri ])
+
+The Atom Next-link for feed paging and archiving.
+
+=head2 $feed->previous_link ([ $uri ])
+
+The Atom Previous-link for feed paging and archiving.
+
+=head2 $feed->current_link ([ $uri ])
+
+The Atom Current-link for feed paging and archiving.
+
+=head2 $feed->next_archive_link ([ $uri ])
+
+The Atom Next-link for feed paging and archiving.
+
+=head2 $feed->prev_archive_link ([ $uri ])
+
+The Atom Prev-Archive-link for feed paging and archiving.
+
 =head1 PACKAGE VARIABLES
 
 =over 4
index 37bab42..0a38ed6 100644 (file)
@@ -56,25 +56,43 @@ sub link {
     }
 }
 
-sub self_link {
+sub _rel_link {
     my $feed = shift;
+    my $rel  = shift;
     if (@_) {
         my $uri = shift;
-        $feed->{atom}->add_link({type => "application/atom+xml", rel => "self", href => $uri});
+        $feed->{atom}->add_link({type => "application/atom+xml", rel => $rel, href => $uri});
         return $uri;
     } 
     else
     {
-        my $l =
-            first
-            { !defined $_->rel || $_->rel eq 'self' }
-            $feed->{atom}->link;
-            ;
+        my $l;
+
+        if ($rel eq 'self') {
+            $l = first
+                { !defined $_->rel || $_->rel eq 'self' }
+                $feed->{atom}->link;
+                ;
+        } else {
+            $l = first
+                { !defined $_->rel || $_->rel eq $rel }
+                $feed->{atom}->link;
+                ;
+        }
 
         return $l ? $l->href : undef;
     }
 }
 
+sub self_link   { shift->_rel_link( 'self', @_ ) }
+sub first_link  { shift->_rel_link( 'first', @_ ) }
+sub last_link   { shift->_rel_link( 'last', @_ ) }
+sub next_link   { shift->_rel_link( 'next', @_ ) }
+sub previous_link     { shift->_rel_link( 'previous', @_ ) };
+sub current_link      { shift->_rel_link( 'current', @_ ) }
+sub prev_archive_link { shift->_rel_link( 'prev-archive', @_ ) }
+sub next_archive_link { shift->_rel_link( 'next-archive', @_ ) }
+
 sub description { shift->{atom}->tagline(@_) }
 sub copyright   { shift->{atom}->copyright(@_) }
 sub language    { shift->{atom}->language(@_) }
index 3a589c9..50f2439 100644 (file)
@@ -103,6 +103,14 @@ sub self_link {
     return $feed->{rss}->channel->{'atom'}{'link'};
 }
 
+# This doesn't exist in RSS
+sub first_link { };
+sub last_link { };
+sub previous_link { };
+sub next_link { };
+sub current_link { };
+sub prev_archive_link { };
+sub next_archive_link { };
 
 sub generator {
     my $feed = shift;
index 776565c..e5fdb18 100644 (file)
@@ -91,6 +91,24 @@ for my $format (qw( Atom RSS )) {
     {
         like ($feed->as_xml(), qr{\Q<link rel="self" href="http://tor.tld/my-feed.rss" type="application/atom+xml"/>\E},
             "Feed contains the atom:link");
+
+        my %rfc5005 = (
+            first_link => "http://tor.tld/my-feed.xml?page=1",
+            next_link  => "http://tor.tld/my-feed.xml?page=4",
+            previous_link  => "http://tor.tld/my-feed.xml?page=2",
+            last_link  => "http://tor.tld/my-feed.xml?page=99",
+            current_link  => "http://tor.tld/archive/2.xml",
+            prev_archive_link  => "http://tor.tld/archive/1.xml",
+            next_archive_link  => "http://tor.tld/archive/3.xml",
+        );
+
+        while ( my($name,$url) = each(%rfc5005) ) {
+            $feed->$name($url);
+            $name =~ s/_link$//;
+            $name =~ s/_/-/g; 
+            like ($feed->as_xml(), qr{\Q<link rel="$name" href="$url" type="application/atom+xml"/>\E},
+                "Feed contains an RFC 5005 rel=\"$name\" link");
+        }
     }
 
 }