File Coverage

blib/lib/DDG/Meta/ZeroClickInfoSpice.pm
Criterion Covered Total %
statement 124 156 79.4
branch 31 52 59.6
condition 0 3 0.0
subroutine 24 29 82.7
pod 0 5 0.0
total 179 245 73.0


line stmt bran cond sub pod time code
1             package DDG::Meta::ZeroClickInfoSpice;
2             our $AUTHORITY = 'cpan:DDG';
3             # ABSTRACT: Functions for generating a L factory
4             $DDG::Meta::ZeroClickInfoSpice::VERSION = '1018';
5 12     32   89 use strict;
  12         33  
  12         384  
6 12     21   83 use warnings;
  12         29  
  12         369  
7 12     12   73 use Carp;
  12         26  
  12         861  
8 12     12   2966 use DDG::ZeroClickInfo::Spice;
  12         43  
  12         536  
9 12     12   4693 use DDG::ZeroClickInfo::Spice::Data;
  12         44  
  12         393  
10 12     12   3930 use DDG::Rewrite;
  12         59  
  12         564  
11 12     12   131 use Package::Stash;
  12         36  
  12         419  
12 12     12   5435 use URI::Encode qw(uri_encode uri_decode);
  12         154004  
  12         1056  
13 12     12   4605 use IO::All;
  12         145221  
  12         166  
