File Coverage

blib/lib/WWW/CPANRatings/RSS.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package WWW::CPANRatings::RSS;
2              
3 1     1   99320 use warnings;
  1         2  
  1         27  
4 1     1   4 use strict;
  1         1  
  1         40  
5              
6             our $VERSION = '0.0307';
7              
8              
9 1     1   391 use XML::Simple;
  0            
  0            
10             use LWP::UserAgent;
11             use Storable qw/lock_retrieve lock_store/;
12              
13             use base 'Class::Data::Accessor';
14             __PACKAGE__->mk_classaccessors (qw/
15             error
16             ua
17             ratings
18             ratings_unique
19             /);
20              
21             sub new {
22             my $class = shift;
23             my %args = @_;
24             $args{ua}{timeout} ||= 30;
25              
26             my $self = bless {}, $class;
27              
28             $self->ua( LWP::UserAgent->new( %{ $args{ua} || {} } ) );
29              
30             return $self;
31             }
32              
33             sub fetch {
34             my $self = shift;
35              
36             $self->$_(undef)
37             for qw/error ratings/;
38              
39             my $response = $self->ua->get('http://cpanratings.perl.org/index.rss');
40             unless ( $response->is_success ) {
41             $self->error( 'Network error: ' . $response->status_line );
42             return;
43             }
44              
45             my $feed;
46             # calling XMLin caused warnings to print out on my system....
47             # YES OMG!! LOOOK AT THIS!!1oneone ^_^
48             {
49             local *STDERR;
50             open STDERR, '>', \my $crap;
51             $feed = XMLin( $response->content );
52             }
53              
54             my @ratings;
55             for my $item ( @{ $feed->{item} || [] } ) {
56             my ( $rating, $comment ) = $item->{description}
57             =~ /Rating: \s* ([\d.]+) \s* stars \s* (.+)/sx;
58              
59             $rating = 'N/A'
60             unless defined $rating;
61              
62             $comment = $item->{description}
63             unless defined $comment;
64              
65             push @ratings, {
66             creator => $item->{'dc:creator'},
67             link => $item->{link},
68             dist => $item->{title},
69             comment => $comment,
70             rating => $rating,
71             };
72             }
73              
74             return $self->ratings( \@ratings );
75             }
76              
77             sub fetch_unique {
78             my ( $self, $file ) = @_;
79              
80             $self->ratings_unique(undef);
81            
82             unless ( defined $file ) {
83             $file = 'cpan_ratings.rss.storable';
84             }
85              
86             my $old_ratings_ref;
87             eval {
88             $old_ratings_ref = lock_retrieve( $file );
89             };
90              
91             $old_ratings_ref ||= [];
92              
93             my $ratings_ref = $self->fetch
94             or return; # error will be set by fetch();
95              
96             my %existing = map { $_->{link} => 1 } @$old_ratings_ref;
97              
98             my @new_ratings;
99             for ( reverse @$ratings_ref ) {
100             next if exists $existing{ $_->{link} };
101             unshift @new_ratings, {%$_};
102             };
103              
104             unshift @$old_ratings_ref, @new_ratings;
105             @$old_ratings_ref = splice @$old_ratings_ref, 0, 60;
106              
107             eval {
108             lock_store($old_ratings_ref, $file);
109             };
110             if ( $@ ) {
111             $self->error("Error with file [$file] [$@]");
112             return;
113             }
114              
115             return $self->ratings_unique( \@new_ratings );
116             }
117              
118             1;
119             __END__