File Coverage

blib/lib/WWW/CPAN.pm
Criterion Covered Total %
statement 21 71 29.5
branch 0 12 0.0
condition 0 4 0.0
subroutine 7 13 53.8
pod 3 3 100.0
total 31 103 30.1


line stmt bran cond sub pod time code
1              
2             package WWW::CPAN;
3              
4 3     3   776374 use 5.006;
  3         12  
  3         120  
5 3     3   16 use strict;
  3         7  
  3         99  
6 3     3   25 use warnings;
  3         7  
  3         156  
7              
8             our $VERSION = '0.011';
9              
10 3     3   2888 use Class::Lego::Constructor 0.004 ();
  3         76060  
  3         98  
11 3     3   1760 use parent qw( Class::Accessor Class::Lego::Constructor );
  3         686  
  3         5282  
12              
13             my $FIELDS = {
14             host => 'search.cpan.org',
15             ua => sub { # default useragent
16             my %options = ( agent => 'www-cpan/' . $VERSION, );
17             # require LWP::UserAgent;
18             # return LWP::UserAgent->new( %options );
19             require LWP::UserAgent::Determined;
20             return LWP::UserAgent::Determined->new( %options );
21             },
22             j_loader => sub { # json loader sub
23             require JSON::Any;
24             JSON::Any->import; # XXX JSON::Any needs this
25             my $j = JSON::Any->new;
26             return sub { $j->Load(shift); }
27             },
28             x_loader => sub { # xml loader sub
29             require XML::Simple;
30             my %options = (
31             ForceArray => [qw( module dist match )],
32             KeyAttr => [],
33             );
34             my $x = XML::Simple->new( %options );
35             return sub { $x->XMLin(shift); }
36             },
37             };
38              
39             __PACKAGE__->mk_constructor0( $FIELDS );
40             __PACKAGE__->mk_accessors( keys %$FIELDS );
41              
42 3     3   37949 use Class::Lego::Myself;
  3         110377  
  3         25  
43             __PACKAGE__->give_my_self;
44              
45 3     3   869 use Carp qw( carp );
  3         7  
  3         3114  
46              
47             sub _build_distmeta_uri {
48 0     0     my $self = shift;
49 0           my $params = shift;
50              
51 0 0         if ( ! ref $params ) {
52 0           $params = { dist => $params };
53             }
54 0           require URI;
55 0           my $uri = URI->new();
56 0           $uri->scheme('http');
57 0           $uri->authority( $self->host );
58 0           my @path = qw( meta );
59 0 0         if ( $params->{author} ) {
60 0           push @path, $params->{author};
61             }
62              
63 0           my $dist = $params->{dist};
64 0 0         if ( $params->{version} ) {
65 0           $dist .= '-' . $params->{version};
66             }
67 0           push @path, $dist;
68              
69 0           push @path, 'META.json'; # XXX support YAML as well
70 0           $uri->path_segments(@path);
71              
72 0           return $uri;
73             }
74              
75             sub fetch_distmeta {
76 0     0 1   (my $self, @_) = &find_my_self;
77 0           my $uri = $self->_build_distmeta_uri(@_);
78 0           my $r = $self->ua->get($uri);
79 0 0         if ( $r->is_success ) {
80 0           return $self->j_loader->( $r->content );
81             } else {
82 0           carp $r->status_line; # FIXME needs more convincing error handling
83 0           return;
84             }
85             }
86              
87             # http://search.cpan.org/search?query=Archive&mode=all&format=xml
88             sub _build_query_uri {
89 0     0     my $self = shift;
90 0           my $params = shift;
91              
92 0 0         if ( ! ref $params ) {
93 0           $params = { query => $params, mode => 'all', format => 'xml', };
94             }
95 0           require URI;
96 0           my $uri = URI->new();
97 0           $uri->scheme('http');
98 0           $uri->authority( $self->host );
99 0           my @path = qw( search );
100 0           $uri->path_segments(@path);
101              
102 0   0       $params->{mode} ||= 'all';
103 0   0       $params->{format} ||= 'xml';
104 0           $uri->query_form( $params );
105              
106 0           return $uri;
107             }
108             # other params: s (start), n (page size, should be <= 100)
109              
110             sub _basic_query {
111 0     0     my $self = shift;
112 0           my $uri = $self->_build_query_uri(@_);
113 0           my $r = $self->ua->get($uri);
114 0 0         if ( $r->is_success ) {
115 0           return $self->x_loader->( $r->content );
116             } else {
117 0           carp $r->status_line; # FIXME needs more convincing error handling
118 0           return;
119             }
120             }
121              
122             sub search {
123 0     0 1   my $self = &find_my_self;
124 0           return $self->_basic_query(@_);
125             }
126             # TODO fetch the entire result by default
127              
128             # &query is an alias to &search (see Method::Alias for the rationale)
129             sub query {
130 0     0 1   goto &{ $_[0]->can('search') };
  0            
131             }
132              
133             "I didn't do it! -- Bart Simpson";