File Coverage

blib/lib/WWW/Noss/FeedReader/RSS.pm
Criterion Covered Total %
statement 92 98 93.8
branch 50 60 83.3
condition 6 15 40.0
subroutine 11 11 100.0
pod 0 1 0.0
total 159 185 85.9


line stmt bran cond sub pod time code
1             package WWW::Noss::FeedReader::RSS;
2 5     5   90 use 5.016;
  5         19  
3 5     5   31 use strict;
  5         12  
  5         181  
4 5     5   37 use warnings;
  5         9  
  5         421  
5             our $VERSION = '2.02';
6              
7 5     5   30 use WWW::Noss::FeedReader::MediaRSS qw(parse_media_node);
  5         12  
  5         365  
8 5     5   48 use WWW::Noss::Timestamp;
  5         10  
  5         7624  
9              
10             sub _title {
11              
12 9     9   19 my ($node) = @_;
13              
14 9         19 my ($title, $display);
15 9         39 $title = $node->textContent;
16 9         18 $display = $title;
17 9         101 $display =~ s/\s+/ /g;
18 9         64 $display =~ s/^\s+|\s+$//g;
19              
20 9 100       41 return wantarray ? ($title, $display) : $title;
21              
22             }
23              
24             sub _time {
25              
26 11     11   23 my ($node) = @_;
27              
28 11         74 return WWW::Noss::Timestamp->mail($node->textContent);
29              
30             }
31              
32             sub _image {
33              
34 2     2   6 my ($node) = @_;
35              
36 2         10 my ($url) = grep { $_->nodeName eq 'url' } $node->childNodes;
  14         104  
37              
38 2 50       11 return undef unless defined $url;
39              
40 2         134 return $url->textContent;
41              
42             }
43              
44             sub _skip {
45              
46 4     4   10 my ($node, $time) = @_;
47              
48             my @items =
49 16         51 map { $_->textContent }
50 4         21 grep { $_->nodeName eq $time }
  36         154  
51             $node->childNodes;
52              
53 4 50       32 return @items ? \@items : undef;
54              
55             }
56              
57             sub _read_entry {
58              
59 9     9   18 my ($node) = @_;
60              
61 9         91 my $entry = {
62             nossid => undef,
63             status => undef,
64             feed => undef,
65             title => undef,
66             link => undef,
67             author => undef,
68             category => undef,
69             summary => undef,
70             published => undef,
71             updated => undef,
72             uid => undef,
73             };
74              
75 9         26 for my $n ($node->childNodes) {
76              
77 163         1029 my $name = $n->nodeName;
78              
79 163 100       712 if ($name =~ /^media:/) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
80 5         14 my $c = parse_media_node($n);
81 5         11 for my $k (keys %$c) {
82 14 100       29 if (ref $c->{ $k } eq 'ARRAY') {
83 2         3 push @{ $entry->{ $k } }, @{ $c->{ $k } };
  2         4  
  2         7  
84             } else {
85 12   66     36 $entry->{ $k } //= $c->{ $k };
86             }
87             }
88             } elsif ($name eq 'title') {
89 7         40 @{ $entry }{ qw(title displaytitle) } = _title($n);
  7         26  
90             } elsif ($name eq 'link') {
91 7         30 $entry->{ link } = $n->textContent;
92             } elsif ($name eq 'description') {
93 7         26 $entry->{ summary } = $n->textContent;
94             } elsif ($name eq 'author') {
95 9         32 $entry->{ author } = $n->textContent;
96             } elsif ($name eq 'category') {
97 24         66 push @{ $entry->{ category } }, $n->textContent;
  24         84  
98             } elsif ($name eq 'guid') {
99 9         29 $entry->{ uid } = $n->textContent;
100             } elsif ($name eq 'pubDate') {
101 9         25 $entry->{ published } = _time($n);
102             }
103              
104             }
105              
106 9 0 33     48 if (not defined $entry->{ title } and not defined $entry->{ summary }) {
107 0         0 return undef;
108             }
109              
110 9         685 return $entry;
111              
112             }
113              
114             sub read_feed {
115              
116 3     3 0 11 my ($class, $feed, $dom) = @_;
117              
118 3         17 my $channel = {
119             nossname => $feed->name,
120             nosslink => $feed->feed,
121             title => undef,
122             link => undef,
123             description => undef,
124             updated => undef,
125             author => undef,
126             category => undef,
127             generator => undef,
128             image => undef,
129             rights => undef,
130             skiphours => undef,
131             skipdays => undef,
132             };
133              
134 3         8 my $entries = [];
135              
136 3         8 my @entry_nodes;
137              
138             my ($channel_node) =
139 3         40 grep { $_->nodeName eq 'channel' }
  9         115  
140             $dom->documentElement->childNodes;
141              
142 3 50       28 unless (defined $channel_node) {
143 0         0 die sprintf "%s is not a valid RSS feed\n", $feed->name;
144             }
145              
146 3         161 for my $n ($channel_node->childNodes) {
147              
148 69         676 my $name = $n->nodeName;
149              
150 69 100       371 if ($name eq 'item') {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
151 9         20 push @entry_nodes, $n;
152             } elsif ($name eq 'title') {
153 2         10 $channel->{ title } = _title($n);
154             } elsif ($name eq 'link') {
155 2         35 $channel->{ link } = $n->textContent;
156             } elsif ($name eq 'description') {
157 2         11 $channel->{ description } = $n->textContent;
158             } elsif ($name eq 'copyright') {
159 2         11 $channel->{ rights } = $n->textContent;
160             } elsif ($name eq 'lastBuildDate') {
161 2         7 $channel->{ updated } = _time($n);
162             } elsif ($name eq 'category') {
163 6         13 push @{ $channel->{ category } }, $n->textContent;
  6         27  
164             } elsif ($name eq 'generator') {
165 2         12 $channel->{ generator } = $n->textContent;
166             } elsif ($name eq 'image') {
167 2         8 $channel->{ image } = _image($n);
168             } elsif ($name eq 'skipHours') {
169 2         10 $channel->{ skiphours } = _skip($n, 'hour');
170             } elsif ($name eq 'skipDays') {
171 2         6 $channel->{ skipdays } = _skip($n, 'day');
172             }
173              
174             }
175              
176 3         14 for my $n (@entry_nodes) {
177 9         229 my $e = _read_entry($n);
178 9 50       23 next unless defined $e;
179 9         22 $e->{ feed } = $channel->{ nossname };
180 9         26 push @$entries, $e;
181             }
182              
183 3 50       12 unless (@$entries) {
184 0         0 die sprintf "%s does not contain any posts\n";
185             }
186              
187             @$entries =
188 9         20 map { $_->[1] }
189             sort {
190 9   33     28 my $at = $a->[1]{ published } // $a->[1]{ updated };
191 9   33     24 my $bt = $b->[1]{ published } // $b->[1]{ updated };
192 9 50 33     37 if (not defined $at and not defined $bt) {
    50          
    50          
193 0         0 $a->[0] <=> $b->[0];
194             } elsif (not defined $at) {
195 0         0 -1;
196             } elsif (not defined $bt) {
197 0         0 1;
198             } else {
199 9         26 $at <=> $bt;
200             }
201             }
202 3         16 map { [ $_, $entries->[$_] ] }
  9         36  
203             0 .. $#$entries;
204              
205 3         57 return ($channel, $entries);
206              
207             }
208              
209             1;
210              
211             # vim: expandtab shiftwidth=4