File Coverage

blib/lib/WG/API/Base.pm
Criterion Covered Total %
statement 67 89 75.2
branch 13 26 50.0
condition 3 5 60.0
subroutine 17 20 85.0
pod 1 1 100.0
total 101 141 71.6


line stmt bran cond sub pod time code
1             package WG::API::Base;
2              
3 6     6   51433 use Modern::Perl '2015';
  6         14  
  6         47  
4 6     6   932 use Moo::Role;
  6         12  
  6         38  
5              
6 6     6   4551 use WG::API::Error;
  6         15  
  6         203  
7 6     6   3747 use LWP::UserAgent;
  6         242330  
  6         523  
8 6     6   4173 use JSON;
  6         41541  
  6         34  
9 6     6   3883 use Data::Dumper;
  6         38643  
  6         411  
10 6     6   2029 use Log::Any qw($log);
  6         36613  
  6         32  
11 6     6   11736 use URI;
  6         12  
  6         134  
12 6     6   2314 use URI::QueryParam;
  6         4269  
  6         6774  
13              
14             =encoding utf8
15              
16             =head1 VERSION
17              
18             Version v0.12
19              
20             =cut
21              
22             our $VERSION = 'v0.12';
23              
24             =head1 SYNOPSIS
25              
26             Base class for all instances
27              
28             =cut
29              
30             requires '_api_uri';
31              
32             =head1 ATTRIBUTES
33              
34             =over 1
35              
36             =item I<application_id*>
37              
38             Required application id: L<https://developers.wargaming.net/documentation/guide/getting-started/>
39              
40             =cut
41              
42             has application_id => (
43             is => 'ro',
44             require => 1,
45             );
46              
47             =item I<language>
48              
49             =cut
50              
51             has language => (
52             is => 'ro',
53             default => sub {'ru'},
54             );
55              
56             =item I<status>
57              
58             Return request status
59              
60             =cut
61              
62             has status => ( is => 'rw', );
63              
64             =item I<response>
65              
66             Return response
67              
68             =cut
69              
70             has response => ( is => 'rw', );
71              
72             =item I<meta_data>
73              
74             Return meta data from response
75              
76             =cut
77              
78             has meta_data => ( is => 'rw', );
79              
80             =item I<debug>
81              
82             Get current debug mode
83              
84             =back
85              
86             =cut
87              
88             has debug => (
89             is => 'rw',
90             writer => 'set_debug',
91             default => '0',
92             );
93              
94             =head1 METHODS
95              
96             =over 1
97              
98             =item B<ua>
99              
100             Returns a user agent instance
101              
102             =cut
103              
104             #@returns LWP::UserAgent
105             has ua => (
106             is => 'ro',
107             default => sub { LWP::UserAgent->new() },
108             );
109              
110             =item B<error>
111              
112             Returns a WG::API::Error instance if defined;
113              
114             =cut
115              
116             #@returns WG::API::Error
117             has error => ( is => 'rw', );
118              
119             =item B<set_debug>
120              
121             Set debug mode
122              
123             =over 1
124              
125             =item B<log>
126              
127             Logger
128              
129             =back
130              
131             =back
132              
133             =cut
134              
135             sub log {
136 2     2 1 7 my ( $self, $event ) = @_;
137              
138 2 50       9 return unless $self->debug;
139              
140 2         26 $log->debug($event);
141             }
142              
143             sub _request {
144 1     1   5 my ( $self, $method, $uri, $params, $required_params, %passed_params ) = @_;
145              
146 1         4 $self->status(undef);
147              
148 1 50       6 unless ( $self->_validate_params( $required_params, %passed_params ) ) { #check required params
149 0         0 $self->status('error');
150 0         0 $self->error(
151             WG::API::Error->new(
152             code => '997',
153             message => 'missing a required field',
154             field => 'xxx',
155             value => 'xxx',
156             raw => 'xxx',
157             )
158             );
159 0         0 return;
160             }
161              
162 1         3 $method = "_" . $method; # add prefix for private methods
163              
164 1         7 $self->$method( $uri, $params, %passed_params );
165              
166 1 50       11 return $self->status eq 'ok' ? $self->response : undef;
167             }
168              
169             sub _validate_params {
170 1     1   3 my ( undef, $required_params, %passed_params ) = @_;
171              
172 1   50     4 $required_params //= [];
173 1 50       19 return if @$required_params > keys %passed_params;
174              
175 1         3 for (@$required_params) {
176 1 50       4 return unless defined $passed_params{$_};
177             }
178              
179 1         4 return 'passed';
180             }
181              
182             sub _get {
183 1     1   4 my ( $self, $uri, $params, %passed_params ) = @_;
184              
185             #@type HTTP::Response
186 1         4 my $response = $self->_raw_get( $self->_build_url($uri) . $self->_build_get_params( $params, %passed_params ) );
187              
188 1 50       1344934 return $self->_parse( $response->is_success ? decode_json $response->decoded_content : undef );
189             }
190              
191             sub _post {
192 0     0   0 my ( $self, $uri, $params, %passed_params ) = @_;
193              
194             #@type HTTP::Response
195 0         0 my $response = $self->_raw_post( $self->_build_url($uri), $self->_build_post_params( $params, %passed_params ) );
196              
197 0 0       0 return $self->_parse( $response->is_success ? decode_json $response->decoded_content : undef );
198             }
199              
200             sub _parse {
201 1     1   213 my ( $self, $response ) = @_;
202              
203 1 50       360 if ( !$response ) {
    50          
204 0         0 $response = {
205             status => 'error',
206             error => {
207             code => '999',
208             message => 'invalid api_uri',
209             field => 'xxx',
210             value => 'xxx',
211             raw => Dumper $response,
212             },
213             };
214             }
215             elsif ( !$response->{'status'} ) {
216 0         0 $response = {
217             status => 'error',
218             error => {
219             code => '998',
220             message => 'unknown status',
221             field => 'xxx',
222             value => 'xxx',
223             raw => Dumper $response,
224             },
225             };
226             }
227              
228 1         12 $self->status( delete $response->{'status'} );
229              
230 1 50       7 if ( $self->status eq 'error' ) {
231 1         14 $self->error( WG::API::Error->new( $response->{'error'} ) );
232             }
233             else {
234 0         0 $self->error(undef);
235 0         0 $self->meta_data( $response->{'meta'} );
236 0         0 $self->response( $response->{'data'} );
237             }
238              
239 1         3002 $self->log( $self->error );
240              
241 1         83 return;
242             }
243              
244             #@returns URI;
245             sub _build_url {
246 1     1   3 my ( $self, $uri ) = @_;
247              
248 1         8 my $url = URI->new( $self->_api_uri );
249 1         4938 $url->scheme("https");
250 1         3403 $url->path($uri);
251              
252 1         55 return $url->as_string;
253             }
254              
255             sub _build_get_params {
256 1     1   13 my ( $self, $params, %passed_params ) = @_;
257              
258 1         5 my $url = URI->new( "", "https" );
259 1         83 $url->query_param( application_id => $self->application_id );
260 1         150 foreach my $param (@$params) {
261 5 100 66     153 $passed_params{$param} = $self->language if $param eq 'language' && !exists $passed_params{$param};
262 5 100       16 $url->query_param( $param => $passed_params{$param} ) if defined $passed_params{$param};
263             }
264              
265 1         148 return $url->as_string;
266             }
267              
268             sub _build_post_params {
269 0     0   0 my ( $self, $params, %passed_params ) = @_;
270              
271 0         0 my %params;
272 0         0 @params{ keys %passed_params } = ();
273 0         0 delete @params{@$params};
274 0         0 delete $passed_params{$_} for keys %params;
275              
276 0         0 $passed_params{'application_id'} = $self->application_id;
277 0 0       0 $passed_params{'language'} = $self->language unless exists $passed_params{'language'};
278              
279 0         0 return \%passed_params;
280             }
281              
282             sub _raw_get {
283 1     1   8 my ( $self, $url ) = @_;
284              
285 1         7 $self->log( sprintf "METHOD GET, URL: %s\n", $url );
286              
287 1         97 return $self->ua->get($url);
288             }
289              
290             sub _raw_post {
291 0     0     my ( $self, $url, $params ) = @_;
292              
293 0           $self->log( sprintf "METHOD POST, URL %s, %s\n", $url, Dumper $params );
294              
295 0           return $self->ua->post( $url, $params );
296             }
297              
298             =head1 BUGS
299              
300             Please report any bugs or feature requests to C<cynovg at cpan.org>, or through the web interface at L<https://gitlab.com/cynovg/WG-API/issues>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
301              
302             =head1 SUPPORT
303              
304             You can find documentation for this module with the perldoc command.
305              
306             perldoc WG::API
307              
308             You can also look for information at:
309              
310             =over 4
311              
312             =item * RT: Gitlab's request tracker (report bugs here)
313              
314             L<https://gitlab.com/cynovg/WG-API/issues>
315              
316             =item * AnnoCPAN: Annotated CPAN documentation
317              
318             L<http://annocpan.org/dist/WG-API>
319              
320             =item * CPAN Ratings
321              
322             L<http://cpanratings.perl.org/d/WG-API>
323              
324             =item * Search CPAN
325              
326             L<https://metacpan.org/pod/WG::API>
327              
328             =back
329              
330              
331             =head1 ACKNOWLEDGEMENTS
332              
333             ...
334              
335             =head1 SEE ALSO
336              
337             WG API Reference L<https://developers.wargaming.net/>
338              
339             =head1 AUTHOR
340              
341             Cyrill Novgorodcev , C<< <cynovg at cpan.org> >>
342              
343             =head1 LICENSE AND COPYRIGHT
344              
345             Copyright 2015 Cyrill Novgorodcev.
346              
347             This program is free software; you can redistribute it and/or modify it
348             under the terms of the the Artistic License (2.0). You may obtain a
349             copy of the full license at:
350              
351             L<http://www.perlfoundation.org/artistic_license_2_0>
352              
353             Any use, modification, and distribution of the Standard or Modified
354             Versions is governed by this Artistic License. By using, modifying or
355             distributing the Package, you accept this license. Do not use, modify,
356             or distribute the Package, if you do not accept this license.
357              
358             If your Modified Version has been derived from a Modified Version made
359             by someone other than you, you are nevertheless required to ensure that
360             your Modified Version complies with the requirements of this license.
361              
362             This license does not grant you the right to use any trademark, service
363             mark, tradename, or logo of the Copyright Holder.
364              
365             This license includes the non-exclusive, worldwide, free-of-charge
366             patent license to make, have made, use, offer to sell, sell, import and
367             otherwise transfer the Package with respect to any patent claims
368             licensable by the Copyright Holder that are necessarily infringed by the
369             Package. If you institute patent litigation (including a cross-claim or
370             counterclaim) against any party alleging that the Package constitutes
371             direct or contributory patent infringement, then this Artistic License
372             to you shall terminate on the date that such litigation is filed.
373              
374             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
375             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
376             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
377             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
378             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
379             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
380             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
381             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
382              
383              
384             =cut
385              
386             1; # End of WG::API::Base