14              
15 11     11 0 68 sub zeroclickinfospice_attributes {qw(
16             call
17             call_type
18             caller
19             from
20             proxy_cache_valid
21             proxy_ssl_session_reuse
22             to
23             wrap_jsonp_callback
24             wrap_string_callback
25             headers
26             post_body
27             is_cached
28             is_unsafe
29             ttl
30             error_fallback
31             alt_to
32             upstream_timeouts
33             content_type_javascript
34             )}
35              
36             my %applied;
37              
38             sub apply_keywords {
39 11     11 0 38 my ( $class, $target ) = @_;
40              
41 11 50       70 return if exists $applied{$target};
42 11         32 $applied{$target} = undef;
43              
44 11         30 my ($callback, $path, $answer_type) = @{params_from_target($target)};
  11         38  
45              
46 11         131 my %zcispice_params = (
47             caller => $target,
48             call_type => 'include',
49             call => $path,
50             wrap_jsonp_callback => 0,
51             wrap_string_callback => 0,
52             content_type_javascript => 0,
53             accept_header => 0,
54             upstream_timeouts => +{},
55             );
56              
57 11         150 my $stash = Package::Stash->new($target);
58              
59             $stash->add_symbol('&call',sub {
60 0     0   0 my %params = %zcispice_params;
61 0         0 delete $params{'from'};
62 0         0 delete $params{'to'};
63 0         0 delete $params{'wrap_jsonp_callback'};
64 0         0 delete $params{'wrap_string_callback'};
65 0         0 delete $params{'accept_header'};
66 0         0 delete $params{'proxy_cache_valid'};
67 0         0 delete $params{'proxy_ssl_session_reuse'};
68 0         0 delete $params{'upstream_timeouts'};
69 0         0 delete $params{'content_type_javascript'};
70 0         0 return DDG::ZeroClickInfo::Spice->new(
71             %params,
72             );
73 11         178 });
74              
75             $stash->add_symbol('&spice_new',sub {
76 11     11   19 shift;
        0      
77 11         14 my @call;
78 11         93 my %params = %zcispice_params;
79 11         22 my $data;
80 11         22 delete $params{'from'};
81 11         19 delete $params{'to'};
82 11         26 for (@_) {
83 16 100       59 if (ref $_ eq 'HASH') {
    100          
    50          
    50          
84 1         2 for my $k (keys %{$_}) {
  1         3  
85 1         3 $params{$k} = $_->{$k};
86             };
87             } elsif (ref $_ eq 'DDG::ZeroClickInfo::Spice::Data') {
88 3 100       5 if ($data) {
89 2         6 $data->add_data($_);
90             } else {
91 1         2 $data = $_;
92             }
93             } elsif (ref $_ eq 'DDG::ZeroClickInfo::Spice') {
94 0         0 return $_;
95             } elsif (!defined $_) {
96             # do nothing
97             } else {
98 12         31 push @call, $_;
99             }
100             }
101 11 100       35 $params{'call_data'} = $data->data if $data;
102 11 50       25 if (@call) {
103 11 100       32 if ($params{'call_type'} eq 'include') {
    50          
104 10         70 $params{'call'} = $target->path.join('/',map { uri_encode($_,1) } @call);
  11         1019  
105             } elsif (scalar @call == 1) {
106 1         4 $params{'call'} = uri_encode($call[0]);
107             } else {
108 0         0 croak "DDG::ZeroClickInfo::Spice can't handle more then one value in return list on non include call_type";
109             }
110             }
111 11         16783 DDG::ZeroClickInfo::Spice->new(%params)
112 11         124 });
113              
114             $stash->add_symbol('&spice',sub {
115 9 50   9   56 if (ref $_[0] eq 'HASH') {
116 0         0 for (keys %{$_[0]}) {
  0         0  
117 0         0 $zcispice_params{check_zeroclickinfospice_key($_)} = $_[0]->{$_};
118             }
119             } else {
120 9         23 while (@_) {
121 9         22 my $key = shift;
122 9         16 my $value = shift;
123 9         24 $zcispice_params{check_zeroclickinfospice_key($key)} = $value;
124             }
125             }
126 11         109 });
127              
128 11     1   96 $stash->add_symbol('&callback',sub { $callback });
  1         8  
129              
130 11     11   106 $stash->add_symbol('&path',sub { $path });
  11         828  
131              
132 11         23 my $spice_js;
133              
134             $stash->add_symbol('&data',sub {
135 3 50   3   885 unshift @_, %{$_[0]} if ref $_[0] eq 'HASH';
  0         0  
136 3         8 my ( %data ) = @_;
137 3         41 return DDG::ZeroClickInfo::Spice::Data->new( data => \%data );
138 11         99 });
139              
140             $stash->add_symbol('&spice_js',sub {
141 0 0   0   0 return $spice_js if defined $spice_js;
142 0         0 my ( $self ) = @_;
143 0         0 $spice_js = "";
144 0 0 0     0 if ($target->can('module_share_dir') && (my $spice_js_file = $target->can('share')->('spice.js'))) {
145 0         0 $spice_js .= io($spice_js_file)->slurp;
146 0         0 $spice_js .= "\n";
147             }
148 0 0       0 if ($target->spice_call_type eq 'self') {
149 0         0 $spice_js .= $target->callback."();";
150             }
151 0         0 return $spice_js;
152 11         96 });
153              
154 11         26 my $rewrite;
155             $stash->add_symbol('&has_rewrite',sub {
156 2     2   12 defined $zcispice_params{'to'};
157 11         143 });
158              
159             $stash->add_symbol('&rewrite',sub {
160 1 50   3   6 unless (defined $rewrite) {
161 1 50       4 if ($target->has_rewrite) {
162 1         6 $rewrite = create_rewrite($callback, $path, \%zcispice_params);
163             }
164             else {
165 0         0 $rewrite = '';
166             }
167             }
168 1         18 return $rewrite;
169 11         100 });
170              
171             # make these accessbile, e.g. for duckpan
172             $stash->add_symbol('&alt_rewrites', sub {
173 2     4   8 my %rewrites;
174             # check if we have alternate end points to add
175 2 100       9 if(my $alt_to = $zcispice_params{alt_to}){
176 1         6 my ($base_target) = $target =~ /^(.+::)\w+$/;
177 1         6 while(my ($to, $params) = each %$alt_to){
178 2         9 check_zeroclickinfospice_key($_) for keys %$params;
179 2         5 my $target = "$base_target$to";
180 2         4 my ($callback, $path) = @{params_from_target($target)};
  2         4  
181 2         6 $rewrites{$to} = create_rewrite($callback, $path, $params);
182             }
183             }
184              
185 2         6 return \%rewrites;
186 11         118 });
187              
188             $stash->add_symbol('&get_nginx_conf',sub {
189 2     4   27 my $nginx_conf_func = $stash->get_symbol('&nginx_conf');
190 2 100       15 return $nginx_conf_func->(@_) if $nginx_conf_func;
191              
192             # (20151208 zt) just in case downstream can't handle undef ;-/
193 1         4 my $conf = '';
194 1 50       6 if($target->has_rewrite){
195 1         6 $conf = $target->rewrite->nginx_conf;
196             }
197              
198             # check if we have alternate end points to add
199 1         3 for my $r (values %{$target->alt_rewrites}){
  1         8  
200 0         0 $conf .= $r->nginx_conf;
201             }
202              
203 1         7 return $conf;
204 11         100 });
205              
206             ### SHOULD GET DEPRECATED vvvv ###
207 11     2   100 $stash->add_symbol('&spice_from',sub { $zcispice_params{'from'} });
  0         0  
208 11     0   93 $stash->add_symbol('&spice_to',sub { $zcispice_params{'to'} });
  0         0  
209 11     0   102 $stash->add_symbol('&spice_call_type',sub { $zcispice_params{'call_type'} });
  0         0  
210             ### ^^^^ ###
211              
212             }
213              
214             sub check_zeroclickinfospice_key {
215 11     11 0 21 my $key = shift;
216 11 50       26 if (grep { $key eq $_ } zeroclickinfospice_attributes) {
  198         318  
217 11         53 return $key;
218             } else {
219 0         0 croak $key." is not supported on DDG::ZeroClickInfo::Spice";
220             }
221             }
222              
223             sub params_from_target {
224 15     15 0 38 my $target = shift;
225              
226 15         69 my @parts = split('::',$target);
227 15         45 my $callback = join('_',map { s/([a-z])([A-Z])/$1_$2/g; lc; } @parts);
  45         185  
  45         146  
228 15         41 shift @parts;
229 15         40 my $path = '/js/'.join('/',map { s/([a-z])([A-Z])/$1_$2/g; lc; } @parts).'/';
  30         89  
  30         99  
230 15         35 shift @parts;
231 15         42 my $answer_type = lc(join(' ',@parts));
232              
233 15         73 return [$callback, $path, $answer_type];
234             }
235              
236             sub create_rewrite {
237 3     3 0 10 my ($callback, $path, $params) = @_;
238              
239             return DDG::Rewrite->new(
240             to => $params->{to},
241             defined $params->{from} ? ( from => $params->{from}) : (),
242             defined $params->{proxy_cache_valid} ? ( proxy_cache_valid => $params->{proxy_cache_valid} ) : (),
243             defined $params->{content_type_javascript} ? ( content_type_javascript => $params->{content_type_javascript} ) : (),
244             defined $params->{proxy_ssl_session_reuse} ? ( proxy_ssl_session_reuse => $params->{proxy_ssl_session_reuse} ) : (),
245             defined $params->{post_body} ? ( post_body => $params->{post_body} ) : (),
246             callback => $callback,
247             path => $path,
248             wrap_jsonp_callback => $params->{wrap_jsonp_callback},
249             wrap_string_callback => $params->{wrap_string_callback},
250             headers => $params->{headers},
251             error_fallback => $params->{error_fallback},
252             upstream_timeouts => $params->{upstream_timeouts},
253 3 50       81 );
    50          
    100          
    50          
    50          
254             }
255              
256             1;
257              
258             __END__