line
stmt
bran
cond
sub
pod
time
code
1
package WWW::Codeguard;
2
3
2
2
47102
use strict;
2
4
2
55
4
2
2
9
use warnings FATAL => 'all', NONFATAL => 'uninitialized';
2
3
2
68
5
6
2
2
8
use Carp qw(croak);
2
4
2
114
7
2
2
634
use English qw(-no_match_vars);
2
3693
2
8
8
2
2
924
use JSON;
2
8333
2
11
9
10
=head1 NAME
11
12
WWW::Codeguard - Perl interface to interact with the Codeguard API
13
14
=head1 VERSION
15
16
Version 0.08
17
18
=cut
19
20
our $VERSION = '0.08';
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
5300
my ($class, $opts) = @_;
84
3
50
33
28
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
12
if ( exists $opts->{partner} and UNIVERSAL::isa($opts->{partner}, 'HASH') ) {
90
2
340
require WWW::Codeguard::Partner;
91
2
18
$partner_obj = WWW::Codeguard::Partner->new($opts->{api_url}, $opts->{partner});
92
}
93
94
3
100
66
17
if ( exists $opts->{user} and UNIVERSAL::isa($opts->{user}, 'HASH') ) {
95
2
408
require WWW::Codeguard::User;
96
2
12
$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
18
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
840
sub get_api_url { shift->{api_url}; }
127
128
4
4
0
26
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