File Coverage

lib/CPAN/Testers/WWW/Reports/Query/AJAX.pm
Criterion Covered Total %
statement 9 89 10.1
branch 0 28 0.0
condition 0 11 0.0
subroutine 3 20 15.0
pod 14 14 100.0
total 26 162 16.0


line stmt bran cond sub pod time code
1             package CPAN::Testers::WWW::Reports::Query::AJAX;
2              
3 7     7   107971 use strict;
  7         14  
  7         303  
4 7     7   29 use warnings;
  7         9  
  7         406  
5              
6             our $VERSION = '0.09';
7            
8             #----------------------------------------------------------------------------
9              
10             =head1 NAME
11              
12             CPAN::Testers::WWW::Reports::Query::AJAX - Get specific CPAN Testers results
13              
14             =head1 SYNOPSIS
15            
16             my $query = CPAN::Testers::WWW::Reports::Query::AJAX->new(
17             dist => 'App-Maisha',
18             version => '0.12', # optional, will default to latest version
19             );
20              
21             # basic results
22             printf "ALL: %d\n" .
23             "PASS: %d\n" .
24             "FAIL: %d\n" .
25             "NA: %d\n" .
26             "UNKNOWN: %d\n" .
27             "%age PASS: %d\n" .
28             "%age FAIL: %d\n" .
29             "%age NA: %d\n" .
30             "%age UNKNOWN: %d\n",
31              
32             $query->all,
33             $query->pass,
34             $query->fail,
35             $query->na,
36             $query->unknown,
37             $query->pc_pass,
38             $query->pc_fail,
39             $query->pc_na,
40             $query->pc_unknown;
41              
42             # get the raw data for all results, or a specific version if supplied
43             my $data = $query->raw;
44              
45             # basic filters (see new() for details)
46             my $query = CPAN::Testers::WWW::Reports::Query::AJAX->new(
47             dist => 'App-Maisha',
48             version => '0.12',
49             osname => 'Win32',
50             patches => 1,
51             perlmat => 1,
52             perlver => '5.10.0',
53             format => 'xml' # xml is default, text also supported
54             );
55              
56             printf "Win32 PASS: %d\n", $query->pass;
57              
58             =head1 DESCRIPTION
59            
60             This module queries the CPAN Testers website (via the AJAX interface) and
61             retrieves a simple data set of results. It then parses these to answer a few
62             simple questions.
63            
64             =cut
65            
66             #----------------------------------------------------------------------------
67             # Library Modules
68              
69 7     7   6999 use WWW::Mechanize;
  7         1036467  
  7         21538  
