File Coverage

lib/CPAN/Testers/WWW/Reports/Query/AJAX.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 CPAN::Testers::WWW::Reports::Query::AJAX;
2              
3 7     7   170918 use strict;
  7         19  
  7         307  
4 7     7   37 use warnings;
  7         12  
  7         465  
5              
6             our $VERSION = '0.08';
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   14714 use WWW::Mechanize;
  0            
  0            
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/^(text|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             my($class, %hash) = @_;
97             my $self = {
98             success => 0,
99             error => ''
100             };
101             bless $self, $class;
102             my @valid = qw(format);
103            
104             for my $key (@fields) {
105             next unless($hash{$key});
106             $hash{$key} =~ s/$rules{$key}/$1/;
107             next unless($hash{$key});
108              
109             $self->{options}{$key} = $hash{$key};
110             push @valid, $key;
111             }
112              
113             $self->{options}{format} ||= 'xml';
114              
115             # ajax request
116             my $url = $URL;
117             $url .= join( '&', map { "$_=$self->{options}{$_}" } @valid );
118             #print "URL: $url\n";
119             eval { $mech->get( $url ); };
120             if($@ || !$mech->success()) {
121             $self->{error} = $@;
122             return $self;
123             }
124              
125             #print "URI: " . $mech->uri . "\n";
126              
127             $self->_parse( $mech->content() );
128            
129             $self->{success} = 1;
130             return $self;
131             }
132              
133             sub is_success { $_[0]->{success}; }
134             sub error { $_[0]->{error}; }
135              
136             sub all { $_[0]->_basic('all'); }
137             sub pass { $_[0]->_basic('pass'); }
138             sub fail { $_[0]->_basic('fail'); }
139             sub na { $_[0]->_basic('na'); }
140             sub unknown { $_[0]->_basic('unknown'); }
141            
142             sub pc_pass { $_[0]->_basic_pc('pass'); }
143             sub pc_fail { $_[0]->_basic_pc('fail'); }
144             sub pc_na { $_[0]->_basic_pc('na'); }
145             sub pc_unknown { $_[0]->_basic_pc('unknown'); }
146              
147             sub _basic {
148             my $self = shift;
149             my $grade = shift;
150             my $version = $self->{options}{version} || $self->{recent};
151             return $self->{result}{$version}{$grade};
152             }
153              
154             sub _basic_pc {
155             my $self = shift;
156             my $grade = shift;
157             my $version = $self->{options}{version} || $self->{recent};
158             return 0 unless($self->{result}{$version}{'all'});
159             my $pc = sprintf "%3.10f", $self->{result}{$version}{$grade} / $self->{result}{$version}{'all'} * 100;
160             $pc =~ s/\.?0+$//;
161             return $pc;
162             }
163              
164             sub _parse {
165             my ($self,$content) = @_;
166             $self->{content} = $content;
167              
168             if($self->{options}{format} eq 'txt') {
169             my @lines = split("\n",$content);
170             for my $line (@lines) {
171             next if($line =~ /^\s*$/);
172             my ($version,$all,$pass,$fail,$na,$unknown) = split(',',$line);
173             next unless($version);
174             if (!exists $self->{recent}) {
175             $self->{recent} = $version;
176             }
177             $self->{result}{$version}{pass} = $pass;
178             $self->{result}{$version}{fail} = $fail;
179             $self->{result}{$version}{na} = $na;
180             $self->{result}{$version}{unknown} = $unknown;
181             $self->{result}{$version}{all} = $all;
182             }
183              
184             } elsif($self->{options}{format} eq 'xml') {
185             my @lines = split("\n",$content);
186             for my $line (@lines) {
187             next if($line =~ /^\s*$/);
188             my ($all,$pass,$fail,$na,$unknown,$version) = $line =~ m{([^<]+)};
189             next unless($version);
190             if (!exists $self->{recent}) {
191             $self->{recent} = $version;
192             }
193             $self->{result}{$version}{pass} = $pass;
194             $self->{result}{$version}{fail} = $fail;
195             $self->{result}{$version}{na} = $na;
196             $self->{result}{$version}{unknown} = $unknown;
197             $self->{result}{$version}{all} = $all;
198             }
199              
200             } elsif($self->{options}{format} eq 'html') {
201             # TODO: need to pull out OT response
202             }
203              
204             # currently no parsing for other formats.
205             # use raw to do it yourself :)
206             }
207              
208             sub data {
209             my $self = shift;
210             my $version = shift;
211             return $self->{result}{$version} if($version);
212             return $self->{result};
213             }
214              
215             sub raw {
216             my $self = shift;
217             return $self->{content};
218             }
219            
220             1;
221              
222             __END__