File Coverage

blib/lib/WWW/Wookie/Connector/Service.pm
Criterion Covered Total %
statement 162 295 54.9
branch 15 70 21.4
condition 5 24 20.8
subroutine 40 45 88.8
pod 14 14 100.0
total 236 448 52.6


line stmt bran cond sub pod time code
1             # -*- cperl; cperl-indent-level: 4 -*-
2             # Copyright (C) 2010-2021, Roland van Ipenburg
3             package WWW::Wookie::Connector::Service v1.1.2;
4 4     4   244616 use strict;
  4         30  
  4         125  
5 4     4   36 use warnings;
  4         8  
  4         111  
6              
7 4     4   1284 use utf8;
  4         35  
  4         29  
8 4     4   170 use 5.020000;
  4         14  
9              
10 4     4   618 use Exception::Class;
  4         5061  
  4         29  
11 4     4   2446 use HTTP::Headers;
  4         28510  
  4         181  
12 4     4   2007 use HTTP::Request;
  4         49725  
  4         142  
13 4     4   2162 use HTTP::Request::Common;
  4         9737  
  4         316  
14 4     4   1947 use HTTP::Status qw(HTTP_CREATED HTTP_OK HTTP_UNAUTHORIZED HTTP_FORBIDDEN);
  4         19759  
  4         505  
15 4     4   2823 use LWP::UserAgent qw/POST/;
  4         81051  
  4         169  
16 4     4   3560 use Log::Log4perl qw(:easy get_logger);
  4         193672  
  4         24  
17 4     4   4681 use Moose qw/around has with/;
  4         963756  
  4         36  
18 4     4   28702 use Regexp::Common qw(URI);
  4         11241  
  4         20  
19 4     4   103472 use URI::Escape qw(uri_escape);
  4         9  
  4         193  
20 4     4   3399 use XML::Simple;
  4         37564  
  4         32  
21 4     4   1460 use namespace::autoclean '-except' => 'meta', '-also' => qr/^__/sxm;
  4         17103  
  4         50  
22              
23 4     4   1853 use WWW::Wookie::Connector::Exceptions;
  4         30  
  4         121  
24 4     4   1902 use WWW::Wookie::Server::Connection;
  4         18  
  4         227  
25 4     4   2810 use WWW::Wookie::User;
  4         18  
  4         180  
26 4     4   1843 use WWW::Wookie::Widget;
  4         13  
  4         167  
27 4     4   1808 use WWW::Wookie::Widget::Category;
  4         14  
  4         193  
28 4     4   1992 use WWW::Wookie::Widget::Property;
  4         14  
  4         190  
29 4     4   1367 use WWW::Wookie::Widget::Instance;
  4         15  
  4         146  
30 4     4   2019 use WWW::Wookie::Widget::Instances;
  4         15  
  4         147  
31              
32 4     4   32 use Readonly;
  4         10  
  4         18085  
