File Coverage

blib/lib/RPC/ExtDirect/Client/API.pm
Criterion Covered Total %
statement 55 55 100.0
branch 7 10 70.0
condition 1 3 33.3
subroutine 12 12 100.0
pod 1 2 50.0
total 76 82 92.6


line stmt bran cond sub pod time code
1             package RPC::ExtDirect::Client::API;
2              
3 11     11   35088 use strict;
  11         18  
  11         294  
4 11     11   43 use warnings;
  11         10  
  11         284  
5 11     11   37 no warnings 'uninitialized'; ## no critic
  11         13  
  11         720  
6              
7 11     11   114 use JSON;
  11         153  
  11         128  
8              
9 11     11   2002 use RPC::ExtDirect::Util::Accessor;
  11         13  
  11         278  
10 11     11   35 use RPC::ExtDirect::Config;
  11         13  
  11         231  
11 11     11   451 use RPC::ExtDirect::API;
  11         3768  
  11         158  
12              
13 11     11   337 use base 'RPC::ExtDirect::API';
  11         24  
  11         6076  
14              
15             ### PUBLIC CLASS METHOD (CONSTRUCTOR) ###
16             #
17             # Instantiate a new API declaration from JavaScript code
18             #
19              
20             sub new_from_js {
21 21     21 0 1076 my ($class, %params) = @_;
22            
23 21   33     68 my $config = delete $params{config} || RPC::ExtDirect::Config->new();
24 21         36 my $js = delete $params{js};
25            
26 21         50 my $api_href = _decode_api($js);
27            
28             my $self = $class->SUPER::new_from_hashref(
29             config => $config,
30             api_href => $api_href->{actions},
31             type => $api_href->{type},
32             url => $api_href->{url},
33 21         218 %params,
34             );
35            
36 21         21750 return $self;
37             }
38              
39             ### PUBLIC INSTANCE METHOD ###
40             #
41             # Return an Action object or a list of Action objects, depending on context
42             #
43              
44             sub actions {
45 3     3 1 25226 my ($self, @actions) = @_;
46              
47 3 100       6 if ( wantarray ) {
48             my @set = @actions ? @actions
49 2 100       5 : keys %{ $self->{actions} }
  1         4  
50             ;
51            
52 2         4 my @result = map { $self->get_action_by_name($_) } @set;
  5         15  
53              
54 2         13 return @result;
55             }
56             else {
57 1         2 my $action_name = shift @actions;
58            
59 1         3 return $self->get_action_by_name($action_name);
60             };
61             }
62              
63             ### PUBLIC INSTANCE METHODS ###
64             #
65             # Read-write accessors
66             #
67              
68             RPC::ExtDirect::Util::Accessor->mk_accessors(
69             simple => [qw/ type url /],
70             );
71              
72             ############## PRIVATE METHODS BELOW ##############
73              
74             ### PRIVATE PACKAGE SUBROUTINE ###
75             #
76             # Decode API declaration and check basic constraints
77             #
78              
79             sub _decode_api {
80 21     21   29 my ($js) = @_;
81              
82 21         78 $js =~ s/^[^{]+//;
83            
84 21         37 my ($api_js) = eval { JSON->new->utf8(1)->decode_prefix($js) };
  21         571  
85              
86 21 50       128 die "Can't decode API declaration: $@\n" if $@;
87              
88 21 50       106 die "Empty API declaration\n"
89             unless 'HASH' eq ref $api_js;
90              
91             die "Unsupported API type\n"
92 21 50       168 unless $api_js->{type} =~ /remoting|polling/i;
93            
94             # Convert the JavaScript API definition to the format
95             # API::new_from_hashref expects
96 21         38 my $actions = $api_js->{actions};
97            
98             my %remote_actions
99 21         70 = map { $_ => _convert_action($actions->{$_}) } keys %$actions;
  13         61  
100            
101 21         41 $api_js->{actions} = \%remote_actions;
102            
103 21         54 return $api_js;
104             }
105              
106             ### PRIVATE PACKAGE SUBROUTINE ###
107             #
108             # Convert JavaScript Action definition to remote Action definition
109             #
110              
111             sub _convert_action {
112 13     13   18 my ($action_def) = @_;
113            
114 13         19 my %methods = map { delete $_->{name} => $_ } @$action_def;
  87         173  
115            
116             return {
117 13         97 remote => 1,
118             methods => \%methods,
119             };
120             }
121              
122             1;