File Coverage

blib/lib/WWW/Codeguard.pm
Criterion Covered Total %
statement 27 88 30.6
branch 7 38 18.4
condition 11 27 40.7
subroutine 8 16 50.0
pod 2 4 50.0
total 55 173 31.7


line stmt bran cond sub pod time code
1             package WWW::Codeguard;
2              
3 2     2   49252 use strict;
  2         4  
  2         64  
4 2     2   10 use warnings FATAL => 'all', NONFATAL => 'uninitialized';
  2         3  
  2         79  
5              
6 2     2   8 use Carp qw(croak);
  2         3  
  2         85  
7 2     2   672 use English qw(-no_match_vars);
  2         3740  
  2         9  
8 2     2   1083 use JSON;
  2         8431  
  2         12  
9              
10             =head1 NAME
11              
12             WWW::Codeguard - Perl interface to interact with the Codeguard API
13              
14             =head1 VERSION
15              
16             Version 0.09
17              
18             =cut
19              
20             our $VERSION = '0.09';
21              
22             =head1 SYNOPSIS
23              
24             This module provides you with an perl interface to interact with the Codeguard API. This is really just the base class that returns the proper object to use.
25             Depending on the params you pass, it will return either the 'Partner' object, or the 'User' object.
26              
27             use WWW::Codeguard;
28              
29             my $partner_api = WWW::Codeguard->new(
30             {
31             api_url => $api_url,
32             partner => {
33             partner_key => $partner_key,
34             },
35             }
36             );
37              
38             my $user_api = WWW::Codeguard->new(
39             {
40             api_url => $api_url,
41             user => {
42             api_key => $user_api_key,
43             api_secret => $user_api_secret,
44             access_secret => $user_access_secret,
45             access_token => $user_access_token,
46             },
47             }
48             );
49              
50             =cut
51              
52             =head1 Object Initialization
53              
54             B takes an hashref of params. The hashref should contain:
55              
56             api_url
57             partner => $hashref_containing_the_partner_options
58             user => $hashref_containing_the_user_options
59              
60             If both 'partner' and 'user' options are specified, then you should use it an array context to get back both objects:
61              
62             my ($partner_api, $user_api) = WWW::Codeguard->new(
63             {
64             api_url => $api_url,
65             partner => {
66             partner_key => $partner_key,
67             },
68             user => {
69             api_key => $user_api_key,
70             api_secret => $user_api_secret,
71             access_secret => $user_access_secret,
72             access_token => $user_access_token,
73             },
74             }
75             );
76              
77             If array context is not specified, then it will only return the partner api object even if both objects were created.
78              
79             =cut
80              
81             sub new {
82              
83 3     3 0 6370 my ($class, $opts) = @_;
84 3 50 33     37 unless ( $opts and UNIVERSAL::isa($opts, 'HASH') and (exists $opts->{partner} or exists $opts->{user}) ) {
      66        
      66        
85 0         0 croak ('Object initialization failed. Invalid params passed to constructor.');
86             }
87              
88 3         6 my ($partner_obj, $user_obj);
89 3 100 66     18 if ( exists $opts->{partner} and UNIVERSAL::isa($opts->{partner}, 'HASH') ) {
90 2         386 require WWW::Codeguard::Partner;
91 2         21 $partner_obj = WWW::Codeguard::Partner->new($opts->{api_url}, $opts->{partner});
92             }
93              
94 3 100 66     22 if ( exists $opts->{user} and UNIVERSAL::isa($opts->{user}, 'HASH') ) {
95 2         579 require WWW::Codeguard::User;
96 2         35 $user_obj = WWW::Codeguard::User->new($opts->{api_url}, $opts->{user});
97             }
98              
99             # If called in an array content, return both;
100             # if not just return which ever one is not undef.
101 3 100 66     26 return wantarray ? ($partner_obj, $user_obj) : $partner_obj || $user_obj;
102             }
103              
104             =head1 METHODS
105              
106             Partner methods are documented in L
107              
108             User methods are documented in L
109              
110             =cut
111              
112             =head2 get_error
113              
114             Returns the current value in $self->{_error}.
115              
116             =cut
117              
118 0     0 1 0 sub get_error { shift->{_error}; }
119              
120             =head2 get_api_url
121              
122             Returns the current value in $self->{api_url}.
123              
124             =cut
125              
126 2     2 1 1228 sub get_api_url { shift->{api_url}; }
127              
128 4     4 0 40 sub VERSION { return $WWW::Codeguard::VERSION; }
129              
130             # Internal Methods
131              
132             sub _do_method {
133              
134 0     0     my ($self, $name, $params) = @_;
135 0 0 0       if (defined $params and not UNIVERSAL::isa($params, 'HASH')) {
136 0           $self->_error('$params passed has to be a HASHREF', 1);
137             }
138              
139 0 0         $self->_sanitize_params($name, $params) or
140             $self->_error('Failed to sanitize params: "'.$self->get_error.'" - The parameters passed in were: '."\n".$self->_stringify_hash($params), 1);
141              
142 0           return $self->_dispatch_request($name, $params);
143             }
144              
145             sub _dispatch_request {
146              
147 0     0     my ($self, $action, $params) = @_;
148 0 0         my $base_url = $self->get_api_url() or
149             return $self->_error('Failed to fetch api_url', 1);
150              
151 0           my $request = $self->_create_request($action, $params);
152 0           my $api_response = $self->{_ua}->request($request);
153 0 0         if (my $output = $api_response->decoded_content) {
154 0 0         my $json = eval { decode_json($output); }
  0            
155             or return $self->_error('Invalid API reponse received (unable to decode json): '.$api_response->status_line, 1);
156 0           return $json;
157             } else {
158 0           return $self->_error('Invalid API reponse received (no json received): '.$api_response->status_line, 1);
159             }
160 0           return;
161             }
162              
163             sub _sanitize_params {
164              
165 0     0     my ($self, $action, $params) = @_;
166 0 0         my $required_params = $self->_fetch_required_params($action, $params) or return $self->_error( 'Unknown action specified: ' . $action );
167 0           my $optional_params = $self->_fetch_optional_params($action);
168              
169 0 0         if (my $check = _check_params($params, $required_params, $optional_params) ) {
170 0           my $error;
171 0           $error .= 'Missing required parameter(s): ' . join (', ', @{ $check->{'required_params'} } ).' ; '
172 0 0         if $check->{'required_params'};
173 0           $error .= 'Blank parameter(s): ' . join (', ', @{ $check->{'blank_params'} } ).' ; '
174 0 0         if $check->{'blank_params'};
175 0           $self->_error($error);
176 0           return;
177             }
178              
179 0           return 1;
180             }
181              
182             sub _set_content {
183              
184 0     0     my ($self, $request, $params) = @_;
185 0 0         if ('GET' ne $request->method) {
186 0 0         my $json = eval {
187 0           encode_json( $params );
188             } or $self->_error('Failed to encode json payload for request', 1);
189 0           $request->content($json);
190             }
191 0           return;
192             }
193              
194             =head2 _check_params
195              
196             B: Three hashrefs that contain the following in the specified order:
197              
198             1) the hashref to the params that need to be checked.
199             2) the hashref to the 'required' set of params
200             3) the hashref to the 'optional' set of params
201              
202             B: Undef if everything is good. If errors are detected, it will return a hashref that has two arrays:
203              
204             'required_params' - which will list the required params that are missing. And
205             'blank_params' - which will list the params that have blank values specified for them.
206              
207             This also 'prunes' the first hashref of params that are not specified in either the required or the optional hashrefs.
208              
209             =cut
210              
211             sub _check_params {
212              
213 0     0     my ($params_to_check, $required_params, $optional_params) = @_;
214 0           my $output;
215              
216 0           foreach my $param ( keys %{ $params_to_check } ) {
  0            
217 0 0 0       if (not (exists $required_params->{$param} or exists $optional_params->{$param} ) ) {
    0          
218 0           delete $params_to_check->{$param};
219             } elsif (not length $params_to_check->{ $param } ) {
220 0           push @{ $output->{'blank_params'} }, $param;
  0            
221             }
222             }
223              
224 0           foreach my $required_param ( keys %{ $required_params } ) {
  0            
225 0 0 0       if (not (exists $params_to_check->{ $required_param } and defined $params_to_check->{ $required_param } ) ) {
226 0           push @{ $output->{'required_params'} }, $required_param;
  0            
227             }
228             }
229              
230 0           return $output;
231             }
232              
233             sub _stringify_hash {
234              
235 0     0     my $self = shift;
236 0           my $hashref = shift;
237 0           my $string;
238 0           while (my ($key, $value) = each %{$hashref}) {
  0            
239 0           $string .= $key.'='.$value.', ';
240             }
241 0           $string =~ s/, $//;
242 0           return $string;
243             }
244              
245             =head2 _error
246              
247             Internal method that is used to report and set $self->{_error}.
248              
249             Will croak if a true second argument is passed. Example:
250              
251             $self->_error($msg, 1);
252              
253             =cut
254              
255             sub _error {
256              
257 0     0     my ($self, $msg, $croak) = @_;
258 0           $self->{_error} = $msg;
259 0 0         if ($croak) {
260 0           croak $msg;
261             }
262             }
263              
264             =head1 AUTHOR
265              
266             Rishwanth Yeddula, C<< >>
267              
268             =head2 COMAINTAINERS
269              
270             =over 4
271              
272             =item David Oswald, C<< >>
273              
274             =item James Jacobson, C<< >>
275              
276             =back
277              
278             =head1 BUGS
279              
280             Please report any bugs or feature requests to C, or through
281             the web interface at L. I will be notified, and then you'll
282             automatically be notified of progress on your bug as I make changes.
283              
284             =head1 SUPPORT
285              
286             You can find documentation for this module with the following perldoc commands.
287              
288             perldoc WWW::Codeguard
289             perldoc WWW::Codeguard::Partner
290             perldoc WWW::Codeguard::User
291              
292              
293             You can also look for information at:
294              
295             =over 4
296              
297             =item * RT: CPAN's request tracker (report bugs here)
298              
299             L
300              
301             =item * AnnoCPAN: Annotated CPAN documentation
302              
303             L
304              
305             =item * CPAN Ratings
306              
307             L
308              
309             =item * Search CPAN
310              
311             L
312              
313             =back
314              
315             =head1 ACKNOWLEDGMENTS
316              
317             Thanks to L for funding the development of this module and providing test resources.
318              
319             =head1 LICENSE AND COPYRIGHT
320              
321             Copyright 2014 Rishwanth Yeddula.
322              
323             This program is free software; you can redistribute it and/or modify it
324             under the terms of the the Artistic License (2.0). You may obtain a
325             copy of the full license at:
326              
327             L
328              
329             Any use, modification, and distribution of the Standard or Modified
330             Versions is governed by this Artistic License. By using, modifying or
331             distributing the Package, you accept this license. Do not use, modify,
332             or distribute the Package, if you do not accept this license.
333              
334             If your Modified Version has been derived from a Modified Version made
335             by someone other than you, you are nevertheless required to ensure that
336             your Modified Version complies with the requirements of this license.
337              
338             This license does not grant you the right to use any trademark, service
339             mark, tradename, or logo of the Copyright Holder.
340              
341             This license includes the non-exclusive, worldwide, free-of-charge
342             patent license to make, have made, use, offer to sell, sell, import and
343             otherwise transfer the Package with respect to any patent claims
344             licensable by the Copyright Holder that are necessarily infringed by the
345             Package. If you institute patent litigation (including a cross-claim or
346             counterclaim) against any party alleging that the Package constitutes
347             direct or contributory patent infringement, then this Artistic License
348             to you shall terminate on the date that such litigation is filed.
349              
350             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
351             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
352             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
353             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
354             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
355             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
356             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
357             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
358              
359              
360             =cut
361              
362             1; # End of WWW::Codeguard