70              
71             #----------------------------------------------------------------------------
72             # Variables
73              
74             my $URL = 'http://www.cpantesters.org/cgi-bin/reports-summary.cgi?';
75             #$URL = 'http://reports/cgi-bin/reports-summary.cgi?'; # local test version
76              
77             my %rules = (
78             dist => qr/^([-\w.]+)$/i,
79             version => qr/^([-\w.]+)$/i,
80             perlmat => qr/^([0-2])$/i,
81             patches => qr/^([0-2])$/i,
82             perlver => qr/^([\w.]+)$/i,
83             osname => qr/^([\w.]+)$/i,
84             format => qr/^(csv|html|xml)$/i
85             );
86              
87             my @fields = keys %rules;
88              
89             my $mech = WWW::Mechanize->new();
90             $mech->agent_alias( 'Linux Mozilla' );
91              
92             # -------------------------------------
93             # Program
94              
95             sub new {
96 0     0 1   my($class, %hash) = @_;
97 0           my $self = {
98             success => 0,
99             error => ''
100             };
101 0           bless $self, $class;
102 0           my @valid = qw(format);
103              
104 0 0         unless($hash{dist}) {
105 0           $self->{error} = q{no value for 'dist' provided};
106 0           return;
107             }
108              
109 0           for my $key (@fields) {
110 0 0         next unless($hash{$key});
111 0           my ($value) = $hash{$key} =~ m/$rules{$key}/;
112 0 0         next unless($value);
113              
114 0           $self->{options}{$key} = $value;
115 0           push @valid, $key;
116             }
117              
118 0   0       $self->{options}{format} ||= 'xml';
119              
120             # ajax request
121 0           my $url = $URL;
122 0           $url .= join( '&', map { "$_=$self->{options}{$_}" } @valid );
  0            
123             #print STDERR "# URL: $url\n";
124 0           eval { $mech->get( $url ); };
  0            
125 0 0 0       if($@ || !$mech->success()) {
126 0           $self->{error} = $@;
127 0           return $self;
128             }
129              
130             #print "URI: " . $mech->uri . "\n";
131              
132 0           $self->_parse( $mech->content() );
133            
134 0           $self->{success} = 1;
135 0           return $self;
136             }
137              
138 0     0 1   sub is_success { $_[0]->{success}; }
139 0     0 1   sub error { $_[0]->{error}; }
140              
141 0     0 1   sub all { $_[0]->_basic('all'); }
142 0     0 1   sub pass { $_[0]->_basic('pass'); }
143 0     0 1   sub fail { $_[0]->_basic('fail'); }
144 0     0 1   sub na { $_[0]->_basic('na'); }
145 0     0 1   sub unknown { $_[0]->_basic('unknown'); }
146            
147 0     0 1   sub pc_pass { $_[0]->_basic_pc('pass'); }
148 0     0 1   sub pc_fail { $_[0]->_basic_pc('fail'); }
149 0     0 1   sub pc_na { $_[0]->_basic_pc('na'); }
150 0     0 1   sub pc_unknown { $_[0]->_basic_pc('unknown'); }
151              
152             sub _basic {
153 0     0     my $self = shift;
154 0           my $grade = shift;
155 0   0       my $version = $self->{options}{version} || $self->{recent};
156 0           return $self->{result}{$version}{$grade};
157             }
158              
159             sub _basic_pc {
160 0     0     my $self = shift;
161 0           my $grade = shift;
162 0   0       my $version = $self->{options}{version} || $self->{recent};
163 0 0         return 0 unless($self->{result}{$version}{'all'});
164 0           my $pc = sprintf "%3.10f", $self->{result}{$version}{$grade} / $self->{result}{$version}{'all'} * 100;
165 0           $pc =~ s/\.?0+$//;
166 0           return $pc;
167             }
168              
169             sub _parse {
170 0     0     my ($self,$content) = @_;
171 0           $self->{content} = $content;
172              
173 0 0         if($self->{options}{format} eq 'csv') {
    0          
174 0           my @lines = split("\n",$content);
175 0           for my $line (@lines) {
176 0 0         next if($line =~ /^\s*$/);
177 0           my ($version,$all,$pass,$fail,$na,$unknown) = split(',',$line);
178 0 0         next unless($version);
179 0 0         if (!exists $self->{recent}) {
180 0           $self->{recent} = $version;
181             }
182 0           $self->{result}{$version}{pass} = $pass;
183 0           $self->{result}{$version}{fail} = $fail;
184 0           $self->{result}{$version}{na} = $na;
185 0           $self->{result}{$version}{unknown} = $unknown;
186 0           $self->{result}{$version}{all} = $all;
187             }
188              
189             } elsif($self->{options}{format} eq 'xml') {
190 0           my @lines = split("\n",$content);
191 0           for my $line (@lines) {
192 0 0         next if($line =~ /^\s*$/);
193 0           my ($all,$pass,$fail,$na,$unknown,$version) = $line =~ m{([^<]+)};
194 0 0         next unless($version);
195 0 0         if (!exists $self->{recent}) {
196 0           $self->{recent} = $version;
197             }
198 0           $self->{result}{$version}{pass} = $pass;
199 0           $self->{result}{$version}{fail} = $fail;
200 0           $self->{result}{$version}{na} = $na;
201 0           $self->{result}{$version}{unknown} = $unknown;
202 0           $self->{result}{$version}{all} = $all;
203             }
204              
205             #} elsif($self->{options}{format} eq 'html') {
206             } else {
207             # TODO: need to pull out OT response
208             }
209              
210             # currently no parsing for other formats.
211             # use raw to do it yourself :)
212             }
213              
214             sub data {
215 0     0 1   my $self = shift;
216 0           my $version = shift;
217 0 0         return $self->{result}{$version} if($version);
218 0           return $self->{result};
219             }
220              
221             sub raw {
222 0     0 1   my $self = shift;
223 0           return $self->{content};
224             }
225            
226             1;
227              
228             __END__