| blib/lib/CPAN/Search/Author.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 49 | 96 | 51.0 |
| branch | 6 | 24 | 25.0 |
| condition | n/a | ||
| subroutine | 11 | 13 | 84.6 |
| pod | 4 | 5 | 80.0 |
| total | 70 | 138 | 50.7 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package CPAN::Search::Author; | ||||||
| 2 | |||||||
| 3 | 2 | 2 | 54080 | use strict; use warnings; | |||
| 2 | 2 | 5 | |||||
| 2 | 63 | ||||||
| 2 | 10 | ||||||
| 2 | 8 | ||||||
| 2 | 82 | ||||||
| 4 | |||||||
| 5 | 2 | 2 | 3391 | use overload q("") => \&as_string, fallback => 1; | |||
| 2 | 2117 | ||||||
| 2 | 14 | ||||||
| 6 | |||||||
| 7 | =head1 NAME | ||||||
| 8 | |||||||
| 9 | CPAN::Search::Author - Interface to search CPAN module author. | ||||||
| 10 | |||||||
| 11 | =head1 VERSION | ||||||
| 12 | |||||||
| 13 | Version 0.03 | ||||||
| 14 | |||||||
| 15 | =cut | ||||||
| 16 | |||||||
| 17 | our $VERSION = '0.03'; | ||||||
| 18 | our $DEBUG = 0; | ||||||
| 19 | |||||||
| 20 | 2 | 2 | 163 | use Carp; | |||
| 2 | 3 | ||||||
| 2 | 178 | ||||||
| 21 | 2 | 2 | 3673 | use Data::Dumper; | |||
| 2 | 15845 | ||||||
| 2 | 165 | ||||||
| 22 | 2 | 2 | 1618 | use HTTP::Request; | |||
| 2 | 57139 | ||||||
| 2 | 70 | ||||||
| 23 | 2 | 2 | 2209 | use LWP::UserAgent; | |||
| 2 | 54367 | ||||||
| 2 | 79 | ||||||
| 24 | 2 | 2 | 1757 | use HTML::Entities qw/decode_entities/; | |||
| 2 | 14908 | ||||||
| 2 | 2376 | ||||||
| 25 | |||||||
| 26 | =head1 DESCRIPTION | ||||||
| 27 | |||||||
| 28 | CPAN::Search::Author is an attempt to provide programmatical interface to CPAN Search engine. | ||||||
| 29 | CPAN Search is a search engine for the distributions, modules, docs, and ID's on CPAN. It was | ||||||
| 30 | conceived and built by Graham Barr as a way to make things easier to navigate. Originally | ||||||
| 31 | named TUCS [ The Ultimate CPAN Search ] it was later named CPAN Search or Search DOT CPAN. | ||||||
| 32 | |||||||
| 33 | =cut | ||||||
| 34 | |||||||
| 35 | sub new | ||||||
| 36 | { | ||||||
| 37 | 1 | 1 | 0 | 17 | my $class = shift; | ||
| 38 | 1 | 15 | my $self = { _browser => LWP::UserAgent->new() }; | ||||
| 39 | |||||||
| 40 | 1 | 492001 | bless $self, $class; | ||||
| 41 | 1 | 6 | return $self; | ||||
| 42 | } | ||||||
| 43 | |||||||
| 44 | =head1 METHODS | ||||||
| 45 | |||||||
| 46 | =head2 by_id() | ||||||
| 47 | |||||||
| 48 | This method accepts CPAN ID exactly as provided by CPAN. It does realtime search on CPAN site | ||||||
| 49 | and fetch the author name for the given CPAN ID. However it would croak if it can't access the | ||||||
| 50 | CPAN site or unable to get any response for the given CPAN ID. | ||||||
| 51 | |||||||
| 52 | use strict; use warnings; | ||||||
| 53 | use CPAN::Search::Author; | ||||||
| 54 | my $search = CPAN::Search::Author->new(); | ||||||
| 55 | my $result = $search->by_id('MANWAR'); | ||||||
| 56 | |||||||
| 57 | =cut | ||||||
| 58 | |||||||
| 59 | sub by_id | ||||||
| 60 | { | ||||||
| 61 | 1 | 1 | 1 | 9 | my $self = shift; | ||
| 62 | 1 | 3 | my $id = shift; | ||||
| 63 | |||||||
| 64 | 1 | 41 | my $browser = $self->{_browser}; | ||||
| 65 | 1 | 7 | $browser->env_proxy; | ||||
| 66 | 1 | 369731 | my $request = HTTP::Request->new(POST=>qq[http://search.cpan.org/search?query=$id&mode=author]); | ||||
| 67 | 1 | 12710 | my $response = $browser->request($request); | ||||
| 68 | 1 | 50 | 483425 | print {*STDOUT} "Search By Id [$id] Status: " . $response->status_line . "\n" if $DEBUG; | |||
| 0 | 0 | ||||||
| 69 | 1 | 50 | 8 | croak("ERROR: Couldn't connect to search.cpan.org.\n") | |||
| 70 | unless $response->is_success; | ||||||
| 71 | |||||||
| 72 | 1 | 28 | my $contents = $response->content; | ||||
| 73 | 1 | 75 | my @contents = split(/\n/,$contents); | ||||
| 74 | 1 | 10 | foreach (@contents) | ||||
| 75 | { | ||||||
| 76 | 58 | 167 | chomp; | ||||
| 77 | 58 | 209 | s/^\s+//g; | ||||
| 78 | 58 | 194 | s/\s+$//g; | ||||
| 79 | 58 | 100 | 241 | if (/\ \ \(.*)<\/b\>/) |
|||
| 80 | { | ||||||
| 81 | 1 | 50 | 17 | if (uc($id) eq uc($1)) | |||
| 82 | { | ||||||
| 83 | 1 | 16 | $self->{result} = decode_entities($2); | ||||
| 84 | 1 | 69 | return $self->{result}; | ||||
| 85 | } | ||||||
| 86 | } | ||||||
| 87 | } | ||||||
| 88 | 0 | 0 | $self->{result} = undef; | ||||
| 89 | 0 | 0 | return; | ||||
| 90 | } | ||||||
| 91 | |||||||
| 92 | =head2 where_id_starts_with() | ||||||
| 93 | |||||||
| 94 | This method accepts an alphabet (A-Z) and get the list of authors that start with the given | ||||||
| 95 | alphabet from CPAN site realtime. However it would croak if it can't access the CPAN site or | ||||||
| 96 | unable to get any response for the given CPAN ID. | ||||||
| 97 | |||||||
| 98 | use strict; use warnings; | ||||||
| 99 | use CPAN::Search::Author; | ||||||
| 100 | my $search = CPAN::Search::Author->new(); | ||||||
| 101 | my $result = $search->where_id_starts_with('M'); | ||||||
| 102 | |||||||
| 103 | =cut | ||||||
| 104 | |||||||
| 105 | sub where_id_starts_with | ||||||
| 106 | { | ||||||
| 107 | 1 | 1 | 1 | 878 | my $self = shift; | ||
| 108 | 1 | 6 | my $letter = shift; | ||||
| 109 | 1 | 50 | 259 | croak("ERROR: Invalid letter [$letter].\n") | |||
| 110 | unless ($letter =~ /[A-Z]/i); | ||||||
| 111 | |||||||
| 112 | 0 | my $browser = $self->{_browser}; | |||||
| 113 | 0 | $browser->env_proxy; | |||||
| 114 | 0 | my $request = HTTP::Request->new(POST=>qq[http://search.cpan.org/author/?$letter]); | |||||
| 115 | 0 | my $response = $browser->request($request); | |||||
| 116 | 0 | 0 | print {*STDOUT} "Search Id Starts With [$letter] Status: " . $response->status_line . "\n" if $DEBUG; | ||||
| 0 | |||||||
| 117 | 0 | 0 | croak("ERROR: Couldn't connect to search.cpan.org.\n") | ||||
| 118 | unless $response->is_success; | ||||||
| 119 | |||||||
| 120 | 0 | my $contents = $response->content; | |||||
| 121 | 0 | my @contents = split(/\n/,$contents); | |||||
| 122 | |||||||
| 123 | 0 | my @authors; | |||||
| 124 | 0 | foreach (@contents) | |||||
| 125 | { | ||||||
| 126 | 0 | chomp; | |||||
| 127 | 0 | s/^\s+//g; | |||||
| 128 | 0 | s/\s+$//g; | |||||
| 129 | 0 | 0 | if (/ | ||||
| 130 | { | ||||||
| 131 | 0 | push @authors, $1; | |||||
| 132 | } | ||||||
| 133 | } | ||||||
| 134 | 0 | return @authors; | |||||
| 135 | } | ||||||
| 136 | |||||||
| 137 | =head2 where_name_contains() | ||||||
| 138 | |||||||
| 139 | This method accepts a search string and look for the string in the author's name of all the | ||||||
| 140 | CPAN modules realtime and returns the a reference to a hash containing id,name pair containing | ||||||
| 141 | the search string. It croaks if unable to access the search.cpan.org. | ||||||
| 142 | |||||||
| 143 | use strict; use warnings; | ||||||
| 144 | use CPAN::Search::Author; | ||||||
| 145 | my $search = CPAN::Search::Author->new(); | ||||||
| 146 | my $result = $search->where_name_contains('MAN'); | ||||||
| 147 | |||||||
| 148 | =cut | ||||||
| 149 | |||||||
| 150 | sub where_name_contains | ||||||
| 151 | { | ||||||
| 152 | 0 | 0 | 1 | my $self = shift; | |||
| 153 | 0 | my $query = shift; | |||||
| 154 | |||||||
| 155 | 0 | my $browser = $self->{_browser}; | |||||
| 156 | 0 | $browser->env_proxy; | |||||
| 157 | 0 | my $request = HTTP::Request->new(POST=>qq[http://search.cpan.org/search?query=$query&mode=author]); | |||||
| 158 | 0 | my $response = $browser->request($request); | |||||
| 159 | 0 | 0 | print {*STDOUT} "Search By Name Contains [$query] Status: " . $response->status_line . "\n" if $DEBUG; | ||||
| 0 | |||||||
| 160 | 0 | 0 | croak("ERROR: Couldn't connect to search.cpan.org.\n") | ||||
| 161 | unless $response->is_success; | ||||||
| 162 | |||||||
| 163 | 0 | my $contents = $response->content; | |||||
| 164 | 0 | my @contents = split(/\n/,$contents); | |||||
| 165 | |||||||
| 166 | 0 | my $authors; | |||||
| 167 | 0 | foreach (@contents) | |||||
| 168 | { | ||||||
| 169 | 0 | chomp; | |||||
| 170 | 0 | s/^\s+//g; | |||||
| 171 | 0 | s/\s+$//g; | |||||
| 172 | 0 | 0 | if (/\ \ \(.*)<\/b\>/) |
||||
| 173 | { | ||||||
| 174 | 0 | $authors->{$1} = decode_entities($2); | |||||
| 175 | } | ||||||
| 176 | } | ||||||
| 177 | 0 | $self->{result} = $authors; | |||||
| 178 | 0 | return $authors; | |||||
| 179 | } | ||||||
| 180 | |||||||
| 181 | =head2 as_string() | ||||||
| 182 | |||||||
| 183 | Return the last search result in human readable format. | ||||||
| 184 | |||||||
| 185 | use strict; use warnings; | ||||||
| 186 | use CPAN::Search::Author; | ||||||
| 187 | my $search = CPAN::Search::Author->new(); | ||||||
| 188 | my $result = $search->where_name_contains('MAN'); | ||||||
| 189 | print $search->as_string(); | ||||||
| 190 | |||||||
| 191 | # or simply | ||||||
| 192 | |||||||
| 193 | print $search; | ||||||
| 194 | |||||||
| 195 | =cut | ||||||
| 196 | |||||||
| 197 | sub as_string | ||||||
| 198 | { | ||||||
| 199 | 0 | 0 | 1 | my $self = shift; | |||
| 200 | 0 | 0 | return $self->{result} unless ref($self->{result}); | ||||
| 201 | |||||||
| 202 | 0 | my $string; | |||||
| 203 | 0 | foreach (keys %{$self->{result}}) | |||||
| 0 | |||||||
| 204 | { | ||||||
| 205 | 0 | $string .= sprintf("%s: %s\n", $_, $self->{result}->{$_}); | |||||
| 206 | } | ||||||
| 207 | 0 | return $string; | |||||
| 208 | } | ||||||
| 209 | |||||||
| 210 | =head1 AUTHOR | ||||||
| 211 | |||||||
| 212 | Mohammad S Anwar, C<< |
||||||
| 213 | |||||||
| 214 | =head1 BUGS | ||||||
| 215 | |||||||
| 216 | Please report any bugs or feature requests to C |
||||||
| 217 | through the web interface at L |
||||||
| 218 | I will be notified, and then you'll automatically be notified of progress on your bug as I | ||||||
| 219 | make changes. | ||||||
| 220 | |||||||
| 221 | =head1 SUPPORT | ||||||
| 222 | |||||||
| 223 | You can find documentation for this module with the perldoc command. | ||||||
| 224 | |||||||
| 225 | perldoc CPAN::Search::Author | ||||||
| 226 | |||||||
| 227 | You can also look for information at: | ||||||
| 228 | |||||||
| 229 | =over 4 | ||||||
| 230 | |||||||
| 231 | =item * RT: CPAN's request tracker | ||||||
| 232 | |||||||
| 233 | L |
||||||
| 234 | |||||||
| 235 | =item * AnnoCPAN: Annotated CPAN documentation | ||||||
| 236 | |||||||
| 237 | L |
||||||
| 238 | |||||||
| 239 | =item * CPAN Ratings | ||||||
| 240 | |||||||
| 241 | L |
||||||
| 242 | |||||||
| 243 | =item * Search CPAN | ||||||
| 244 | |||||||
| 245 | L |
||||||
| 246 | |||||||
| 247 | =back | ||||||
| 248 | |||||||
| 249 | =head1 LICENSE AND COPYRIGHT | ||||||
| 250 | |||||||
| 251 | Copyright 2011-14 Mohammad S Anwar. | ||||||
| 252 | |||||||
| 253 | This program is free software; you can redistribute it and/or modify it under the terms of | ||||||
| 254 | either : the GNU General Public License as published by the Free Software Foundation; or the | ||||||
| 255 | Artistic License. | ||||||
| 256 | |||||||
| 257 | See http://dev.perl.org/licenses/ for more information. | ||||||
| 258 | |||||||
| 259 | =head1 DISCLAIMER | ||||||
| 260 | |||||||
| 261 | This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; | ||||||
| 262 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||||
| 263 | |||||||
| 264 | =cut | ||||||
| 265 | |||||||
| 266 | 1; # End of CPAN::Search::Author |