33             ## no critic qw(ProhibitCallsToUnexportedSubs)
34             Readonly::Scalar my $DEFAULT_ICON =>
35             q{http://www.oss-watch.ac.uk/images/logo2.gif};
36             Readonly::Scalar my $TIMEOUT => 15;
37             Readonly::Scalar my $AGENT => q{WWW::Wookie/}
38             . $WWW::Wookie::Connector::Service::VERSION;
39             Readonly::Scalar my $TESTUSER => q{testuser};
40              
41             Readonly::Scalar my $EMPTY => q{};
42             Readonly::Scalar my $QUERY => q{?};
43             Readonly::Scalar my $SLASH => q{/};
44             Readonly::Scalar my $TRUE => 1;
45             Readonly::Scalar my $FALSE => 0;
46              
47             Readonly::Scalar my $MORE_ARGS => 4;
48             Readonly::Scalar my $MOST_ARGS => 5;
49              
50             Readonly::Scalar my $GET => q{GET};
51             Readonly::Scalar my $POST => q{POST};
52             Readonly::Scalar my $DELETE => q{DELETE};
53             Readonly::Scalar my $PUT => q{PUT};
54              
55             Readonly::Scalar my $ALL => q{all};
56             Readonly::Scalar my $PARTICIPANTS => q{participants};
57             Readonly::Scalar my $PROPERTIES => q{properties};
58             Readonly::Scalar my $SERVICES => q{services};
59             Readonly::Scalar my $WIDGETS => q{widgets};
60             Readonly::Scalar my $WIDGETINSTANCES => q{widgetinstances};
61              
62             Readonly::Scalar my $DEFAULT_SCHEME => q{http};
63             Readonly::Scalar my $VALID_SCHEMES => $DEFAULT_SCHEME . q{s?}; # http(s)
64              
65             Readonly::Hash my %LOG => (
66             'GET_USERS' => q{Getting users for instance of '%s'},
67             'USING_URL' => q{Using URL '%s'},
68             'RESPONSE_CODE' => q{Got response code %s},
69             'DO_REQUEST' => q{Requesting %s '%s'},
70             'ALL_TRUE' => q{Requesting all widgets},
71             );
72              
73             Readonly::Hash my %ERR => (
74             'NO_WIDGET_INSTANCE' => q{No Widget instance},
75             'NO_PROPERTIES_INSTANCE' => q{No properties instance},
76             'NO_USER_OBJECT' => q{No User object},
77             'NO_WIDGET_GUID' => q{No GUID nor widget object},
78             'MALFORMED_URL' => q{URL for supplied Wookie Server is malformed: %s},
79             'INCORRECT_PARTICIPANTS_REST_URL' =>
80             q{Participants rest URL is incorrect: %s},
81             'INCORRECT_PROPERTIES_REST_URL' => q{Properties rest URL is incorrect: %s},
82             'INVALID_API_KEY' => q{Invalid API key},
83             'HTTP' => q{%s<br />%s},
84             );
85             ## use critic
86              
87             ## no critic qw(ProhibitCallsToUnexportedSubs)
88             Log::Log4perl::easy_init($ERROR);
89             ## use critic
90              
91             has '_logger' => (
92             'is' => 'ro',
93             'isa' => 'Log::Log4perl::Logger',
94             'default' =>
95             sub { Log::Log4perl->get_logger('WWW::Wookie::Connector::Service') },
96             'reader' => 'getLogger',
97             );
98              
99             has '_conn' => (
100             'is' => 'rw',
101             'isa' => 'WWW::Wookie::Server::Connection',
102             'reader' => 'getConnection',
103             'writer' => '_setConnection',
104             );
105              
106             has '_locale' => (
107             'is' => 'rw',
108             'isa' => 'Str',
109             'reader' => 'getLocale',
110             'writer' => 'setLocale',
111             );
112              
113             ## no critic qw(Capitalization)
114             sub getAvailableServices {
115             ## use critic
116 1     1 1 689 my ( $self, $service_name ) = @_;
117 1         5 my $url = $self->_append_path($SERVICES);
118 1         20 __check_url( $url, $ERR{'MALFORMED_URL'} );
119 0         0 my $content = {};
120 0 0       0 if ($service_name) {
121 0         0 $url .= $SLASH . URI::Escape::uri_escape($service_name);
122             }
123 0 0       0 if ( $self->getLocale ) {
124 0         0 ${$content}{'locale'} = $self->getLocale;
  0         0  
125             }
126              
127 0         0 my %services = ();
128 0         0 my $response = $self->_do_request( $url, $content, $GET );
129 0         0 my $xml_obj = XML::Simple->new(
130             'ForceArray' => 1,
131             'KeyAttr' => { 'widget' => q{id}, 'service' => q{name} },
132             )->XMLin( $response->content );
133 0         0 while ( my ( $name, $value ) = each %{ ${$xml_obj}{'service'} } ) {
  0         0  
  0         0  
134 0         0 $self->getLogger->debug($name);
135 0         0 my $service = WWW::Wookie::Widget::Category->new( 'name' => $name );
136 0         0 while ( my ( $id, $value ) = each %{ ${$value}{'widget'} } ) {
  0         0  
  0         0  
137 0         0 $service->put(
138             WWW::Wookie::Widget->new( $id, $self->_parse_widget($value) ) );
139             }
140 0         0 $services{$name} = $service;
141             }
142 0         0 return values %services;
143             }
144              
145             ## no critic qw(Capitalization)
146             sub getAvailableWidgets {
147             ## use critic
148 1     1 1 683 my ( $self, $service ) = @_;
149 1         4 my %widgets = ();
150 1         5 my $url = $self->_append_path($WIDGETS);
151 1         16 my $content = {};
152 1 50 33     6 if ( !defined $service || $service eq $ALL ) {
    0          
153 1         34 $self->getLogger->debug( $LOG{'ALL_TRUE'} );
154 1         11 ${$content}{'all'} = q{true};
  1         3  
155             }
156             elsif ($service) {
157 0         0 $url .= $SLASH . URI::Escape::uri_escape($service);
158             }
159 1 50       36 if ( $self->getLocale ) {
160 0         0 ${$content}{'locale'} = $self->getLocale;
  0         0  
161             }
162 1         6 __check_url( $url, $ERR{'MALFORMED_URL'} );
163              
164 0         0 my $response = $self->_do_request( $url, $content, $GET );
165 0         0 my $xml_obj =
166             XML::Simple->new( 'ForceArray' => 1, 'KeyAttr' => 'id' )
167             ->XMLin( $response->content );
168 0         0 while ( my ( $id, $value ) = each %{ ${$xml_obj}{'widget'} } ) {
  0         0  
  0         0  
169             $widgets{$id} =
170             WWW::Wookie::Widget->new( $id,
171 0         0 $self->_parse_widget( ${ ${$xml_obj}{'widget'} }{$id} ) );
  0         0  
  0         0  
172             }
173 0         0 return values %widgets;
174             }
175              
176             has '_user' => (
177             'is' => 'ro',
178             'isa' => 'WWW::Wookie::User',
179             'reader' => '_getUser',
180             'writer' => '_setUser',
181             );
182              
183             ## no critic qw(Capitalization)
184             sub getUser {
185             ## use critic
186 1     1 1 4 my ( $self, $userid ) = @_;
187 1 50 33     4 if ( defined $userid && $userid =~ /$TESTUSER(\d+)/gsmxi ) {
188 0         0 return WWW::Wookie::User->new( $userid, qq{Test User $1} );
189             }
190 1         35 return $self->_getUser;
191             }
192              
193             ## no critic qw(Capitalization)
194             sub setUser {
195             ## use critic
196 0     0 1 0 my ( $self, $login, $screen ) = @_;
197 0         0 $self->_setUser( WWW::Wookie::User->new( $login, $screen ) );
198 0         0 return;
199             }
200              
201             has 'WidgetInstances' => (
202             'is' => 'rw',
203             'isa' => 'WWW::Wookie::Widget::Instances',
204             'default' => sub { WWW::Wookie::Widget::Instances->new() },
205             'writer' => '_setWidgetInstances',
206             );
207              
208             ## no critic qw(Capitalization)
209             sub getWidget {
210             ## use critic
211 0     0 1 0 my ( $self, $widget_id ) = @_;
212             my @widgets =
213 0         0 grep { $_->getIdentifier eq $widget_id } $self->getAvailableWidgets;
  0         0  
214 0         0 return shift @widgets;
215              
216             ## no critic qw(ProhibitCommentedOutCode)
217             # API method isn't implemented using proper id on the server.
218             #my $url = $self->_append_path($WIDGETS);
219             #if ( defined $widget_id ) {
220             # $url .= $SLASH . URI::Escape::uri_escape($widget_id);
221             #}
222             #__check_url($url, $ERR{'MALFORMED_URL'});
223              
224             #my $response = $self->_do_request( $url, {}, $GET );
225             #my $xs = XML::Simple->new( 'ForceArray' => 1, 'KeyAttr' => 'id' );
226             #my $xml_obj = $xs->XMLin( $response->content );
227             #return WWW::Wookie::Widget->new( $widget_id,
228             # $self->_parse_widget($xml_obj) );
229             ## use critic
230             }
231              
232             ## no critic qw(Capitalization)
233             sub getOrCreateInstance {
234             ## use critic
235 2     2 1 930 my ( $self, $widget_or_guid ) = @_;
236 2         4 my $guid = $widget_or_guid;
237 2 50       8 if ( q{WWW::Wookie::Widget} eq ref $widget_or_guid ) {
238 0         0 $guid = $widget_or_guid->getIdentifier;
239             }
240 2         5 my $result = eval {
241 2 100 66     12 if ( defined $guid && $guid eq $EMPTY ) {
242             ## no critic qw(RequireExplicitInclusion)
243             WookieConnectorException->throw(
244 1         8 'error' => $ERR{'NO_WIDGET_GUID'} );
245             ## use critic
246             }
247 1         10 my $url = $self->_append_path($WIDGETINSTANCES);
248 1         24 __check_url( $url, $ERR{'MALFORMED_URL'} );
249 0         0 my $content = { 'widgetid' => $guid };
250 0 0       0 if ( my $locale = $self->getLocale ) {
251 0         0 ${$content}{'locale'} = $locale;
  0         0  
252             }
253 0         0 my $response = $self->_do_request( $url, $content );
254 0 0       0 if ( $response->code == HTTP_CREATED ) {
255 0         0 $response = $self->_do_request( $url, $content );
256             }
257              
258 0         0 my $instance = $self->_parse_instance( $guid, $response->content );
259 0 0       0 if ($instance) {
260 0         0 $self->WidgetInstances->put($instance);
261 0         0 $self->addParticipant( $instance, $self->getUser );
262             }
263 0         0 return $instance;
264             };
265              
266 2 50       1155 if ( my $e = Exception::Class->caught('WookieConnectorException') ) {
267 2         112 $self->getLogger->error( $e->error );
268 2         892 $e->rethrow;
269 0         0 return $FALSE;
270             }
271 0         0 return $result;
272             }
273              
274             ## no critic qw(Capitalization)
275             sub getUsers {
276             ## use critic
277 0     0 1 0 my ( $self, $instance ) = @_;
278 0 0       0 if ( ref $instance ne q{WWW::Wookie::Widget::Instance} ) {
279 0         0 $instance = $self->getOrCreateInstance($instance);
280             }
281 0         0 $self->getLogger->debug( sprintf $LOG{'GET_USERS'},
282             $instance->getIdentifier );
283 0         0 my $url = $self->_append_path($PARTICIPANTS);
284 0         0 $self->getLogger->debug( sprintf $LOG{'USING_URL'}, $url );
285              
286 0         0 __check_url( $url, $ERR{'MALFORMED_URL'} );
287 0         0 my $response =
288             $self->_do_request( $url, { 'widgetid' => $instance->getIdentifier, },
289             $GET, );
290              
291 0 0       0 if ( $response->code > HTTP_OK ) {
292 0         0 __throw_http_err($response);
293             }
294 0         0 my $xml_obj =
295             XML::Simple->new( 'ForceArray' => 1, 'KeyAttr' => 'id' )
296             ->XMLin( $response->content );
297 0         0 my @users = ();
298 0         0 while ( my ( $id, $value ) = each %{ ${$xml_obj}{'participant'} } ) {
  0         0  
  0         0  
299             my $new_user = WWW::Wookie::User->new(
300             $id,
301             defined ${$value}{'displayName'} || $id,
302 0   0     0 defined ${$value}{'thumbnail_url'} || $EMPTY,
      0        
303             );
304 0         0 push @users, $new_user;
305             }
306 0         0 return @users;
307             }
308              
309             ## no critic qw(Capitalization)
310             sub addProperty {
311             ## use critic
312 1     1 1 4 my ( $self, $widget, $property ) = @_;
313 1         4 my $url = $self->_append_path($PROPERTIES);
314 1         20 __check_url( $url, $ERR{'INCORRECT_PROPERTIES_REST_URL'} );
315 0         0 my $response = $self->_do_request(
316             $url,
317             {
318             'widgetid' => $widget->getIdentifier,
319             'propertyname' => $property->getName,
320             'propertyvalue' => $property->getValue,
321             'is_public' => $property->getIsPublic,
322             },
323             $POST,
324             );
325 0 0 0     0 if ( $response->code == HTTP_OK || $response->code == HTTP_CREATED ) {
    0          
326 0         0 return $TRUE;
327             }
328             elsif ( $response->code > HTTP_CREATED ) {
329 0         0 return $response->content;
330             }
331 0         0 return $FALSE;
332             }
333              
334             ## no critic qw(Capitalization)
335             sub getProperty {
336             ## use critic
337 4     4 1 19 my ( $self, $widget_instance, $property_instance ) = @_;
338 4         10 my $url = $self->_append_path($PROPERTIES);
339 4         85 __check_widget($widget_instance);
340 3         9 __check_property($property_instance);
341 2         13 __check_url( $url, $ERR{'MALFORMED_URL'} );
342 1         39 my $response = $self->_do_request(
343             $url,
344             {
345             'widgetid' => $widget_instance->getIdentifier,
346             'propertyname' => $property_instance->getName,
347             },
348             $GET,
349             );
350 1 50       8 if ( !$response->is_success ) {
351 1         18 __throw_http_err($response);
352 0         0 return $FALSE;
353             }
354 0         0 return WWW::Wookie::Widget::Property->new( $property_instance->getName,
355             $response->content );
356              
357             }
358              
359             ## no critic qw(Capitalization)
360             sub setProperty {
361             ## use critic
362 3     3 1 707 my ( $self, $widget, $property ) = @_;
363 3         8 my $url = $self->_append_path($PROPERTIES);
364 3         42 my $result = eval {
365 3         13 __check_widget($widget);
366 2         7 __check_property($property);
367 1         12 __check_url( $url, $ERR{'INCORRECT_PROPERTIES_REST_URL'} );
368 0         0 my $response = $self->_do_request(
369             $url,
370             {
371             'widgetid' => $widget->getIdentifier,
372             'propertyname' => $property->getName,
373             'propertyvalue' => $property->getValue,
374             'is_public' => $property->getIsPublic,
375             },
376              
377             ## no critic qw(ProhibitFlagComments)
378             # TODO: $PUT breaks, but should be used instead of $POST
379             ## use critic
380             $POST,
381             );
382 0 0 0     0 if ( $response->code == HTTP_CREATED || $response == HTTP_OK ) {
383 0         0 return $property;
384             }
385             else {
386 0         0 __throw_http_err($response);
387             }
388             };
389 3 100       1645 if ( my $e = Exception::Class->caught('WookieConnectorException') ) {
390 2         105 $self->getLogger->error( $e->error );
391 2         696 $e->rethrow;
392 0         0 return $FALSE;
393             }
394 1 50       19 if ( my $e = Exception::Class->caught('WookieWidgetInstanceException') ) {
395 1         90 $self->getLogger->error( $e->error );
396 1         358 $e->rethrow;
397 0         0 return $FALSE;
398             }
399 0         0 return $result;
400             }
401              
402             ## no critic qw(Capitalization)
403             sub deleteProperty {
404             ## use critic
405 3     3 1 16 my ( $self, $widget, $property ) = @_;
406 3         8 my $url = $self->_append_path($PROPERTIES);
407 3         59 __check_url( $url, $ERR{'INCORRECT_PROPERTIES_REST_URL'} );
408 2         9 __check_widget($widget);
409 1         5 __check_property($property);
410 0         0 my $response = $self->_do_request(
411             $url,
412             {
413             'widgetid' => $widget->getIdentifier,
414             'propertyname' => $property->getName,
415             },
416             $DELETE,
417             );
418 0 0       0 if ( $response->code == HTTP_OK ) {
419 0         0 return $TRUE;
420             }
421 0         0 return $FALSE;
422             }
423              
424             ## no critic qw(Capitalization)
425             sub addParticipant {
426             ## use critic
427 2     2 1 711 my ( $self, $widget_instance, $user ) = @_;
428 2         8 __check_widget($widget_instance);
429 1         4 my $url = $self->_append_path($PARTICIPANTS);
430 1         18 __check_url( $url, $ERR{'INCORRECT_PARTICIPANTS_REST_URL'} );
431 0         0 my $response = $self->_do_request(
432             $url,
433             {
434             'widgetid' => $widget_instance->getIdentifier,
435             'participant_id' => $self->getUser->getLoginName,
436             'participant_display_name' => $user->getScreenName,
437             'participant_thumbnail_url' => $user->getThumbnailUrl,
438             },
439             );
440 0 0       0 if ( $response->code == HTTP_OK ) {
    0          
    0          
441 0         0 return $TRUE;
442             }
443             elsif ( $response->code == HTTP_CREATED ) {
444 0         0 return $TRUE;
445             }
446             elsif ( $response->code > HTTP_CREATED ) {
447 0         0 return $response->content;
448             }
449 0         0 return $FALSE;
450             }
451              
452             ## no critic qw(Capitalization)
453             sub deleteParticipant {
454             ## use critic
455 2     2 1 689 my ( $self, $widget, $user ) = @_;
456 2         8 __check_widget($widget);
457 1         5 my $url = $self->_append_path($PARTICIPANTS);
458 1         20 __check_url( $url, $ERR{'INCORRECT_PARTICIPANTS_REST_URL'} );
459 0         0 my $response = $self->_do_request(
460             $url,
461             {
462             'widgetid' => $widget->getIdentifier,
463             'participant_id' => $self->getUser->getLoginName,
464             'participant_display_name' => $user->getScreenName,
465             'participant_thumbnail_url' => $user->getThumbnailUrl,
466             },
467             $DELETE,
468             );
469 0 0       0 if ( $response->code == HTTP_OK ) {
    0          
    0          
470 0         0 return $TRUE;
471             }
472             elsif ( $response->code == HTTP_CREATED ) {
473 0         0 return $TRUE;
474             }
475             elsif ( $response->code > HTTP_CREATED ) {
476 0         0 __throw_http_err($response);
477             }
478 0         0 return $FALSE;
479             }
480              
481             ## no critic qw(Capitalization)
482             sub _setWidgetInstancesHolder {
483             ## use critic
484 9     9   15 my $self = shift;
485 9         375 $self->_setWidgetInstances( WWW::Wookie::Widget::Instances->new );
486 9         48 return;
487             }
488              
489             has '_ua' => (
490             'is' => 'rw',
491             'isa' => 'LWP::UserAgent',
492             'default' => sub {
493             LWP::UserAgent->new(
494             'timeout' => $TIMEOUT,
495             'agent' => $AGENT,
496             );
497             },
498             );
499              
500             around 'BUILDARGS' => sub {
501             my $orig = shift;
502             my $class = shift;
503              
504             if ( @_ == $MORE_ARGS ) {
505             push @_, $EMPTY;
506             }
507             if ( @_ == $MOST_ARGS && !ref $_[0] ) {
508             my ( $url, $api_key, $shareddata_key, $loginname, $screenname ) = @_;
509             return $class->$orig(
510             '_user' => WWW::Wookie::User->new( $loginname, $screenname ),
511             '_conn' => WWW::Wookie::Server::Connection->new(
512             $url, $api_key, $shareddata_key,
513             ),
514             );
515             }
516             return $class->$orig(@_);
517             };
518              
519             sub BUILD {
520 9     9 1 1359 my $self = shift;
521 9         39 $self->_setWidgetInstancesHolder;
522 9         248 return;
523             }
524              
525             sub _append_path {
526 16     16   39 my ( $self, $path ) = @_;
527 16         565 return $self->getConnection->getURL . URI::Escape::uri_escape($path);
528             }
529              
530             sub __check_url {
531             my ( $url, $message ) = @_;
532             if ( $url !~ m{^$RE{URI}{HTTP}{-keep}{ '-scheme' => $VALID_SCHEMES }$}smx )
533             {
534             ## no critic qw(RequireExplicitInclusion)
535             WookieConnectorException->throw( 'error' => sprintf $message, $url );
536             ## use critic
537             }
538             return;
539             }
540              
541             sub __check_widget {
542             my ($ref) = @_;
543             if ( ref $ref ne q{WWW::Wookie::Widget::Instance} ) {
544             ## no critic qw(RequireExplicitInclusion)
545             WookieWidgetInstanceException->throw(
546             ## use critic
547             'error' => $ERR{'NO_WIDGET_INSTANCE'},
548             );
549             }
550             return;
551             }
552              
553             sub __check_property {
554             my ($ref) = @_;
555             if ( ref $ref ne q{WWW::Wookie::Widget::Property} ) {
556             ## no critic qw(RequireExplicitInclusion)
557             WookieConnectorException->throw(
558             ## use critic
559             'error' => $ERR{'NO_PROPERTIES_INSTANCE'},
560             );
561             }
562             return;
563             }
564              
565             sub __throw_http_err {
566             my ($response) = @_;
567             ## no critic qw(RequireExplicitInclusion)
568             WookieConnectorException->throw(
569             ## use critic
570             'error' => sprintf $ERR{'HTTP'},
571             $response->headers->as_string, $response->content,
572             );
573             return;
574             }
575              
576             sub _do_request {
577 1     1   5 my ( $self, $url, $payload, $method ) = @_;
578              
579             # Widgets and Services request doesn't require API key stuff:
580 1 50       7 if ( $url !~ m{/(?:widgets|services)(?:[?/]|$)}gismx ) {
581             $payload = {
582             'api_key' => $self->getConnection->getApiKey,
583             'shareddatakey' => $self->getConnection->getSharedDataKey,
584             'userid' => $self->getUser->getLoginName,
585 1         34 %{$payload},
  1         5  
586             };
587             }
588 1 50       5 if ( !defined $method ) {
589 0         0 $method = $POST;
590             }
591              
592 1 50       3 if ( ( my $content = [ POST $url, [ %{$payload} ] ]->[0]->content ) ne
  1         7  
593             $EMPTY )
594             {
595 1         8182 $url .= $QUERY . $content;
596             }
597 1         49 $self->getLogger->debug( sprintf $LOG{'DO_REQUEST'}, $method, $url );
598 1         33 my $request = HTTP::Request->new(
599             $method => $url,
600             HTTP::Headers->new(),
601             );
602 1         171 my $response = $self->_ua->request($request);
603 1         43882 $self->getLogger->debug( sprintf $LOG{'RESPONSE_CODE'}, $response->code );
604 1 50 33     40 if ( $response->code == HTTP_UNAUTHORIZED
605             || $response->code == HTTP_FORBIDDEN )
606             {
607             ## no critic qw(RequireExplicitInclusion)
608 0         0 WookieConnectorException->throw( 'error' => $ERR{'INVALID_API_KEY'} );
609             ## use critic
610             }
611 1         34 return $response;
612             }
613              
614             sub _parse_instance {
615 0     0     my ( $self, $guid, $xml ) = @_;
616 0           my $xml_obj =
617             XML::Simple->new( 'ForceArray' => 1, 'KeyAttr' => 'id' )->XMLin($xml);
618 0 0         if (
619             my $instance = WWW::Wookie::Widget::Instance->new(
620 0           ${$xml_obj}{'url'}[0], $guid,
621 0           ${$xml_obj}{'title'}[0], ${$xml_obj}{'height'}[0],
  0            
622 0           ${$xml_obj}{'width'}[0],
623             )
624             )
625             {
626 0           $self->WidgetInstances->put($instance);
627 0           $self->addParticipant( $instance, $self->getUser );
628 0           return $instance;
629             }
630 0           return;
631             }
632              
633             sub _parse_widget {
634 0     0     my ( $self, $xml ) = @_;
635 0           my $title = ${ ${$xml}{'name'}[0] }{'content'};
  0            
  0            
636             my $description =
637 0           ref ${$xml}{'description'}[0]
638 0           ? ${ ${$xml}{'description'}[0] }{'content'}
  0            
639 0 0         : ${$xml}{'description'}[0];
  0            
640             my $icon =
641 0           ref ${$xml}{'icon'}[0]
642 0           ? ${ ${$xml}{'icon'}[0] }{'content'}
  0            
643 0 0         : ${$xml}{'icon'}[0];
  0            
644 0 0         if ( !$icon ) {
645 0           $icon = $DEFAULT_ICON;
646             }
647 0           return ( $title, $description, $icon );
648             }
649              
650             with 'WWW::Wookie::Connector::Service::Interface';
651              
652 4     4   42 no Moose;
  4         13  
  4         33  
653              
654             __PACKAGE__->meta->make_immutable;
655              
656             1;
657              
658             __END__
659              
660             =encoding utf8
661              
662             =for stopwords Bitbucket API Readonly Wookie guid Ipenburg login MERCHANTABILITY
663              
664             =head1 NAME
665              
666             WWW::Wookie::Connector::Service - Wookie connector service, handles all the
667             data requests and responses
668              
669             =head1 VERSION
670              
671             This document describes WWW::Wookie::Connector::Service version C<v1.1.2>
672              
673             =head1 SYNOPSIS
674              
675             use WWW::Wookie::Connector::Service;
676              
677             =head1 DESCRIPTION
678              
679             =head1 SUBROUTINES/METHODS
680              
681             This module is an implementation of the
682             L<WWW::Wookie::Connector::Service::Interface
683             |WWW::Wookie::Connector::Service::Interface/"SUBROUTINES/METHODS">.
684              
685             =head2 C<new>
686              
687             Create a new connector
688              
689             =over
690              
691             =item 1. URL to Wookie host as string
692              
693             =item 2. Wookie API key as string
694              
695             =item 3. Shared data key to use as string
696              
697             =item 4. User login name
698              
699             =item 5. User display name
700              
701             =back
702              
703             =head2 C<getAvailableServices>
704              
705             Get a all available service categories in the server. Returns an array of
706             L<WWWW::Wookie::Widget::Category|WW::Wookie::Widget::Category> objects.
707             Throws a C<WookieConnectorException>.
708              
709             =head2 C<getAvailableWidgets>
710              
711             Get all available widgets in the server, or only the available widgets in the
712             specified service category. Returns an array of
713             L<WWW::Wookie::Widget|WWW::Wookie::Widget> objects, otherwise false. Throws a
714             C<WookieConnectorException>.
715              
716             =over
717              
718             =item 1. Service category name as string
719              
720             =back
721              
722             =head2 C<getWidget>
723              
724             Get the details of the widget specified by it's identifier. Returns a
725             L<WWW::Wookie::Widget|WWW::Wookie::Widget> object.
726              
727             =over
728              
729             =item 1. The identifier of an available widget
730              
731             =back
732              
733             =head2 C<getConnection>
734              
735             Get the currently active connection to the Wookie server. Returns a
736             L<WWW::Wookie::Server::Connection|WWW::Wookie::Server::Connection> object.
737              
738             =head2 C<setUser>
739              
740             Set the current user.
741              
742             =over
743              
744             =item 1. User name for the current Wookie connection
745              
746             =item 2. Screen name for the current Wookie connection
747              
748             =back
749              
750             =head2 C<getUser>
751              
752             Retrieve the details of the current user. Returns an instance of the user as a
753             L<WWW::Wookie::User|WWW::Wookie::User> object.
754              
755             =head2 C<getOrCreateInstance>
756              
757             Get or create a new instance of a widget. The current user will be added as a
758             participant. Returns a
759             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object if
760             successful, otherwise false. Throws a C<WookieConnectorException>.
761              
762             =over
763              
764             =item 1. Widget as guid string or a L<WWW::Wookie::Widget|WWW::Wookie::Widget>
765             object
766              
767             =back
768              
769             =head2 C<addParticipant>
770              
771             Add a participant to a widget. Returns true if successful, otherwise false.
772             Throws a C<WookieWidgetInstanceException> or a C<WookieConnectorException>.
773              
774             =over
775              
776             =item 1. Instance of widget as
777             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
778              
779             =item 2. Instance of user as L<WWW::Wookie::User|WWW::Wookie::User> object
780              
781             =back
782              
783             =head2 C<deleteParticipant>
784              
785             Delete a participant. Returns true if successful, otherwise false. Throws a
786             C<WookieWidgetInstanceException> or a C<WookieConnectorException>.
787              
788             =over
789              
790             =item 1. Instance of widget as
791             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
792              
793             =item 2. Instance of user as L<WWW::Wookie::User|WWW::Wookie::User> object
794              
795             =back
796              
797             =head2 C<getUsers>
798              
799             Get all participants of the current widget. Returns an array of
800             L<WWW::Wookie::User|WWW::Wookie::User> instances. Throws a
801             C<WookieConnectorException>.
802              
803             =over
804              
805             =item 1. Instance of widget as
806             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
807              
808             =back
809              
810             =head2 C<addProperty>
811              
812             Adds a new property. Returns true if successful, otherwise false. Throws a
813             C<WookieConnectorException>.
814              
815             =over
816              
817             =item 1. Instance of widget as
818             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
819              
820             =item 2. Instance of property as
821             L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property> object
822              
823             =back
824              
825             =head2 C<setProperty>
826              
827             Set a new property. Returns the property as
828             L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property> if successful,
829             otherwise false. Throws a C<WookieWidgetInstanceException> or a
830             C<WookieConnectorException>.
831              
832             =over
833              
834             =item 1. Instance of widget as
835             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
836              
837             =item 2. Instance of property as
838             L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property> object
839              
840             =back
841              
842             =head2 C<getProperty>
843              
844             Get a property. Returns the property as
845             L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property> if successful,
846             otherwise false. Throws a C<WookieWidgetInstanceException> or a
847             C<WookieConnectorException>.
848              
849             =over
850              
851             =item 1. Instance of widget as
852             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
853              
854             =item 2. Instance of property as
855             L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property> object
856              
857             =back
858              
859             =head2 C<deleteProperty>
860              
861             Delete a property. Returns true if successful, otherwise false. Throws a
862             C<WookieWidgetInstanceException> or a C<WookieConnectorException>.
863              
864             =over
865              
866             =item 1. Instance of widget as
867             L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance> object
868              
869             =item 2. Instance of property as
870             L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property> object
871              
872             =back
873              
874             =head2 C<setLocale>
875              
876             Set a locale.
877              
878             =over
879              
880             =item 1. Locale as string
881              
882             =back
883              
884             =head2 C<getLocale>
885              
886             Get the current locale setting. Returns current locale as string.
887              
888             =head2 C<BUILD>
889              
890             The Moose internal BUILD method.
891              
892             =head1 CONFIGURATION AND ENVIRONMENT
893              
894             =head1 DEPENDENCIES
895              
896             =over 4
897              
898             =item * L<HTTP::Headers|HTTP::Headers>
899              
900             =item * L<HTTP::Request|HTTP::Request>
901              
902             =item * L<HTTP::Request::Common|HTTP::Request::Common>
903              
904             =item * L<HTTP::Status|HTTP::Status>
905              
906             =item * L<LWP::UserAgent|LWP::UserAgent>
907              
908             =item * L<Log::Log4perl|Log::Log4perl>
909              
910             =item * L<Moose|Moose>
911              
912             =item * L<Moose::Util::TypeConstraints|Moose::Util::TypeConstraints>
913              
914             =item * L<Readonly|Readonly>
915              
916             =item * L<Regexp::Common|Regexp::Common>
917              
918             =item * L<WWW::Wookie::Connector::Exceptions|WWW::Wookie::Connector::Exceptions>
919              
920             =item * L<WWW::Wookie::Server::Connection|WWW::Wookie::Server::Connection>
921              
922             =item * L<WWW::Wookie::User|WWW::Wookie::User>
923              
924             =item * L<WWW::Wookie::Widget::Instance|WWW::Wookie::Widget::Instance>
925              
926             =item * L<WWW::Wookie::Widget::Instances|WWW::Wookie::Widget::Instances>
927              
928             =item * L<WWW::Wookie::Widget::Property|WWW::Wookie::Widget::Property>
929              
930             =item * L<WWW::Wookie::Widget|WWW::Wookie::Widget>
931              
932             =item * L<XML::Simple|XML::Simple>
933              
934             =item * L<namespace::autoclean|namespace::autoclean>
935              
936             =back
937              
938             =head1 INCOMPATIBILITIES
939              
940             =head1 DIAGNOSTICS
941              
942             =head1 BUGS AND LIMITATIONS
943              
944             Please report any bugs or feature requests at
945             L<Bitbucket|https://bitbucket.org/rolandvanipenburg/www-wookie/issues>.
946              
947             =head1 AUTHOR
948              
949             Roland van Ipenburg, E<lt>roland@rolandvanipenburg.comE<gt>
950              
951             =head1 LICENSE AND COPYRIGHT
952              
953             Copyright 2010-2021 by Roland van Ipenburg
954              
955             This library is free software; you can redistribute it and/or modify
956             it under the same terms as Perl itself, either Perl version 5.14.0 or,
957             at your option, any later version of Perl 5 you may have available.
958              
959             =head1 DISCLAIMER OF WARRANTY
960              
961             BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
962             FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
963             OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
964             PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
965             EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
966             WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
967             ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
968             YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
969             NECESSARY SERVICING, REPAIR, OR CORRECTION.
970              
971             IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
972             WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
973             REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENSE, BE
974             LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
975             OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
976             THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
977             RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
978             FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
979             SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
980             SUCH DAMAGES.
981              
982             =cut