File Coverage

blib/lib/XML/Feed/Format/RSS.pm
Criterion Covered Total %
statement 16 18 88.8
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 22 24 91.6


line stmt bran cond sub pod time code
1             package XML::Feed::Format::RSS;
2 28     28   44422 use strict;
  28         56  
  28         863  
3 28     28   131 use warnings;
  28         53  
  28         1230  
4              
5             our $VERSION = '0.53';
6              
7 28     28   188 use base qw( XML::Feed );
  28         58  
  28         2682  
8 28     28   23535 use DateTime::Format::Mail;
  28         3323819  
  28         1082  
9 28     28   22281 use DateTime::Format::W3CDTF;
  28         21908  
  28         942  
10 28     28   21630 use XML::Atom::Util qw(iso2dt);
  0            
  0            
11             use XML::Feed::Enclosure;
12             use XML::Feed::Entry::Format::RSS;
13              
14             our $PREFERRED_PARSER = "XML::RSS";
15              
16              
17             sub identify {
18             my $class = shift;
19             my $xml = shift;
20             my $tag = $class->_get_first_tag($xml);
21             return ($tag eq 'rss' || $tag eq 'RDF');
22             }
23              
24             sub init_empty {
25             my ($feed, %args) = @_;
26             $args{'version'} ||= '2.0';
27             eval "use $PREFERRED_PARSER"; die $@ if $@;
28             $feed->{rss} = $PREFERRED_PARSER->new(%args);
29             $feed->{rss}->add_module(prefix => "content", uri => 'http://purl.org/rss/1.0/modules/content/');
30             $feed->{rss}->add_module(prefix => "dcterms", uri => 'http://purl.org/dc/terms/');
31             $feed->{rss}->add_module(prefix => "atom", uri => 'http://www.w3.org/2005/Atom');
32             $feed->{rss}->add_module(prefix => "geo", uri => 'http://www.w3.org/2003/01/geo/wgs84_pos#');
33             $feed;
34             }
35              
36             sub init_string {
37             my $feed = shift;
38             my($str) = @_;
39             $feed->init_empty;
40             my $opts = {
41             hashrefs_instead_of_strings => 1,
42             };
43             $opts->{allow_multiple} = [ 'enclosure' ] if $XML::Feed::MULTIPLE_ENCLOSURES;
44             if ($str) {
45             $feed->{rss}->parse($$str, $opts );
46             }
47             $feed;
48             }
49              
50             sub format { 'RSS ' . $_[0]->{rss}->{'version'} }
51              
52             ## The following elements are the same in all versions of RSS.
53             sub title { shift->{rss}->channel('title', @_) }
54             sub link {
55             my $link = shift->{rss}->channel('link', @_);
56             $link =~ s/^\s+//;
57             $link =~ s/\s+$//;
58             return $link;
59             }
60             sub description { shift->{rss}->channel('description', @_) }
61             sub updated { shift->modified(@_) }
62              
63             # This doesn't exist in RSS
64             sub id { }
65              
66             ## This is RSS 2.0 only--what's the equivalent in RSS 1.0?
67             sub copyright { shift->{rss}->channel('copyright', @_) }
68              
69             sub base {
70             my $feed = shift;
71             if (@_) {
72             $feed->{rss}->{'xml:base'} = $_[0];
73             } else {
74             $feed->{rss}->{'xml:base'};
75             }
76             }
77              
78             ## The following all work transparently in any RSS version.
79             sub language {
80             my $feed = shift;
81             if (@_) {
82             $feed->{rss}->channel('language', $_[0]);
83             $feed->{rss}->channel->{dc}{language} = $_[0];
84             } else {
85             $feed->{rss}->channel('language') ||
86             $feed->{rss}->channel->{dc}{language};
87             }
88             }
89              
90             sub self_link {
91             my $feed = shift;
92              
93             if (@_) {
94             my $uri = shift;
95              
96             $feed->{rss}->channel->{'atom'}{'link'} =
97             {
98             rel => "self",
99             href => $uri,
100             type => "application/rss+xml",
101             };
102             }
103              
104             return $feed->{rss}->channel->{'atom'}{'link'};
105             }
106              
107             # This doesn't exist in RSS
108             sub first_link { };
109             sub last_link { };
110             sub previous_link { };
111             sub next_link { };
112             sub current_link { };
113             sub prev_archive_link { };
114             sub next_archive_link { };
115              
116             sub generator {
117             my $feed = shift;
118             if (@_) {
119             $feed->{rss}->channel('generator', $_[0]);
120             $feed->{rss}->channel->{'http://webns.net/mvcb/'}{generatorAgent} =
121             $_[0];
122             } else {
123             $feed->{rss}->channel('generator') ||
124             $feed->{rss}->channel->{'http://webns.net/mvcb/'}{generatorAgent};
125             }
126             }
127              
128             sub author {
129             my $feed = shift;
130             if (@_) {
131             $feed->{rss}->channel('webMaster', $_[0]);
132             $feed->{rss}->channel->{dc}{creator} = $_[0];
133             } else {
134             $feed->{rss}->channel('webMaster') ||
135             $feed->{rss}->channel->{dc}{creator};
136             }
137             }
138              
139             sub modified {
140             my $rss = shift->{rss};
141             if (@_) {
142             $rss->channel('pubDate',
143             DateTime::Format::Mail->format_datetime($_[0]));
144             ## XML::RSS is so weird... if I set this, it will try to use
145             ## the value for the lastBuildDate, which I don't want--because
146             ## this date is formatted for an RSS 1.0 feed. So it's commented out.
147             #$rss->channel->{dc}{date} =
148             # DateTime::Format::W3CDTF->format_datetime($_[0]);
149             } else {
150             my $date;
151             eval {
152             if (my $ts = $rss->channel('pubDate')) {
153             $ts =~ s/^\s+//;
154             $ts =~ s/\s+$//;
155             $date = DateTime::Format::Mail->parse_datetime($ts);
156             } elsif ($ts = $rss->channel->{dc}{date}) {
157             $ts =~ s/^\s+//;
158             $ts =~ s/\s+$//;
159             $date = DateTime::Format::W3CDTF->parse_datetime($ts);
160             }
161             };
162             return $date;
163             }
164             }
165              
166             sub image {
167             my $self = shift;
168             my $rss = $self->{rss};
169              
170             return @_ ? $rss->image(@_) : $rss->image('url');
171             }
172              
173             sub entries {
174             my $rss = $_[0]->{rss};
175             my @entries;
176             for my $item (@{ $rss->{items} }) {
177             push @entries, XML::Feed::Entry::Format::RSS->wrap($item);
178             $entries[-1]->{_version} = $rss->{'version'};
179             }
180             @entries;
181             }
182              
183             sub add_entry {
184             my $feed = shift;
185             my $entry = shift || return;
186             $entry = $feed->_convert_entry($entry);
187             $feed->{rss}->add_item(%{ $entry->unwrap });
188             }
189              
190             sub as_xml { $_[0]->{rss}->as_string }
191              
192             1;
193