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   35974 use strict;
  11         11  
  11         303  
4 11     11   39 use warnings;
  11         15  
  11         262  
5 11     11   32 no warnings 'uninitialized'; ## no critic
  11         12  
  11         353  
6              
7 11     11   52 use JSON;
  11         190  
  11         115  
8              
9 11     11   1668 use RPC::ExtDirect::Util::Accessor;
  11         11  
  11         233  
10 11     11   39 use RPC::ExtDirect::Config;
  11         7  
  11         212  
11 11     11   450 use RPC::ExtDirect::API;
  11         3882  
  11         129  
12              
13 11     11   290 use base 'RPC::ExtDirect::API';
  11         23  
  11         5781  
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 1072 my ($class, %params) = @_;
22            
23 21   33     62 my $config = delete $params{config} || RPC::ExtDirect::Config->new();
24 21         31 my $js = delete $params{js};
25            
26 21         38 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         189 %params,
34             );
35            
36 21         22418 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 33104 my ($self, @actions) = @_;
46              
47 3 100       7 if ( wantarray ) {
48             my @set = @actions ? @actions
49 2 100       5 : keys %{ $self->{actions} }
  1         4  
50             ;
51            
52 2         5 my @result = map { $self->get_action_by_name($_) } @set;
  5         20  
53              
54 2         17 return @result;
55             }
56             else {
57 1         2 my $action_name = shift @actions;
58            
59 1         4 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   25 my ($js) = @_;
81              
82 21         66 $js =~ s/^[^{]+//;
83            
84 21         33 my ($api_js) = eval { JSON->new->utf8(1)->decode_prefix($js) };
  21         537  
85              
86 21 50       144 die "Can't decode API declaration: $@\n" if $@;
87              
88 21 50       87 die "Empty API declaration\n"
89             unless 'HASH' eq ref $api_js;
90              
91             die "Unsupported API type\n"
92 21 50       131 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         33 my $actions = $api_js->{actions};
97            
98             my %remote_actions
99 21         52 = map { $_ => _convert_action($actions->{$_}) } keys %$actions;
  13         48  
100            
101 21         57 $api_js->{actions} = \%remote_actions;
102            
103 21         53 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         103 remote => 1,
118             methods => \%methods,
119             };
120             }
121              
122             1;