line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Plack::Middleware::MangleEnv; |
2
|
|
|
|
|
|
|
|
3
|
8
|
|
|
8
|
|
5045
|
use strict; |
|
8
|
|
|
|
|
8
|
|
|
8
|
|
|
|
|
192
|
|
4
|
8
|
|
|
8
|
|
25
|
use warnings; |
|
8
|
|
|
|
|
9
|
|
|
8
|
|
|
|
|
231
|
|
5
|
8
|
|
|
8
|
|
28
|
use Carp qw< confess >; |
|
8
|
|
|
|
|
8
|
|
|
8
|
|
|
|
|
416
|
|
6
|
8
|
|
|
8
|
|
3442
|
use English qw< -no_match_vars >; |
|
8
|
|
|
|
|
5269
|
|
|
8
|
|
|
|
|
30
|
|
7
|
|
|
|
|
|
|
{ our $VERSION = '0.001'; } |
8
|
|
|
|
|
|
|
|
9
|
8
|
|
|
8
|
|
2741
|
use parent 'Plack::Middleware'; |
|
8
|
|
|
|
|
237
|
|
|
8
|
|
|
|
|
49
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Note: manglers in "manglers" here are totally reconstructured and not |
12
|
|
|
|
|
|
|
# necessarily straightly coming from the "mangle" field in the original |
13
|
|
|
|
|
|
|
sub call { |
14
|
6
|
|
|
6
|
1
|
90549
|
my ($self, $env) = @_; |
15
|
|
|
|
|
|
|
VAR: |
16
|
6
|
|
|
|
|
10
|
for my $mangler (@{$self->{_manglers}}) { |
|
6
|
|
|
|
|
25
|
|
17
|
40
|
|
|
|
|
62
|
my ($key, $value) = @$mangler; |
18
|
40
|
100
|
100
|
|
|
208
|
if ($value->{remove}) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
19
|
5
|
|
|
|
|
9
|
delete $env->{$key}; |
20
|
|
|
|
|
|
|
} |
21
|
|
|
|
|
|
|
elsif (exists($env->{$key}) && (!$value->{override})) { |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# $env->{$key} is already OK here, do nothing! |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
elsif (exists $value->{value}) { # set unconditionally |
26
|
12
|
|
|
|
|
22
|
$env->{$key} = $value->{value}; |
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
elsif (exists $value->{env}) { # copy from other item in $env |
29
|
6
|
|
|
|
|
14
|
$env->{$key} = $env->{$value->{env}}; |
30
|
|
|
|
|
|
|
} |
31
|
|
|
|
|
|
|
elsif (exists $value->{ENV}) { # copy from %ENV |
32
|
2
|
|
|
|
|
7
|
$env->{$key} = $ENV{$value->{ENV}}; |
33
|
|
|
|
|
|
|
} |
34
|
|
|
|
|
|
|
elsif (exists $value->{sub}) { |
35
|
11
|
|
|
|
|
45
|
$value->{sub}->($env->{$key}, $env, $key); |
36
|
|
|
|
|
|
|
} |
37
|
|
|
|
|
|
|
else { |
38
|
0
|
|
|
|
|
0
|
require Data::Dumper; |
39
|
0
|
|
|
|
|
0
|
my $package = ref $self; |
40
|
0
|
|
|
|
|
0
|
confess "BUG in $package, value for '$key' not as expected: ", |
41
|
|
|
|
|
|
|
Data::Dumper::Dumper($value); |
42
|
|
|
|
|
|
|
} ## end else [ if ($value->{remove}) ] |
43
|
|
|
|
|
|
|
} ## end VAR: for my $mangler (@{$self...}) |
44
|
|
|
|
|
|
|
|
45
|
6
|
|
|
|
|
54
|
return $self->app()->($env); |
46
|
|
|
|
|
|
|
} ## end sub call |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# Initialization code, this is executed once at application startup |
49
|
|
|
|
|
|
|
# so we are more relaxed about *not* calling too many subs |
50
|
|
|
|
|
|
|
sub prepare_app { |
51
|
9
|
|
|
9
|
1
|
3008
|
my ($self) = @_; |
52
|
9
|
|
|
|
|
17
|
$self->_normalize_input_structure(); # reorganize internally |
53
|
9
|
|
|
|
|
8
|
my @inputs = @{$self->{manglers}}; # we will consume @inputs |
|
9
|
|
|
|
|
23
|
|
54
|
9
|
|
|
|
|
36
|
$self->{_manglers} = []; |
55
|
|
|
|
|
|
|
|
56
|
9
|
|
|
|
|
25
|
while (@inputs) { |
57
|
43
|
|
|
|
|
52
|
my ($key, $value) = splice @inputs, 0, 2; |
58
|
43
|
|
|
|
|
80
|
$self->push_manglers( |
59
|
|
|
|
|
|
|
$self->generate_manglers($key, $value, {override => 1})); |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
7
|
|
|
|
|
29
|
return $self; |
63
|
|
|
|
|
|
|
} ## end sub prepare_app |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
sub push_manglers { |
66
|
41
|
|
|
41
|
1
|
33
|
my $self = shift; |
67
|
41
|
|
|
|
|
27
|
push @{$self->{_manglers}}, @_; |
|
41
|
|
|
|
|
66
|
|
68
|
41
|
|
|
|
|
99
|
return $self; |
69
|
|
|
|
|
|
|
} ## end sub push_manglers |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub generate_manglers { # simple dispatch method |
72
|
43
|
|
|
43
|
1
|
33
|
my $self = shift; |
73
|
43
|
|
|
|
|
35
|
my ($key, $value) = @_; # ignoring rest of parameters here |
74
|
43
|
|
|
|
|
37
|
my $ref = ref $value; |
75
|
43
|
100
|
|
|
|
69
|
return $self->generate_immediate_manglers(value => @_) unless $ref; |
76
|
36
|
100
|
|
|
|
62
|
return $self->generate_array_manglers(@_) if $ref eq 'ARRAY'; |
77
|
30
|
100
|
|
|
|
69
|
return $self->generate_hash_manglers(@_) if $ref eq 'HASH'; |
78
|
6
|
50
|
|
|
|
17
|
return $self->generate_code_manglers(@_) if $ref eq 'CODE'; |
79
|
|
|
|
|
|
|
|
80
|
0
|
|
|
|
|
0
|
confess "invalid reference '$ref' for '$key'"; |
81
|
|
|
|
|
|
|
} ## end sub generate_manglers |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
sub generate_immediate_manglers { |
84
|
41
|
|
|
41
|
1
|
57
|
my ($self, $type, $key, $value, $opts) = @_; |
85
|
41
|
|
|
|
|
171
|
return [$key => {%$opts, $type => $value}]; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub generate_array_manglers { |
89
|
6
|
|
|
6
|
1
|
15
|
my ($self, $key, $aref, $defaults) = @_; |
90
|
6
|
100
|
|
|
|
16
|
return $self->generate_remove_manglers($key, undef, $defaults) |
91
|
|
|
|
|
|
|
if @$aref == 0; |
92
|
3
|
50
|
|
|
|
10
|
return $self->generate_immediate_manglers(value => $key, $aref->[0], $defaults) |
93
|
|
|
|
|
|
|
if @$aref == 1; |
94
|
|
|
|
|
|
|
|
95
|
0
|
|
|
|
|
0
|
my @values = $self->stringified_list(@$aref); |
96
|
0
|
|
|
|
|
0
|
confess "array for '$key' has more than one value (@values)"; |
97
|
|
|
|
|
|
|
} |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub generate_code_manglers { |
100
|
10
|
|
|
10
|
1
|
13
|
my ($self, $key, $sub, $opts) = @_; |
101
|
10
|
100
|
|
|
|
15
|
$sub = $self->wrap_code($sub) |
102
|
|
|
|
|
|
|
or confess "sub for '$key' is not a CODE reference"; |
103
|
8
|
|
|
|
|
14
|
return $self->generate_immediate_manglers(sub => $key, $sub, $opts); |
104
|
|
|
|
|
|
|
} |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
sub generate_hash_manglers { |
107
|
24
|
|
|
24
|
1
|
34
|
my ($self, $key, $hash, $defaults) = @_; |
108
|
|
|
|
|
|
|
|
109
|
24
|
|
|
|
|
48
|
my %opt = %$defaults; |
110
|
24
|
100
|
|
|
|
45
|
$opt{override} = delete($hash->{override}) if exists($hash->{override}); |
111
|
|
|
|
|
|
|
|
112
|
24
|
50
|
|
|
|
58
|
if ((my @keys = keys %$hash) > 1) { |
113
|
0
|
|
|
|
|
0
|
@keys = $self->stringified_list(@keys); |
114
|
0
|
|
|
|
|
0
|
confess "too many options ('@keys') for '$key'"; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
24
|
|
|
|
|
54
|
my ($type, $value) = %$hash; |
118
|
24
|
50
|
|
|
|
113
|
my $cb = $self->can('generate_hash_manglers_' . $type) |
119
|
|
|
|
|
|
|
or confess "unknown option '$type' for '$key'"; |
120
|
|
|
|
|
|
|
|
121
|
24
|
|
|
|
|
45
|
return $cb->($self, $key, $value, \%opt); |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub generate_hash_manglers_ENV { |
125
|
4
|
|
|
4
|
1
|
5
|
my $self = shift; |
126
|
4
|
|
|
|
|
6
|
return $self->generate_immediate_manglers(ENV => @_); |
127
|
|
|
|
|
|
|
} |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
sub generate_hash_manglers_env { |
130
|
6
|
|
|
6
|
1
|
7
|
my $self = shift; |
131
|
6
|
|
|
|
|
9
|
return $self->generate_immediate_manglers(env => @_); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub get_values_from_source { |
135
|
15
|
|
|
15
|
1
|
18
|
my ($self, $env, $source) = @_; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# get right start value |
138
|
15
|
|
|
|
|
11
|
my ($type, $sel) = @{$source}{qw< type value >}; |
|
15
|
|
|
|
|
23
|
|
139
|
|
|
|
|
|
|
my $svalue = ($type eq 'env') ? $env->{$sel} |
140
|
15
|
100
|
|
|
|
28
|
: ($type eq 'ENV') ? $ENV{$sel} |
|
|
100
|
|
|
|
|
|
141
|
|
|
|
|
|
|
: $sel; |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
# flatten if requested and possible |
144
|
15
|
|
|
|
|
14
|
my @values = ($svalue); |
145
|
15
|
100
|
|
|
|
22
|
if ($source->{flatten}) { |
146
|
7
|
100
|
|
|
|
12
|
if (ref($svalue) eq 'ARRAY') { |
|
|
50
|
|
|
|
|
|
147
|
3
|
|
|
|
|
7
|
@values = @$svalue; |
148
|
|
|
|
|
|
|
} |
149
|
|
|
|
|
|
|
elsif (ref($svalue) eq 'HASH') { |
150
|
0
|
|
|
|
|
0
|
@values = %$svalue; |
151
|
|
|
|
|
|
|
} |
152
|
|
|
|
|
|
|
} |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
# handle undefined values |
155
|
15
|
|
|
|
|
13
|
my $default = $source->{default}; |
156
|
15
|
|
|
|
|
10
|
my $doe = $source->{default_on_empty}; |
157
|
|
|
|
|
|
|
@values = map { |
158
|
15
|
100
|
100
|
|
|
14
|
(! defined($_)) ? @$default |
|
27
|
100
|
|
|
|
80
|
|
159
|
|
|
|
|
|
|
: ($doe && (! length($_))) ? @$default |
160
|
|
|
|
|
|
|
: $_; |
161
|
|
|
|
|
|
|
} @values; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# filter stuff out |
164
|
15
|
|
|
|
|
13
|
my $remove_if = $source->{remove_if}; |
165
|
15
|
50
|
|
|
|
12
|
my @retval = grep { ref($_) || (! $remove_if->{$_}) } @values; |
|
23
|
|
|
|
|
59
|
|
166
|
15
|
100
|
|
|
|
24
|
return unless @retval; |
167
|
|
|
|
|
|
|
|
168
|
13
|
|
|
|
|
28
|
return @retval; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub normalize_source { |
172
|
15
|
|
|
15
|
1
|
12
|
my ($self, $source, $defaults) = @_; |
173
|
15
|
|
|
|
|
8
|
my %src; |
174
|
15
|
|
|
|
|
14
|
for my $feature (qw< remove_if default default_on_empty flatten >) { |
175
|
|
|
|
|
|
|
$src{$feature} = exists($source->{$feature}) |
176
|
60
|
100
|
|
|
|
85
|
? delete($source->{$feature}) : $defaults->{$feature}; |
177
|
|
|
|
|
|
|
} |
178
|
15
|
|
|
|
|
11
|
$src{remove_if} = { map { $_ => 1 } @{$src{remove_if}} }; |
|
0
|
|
|
|
|
0
|
|
|
15
|
|
|
|
|
16
|
|
179
|
15
|
100
|
|
|
|
32
|
$src{default} = [$src{default}] unless ref($src{default}) eq 'ARRAY'; |
180
|
|
|
|
|
|
|
confess "too many elements in default for list" |
181
|
15
|
50
|
|
|
|
8
|
if @{$src{default}} > 1; |
|
15
|
|
|
|
|
23
|
|
182
|
15
|
50
|
|
|
|
23
|
confess "too many options in list" if keys(%$source) > 1; |
183
|
15
|
50
|
|
|
|
17
|
confess "nothing to take from in list" if keys(%$source) < 1; |
184
|
15
|
|
|
|
|
24
|
($src{type}, $src{value}) = %$source; |
185
|
|
|
|
|
|
|
confess "unknown source '$src{type}' in list" |
186
|
15
|
50
|
|
|
|
16
|
unless grep {$_ eq $src{type}} qw< env ENV value >; |
|
45
|
|
|
|
|
47
|
|
187
|
15
|
|
|
|
|
22
|
return \%src; |
188
|
|
|
|
|
|
|
} |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub generate_hash_manglers_list { |
191
|
4
|
|
|
4
|
1
|
4
|
my ($self, $key, $cfg, $opts) = @_; |
192
|
4
|
|
50
|
|
|
15
|
$cfg->{remove_if} ||= []; |
193
|
4
|
|
50
|
|
|
15
|
$cfg->{default} ||= []; |
194
|
4
|
|
100
|
|
|
11
|
$cfg->{default_on_empty} ||= 0; |
195
|
4
|
|
100
|
|
|
8
|
$cfg->{flatten} ||= 0; |
196
|
|
|
|
|
|
|
|
197
|
4
|
|
|
|
|
4
|
my $count = 0; |
198
|
4
|
|
|
|
|
15
|
for my $feature (qw< join sprintf >) { |
199
|
8
|
100
|
|
|
|
17
|
defined(my $v = $cfg->{$feature}) or next; |
200
|
3
|
50
|
|
|
|
8
|
confess "cannot specify both join and sprintf for '$key'" |
201
|
|
|
|
|
|
|
if ++$count > 1; |
202
|
3
|
100
|
|
|
|
7
|
$v = {value => $v} unless ref $v; |
203
|
3
|
|
|
|
|
9
|
$cfg->{$feature} = $self->normalize_source($v, {%$opts, $feature => undef}); |
204
|
|
|
|
|
|
|
} |
205
|
4
|
|
|
|
|
4
|
my ($join, $sprintf) = @{$cfg}{qw< join sprintf >}; |
|
4
|
|
|
|
|
6
|
|
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
my @sources = map { |
208
|
12
|
|
|
|
|
14
|
$self->normalize_source($_, $cfg); |
209
|
4
|
|
|
|
|
3
|
} @{$cfg->{sources}}; |
|
4
|
|
|
|
|
5
|
|
210
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
my $sub = sub { |
212
|
4
|
|
|
4
|
|
7
|
my ($value, $env, $key) = @_; |
213
|
4
|
|
|
|
|
4
|
my @retval; |
214
|
4
|
|
|
|
|
6
|
for my $source (@sources) { |
215
|
12
|
|
|
|
|
19
|
push @retval, $self->get_values_from_source($env, $source); |
216
|
|
|
|
|
|
|
} |
217
|
|
|
|
|
|
|
|
218
|
4
|
100
|
|
|
|
11
|
if (defined $join) { |
|
|
100
|
|
|
|
|
|
219
|
2
|
|
|
|
|
3
|
my ($joinstr) = $self->get_values_from_source($env, $join); |
220
|
2
|
|
|
|
|
7
|
$env->{$key} = join $joinstr, @retval; |
221
|
|
|
|
|
|
|
} |
222
|
|
|
|
|
|
|
elsif (defined $sprintf) { |
223
|
1
|
|
|
|
|
2
|
my ($sprintfstr) = $self->get_values_from_source($env, $sprintf); |
224
|
1
|
|
|
|
|
8
|
$env->{$key} = sprintf $sprintfstr, @retval; |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
else { |
227
|
1
|
|
|
|
|
4
|
$env->{$key} = \@retval; |
228
|
|
|
|
|
|
|
} |
229
|
4
|
|
|
|
|
16
|
}; |
230
|
4
|
|
|
|
|
6
|
return $self->generate_immediate_manglers(sub => $key, $sub, $opts); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
*generate_hash_manglers_remove = \&generate_remove_manglers; |
234
|
|
|
|
|
|
|
*generate_hash_manglers_sub = \&generate_code_manglers; |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub generate_hash_manglers_value { |
237
|
4
|
|
|
4
|
1
|
3
|
my $self = shift; |
238
|
4
|
|
|
|
|
6
|
return $self->generate_immediate_manglers(value => @_); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
sub generate_remove_manglers { |
242
|
5
|
|
|
5
|
1
|
6
|
my ($self, $key, $value, $defaults) = @_; |
243
|
5
|
50
|
33
|
|
|
18
|
if ((ref($value) eq 'HASH') && (my @keys = keys(%$value))) { |
244
|
0
|
|
|
|
|
0
|
@keys = $self->stringified_list(@keys); |
245
|
0
|
|
|
|
|
0
|
confess "remove MUST be alone when set to true, found (@keys)"; |
246
|
|
|
|
|
|
|
} |
247
|
5
|
|
|
|
|
10
|
return $self->generate_immediate_manglers(remove => $key, 1, {}); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
sub wrap_code { |
251
|
10
|
|
|
10
|
1
|
18
|
my ($self, $sub) = @_; |
252
|
10
|
100
|
|
|
|
54
|
return unless ref($sub) eq 'CODE'; |
253
|
|
|
|
|
|
|
return sub { |
254
|
7
|
100
|
|
7
|
|
21
|
defined(my $retval = $sub->(@_)) or return; |
255
|
6
|
100
|
|
|
|
48
|
$retval = [$retval] unless ref($retval); |
256
|
|
|
|
|
|
|
|
257
|
6
|
|
|
|
|
10
|
my ($value, $env, $key) = @_; |
258
|
6
|
50
|
|
|
|
13
|
confess "sub for '$key' returned an invalid value" |
259
|
|
|
|
|
|
|
unless ref($retval) eq 'ARRAY'; |
260
|
|
|
|
|
|
|
|
261
|
6
|
|
|
|
|
4
|
my $n = scalar @$retval; |
262
|
6
|
50
|
|
|
|
15
|
if ($n == 0) { |
|
|
50
|
|
|
|
|
|
263
|
0
|
|
|
|
|
0
|
delete $env->{$key}; |
264
|
|
|
|
|
|
|
} |
265
|
|
|
|
|
|
|
elsif ($n == 1) { |
266
|
6
|
|
|
|
|
8
|
$env->{$key} = $retval->[0]; |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
else { |
269
|
0
|
|
|
|
|
0
|
my @values = $self->stringified_list(@$retval); |
270
|
0
|
|
|
|
|
0
|
confess "too many return values (@values) from sub for '$key'"; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
6
|
|
|
|
|
12
|
return; |
274
|
8
|
|
|
|
|
41
|
}; |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
sub stringified_list { |
278
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
279
|
|
|
|
|
|
|
return map { |
280
|
0
|
0
|
|
|
|
0
|
if (defined(my $v = $_)) { |
|
0
|
|
|
|
|
0
|
|
281
|
0
|
|
|
|
|
0
|
$v =~ s{([\\'])}{\\$1}gmxs; |
282
|
0
|
|
|
|
|
0
|
"'$v'"; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
else { |
285
|
0
|
|
|
|
|
0
|
'undef'; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
} @_; |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
# _PRIVATE METHODS_ |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
sub _normalize_input_structure { |
293
|
9
|
|
|
9
|
|
10
|
my ($self) = @_; |
294
|
9
|
100
|
|
|
|
222
|
if (exists $self->{manglers}) { |
295
|
4
|
|
|
|
|
8
|
local $" = "', '"; |
296
|
4
|
|
|
|
|
4
|
my $mangle = $self->{manglers}; |
297
|
4
|
50
|
|
|
|
13
|
$mangle = $self->{manglers} = [%$mangle] if ref($mangle) eq 'HASH'; |
298
|
4
|
50
|
|
|
|
12
|
confess "'mangle' MUST point to an array or hash reference" |
299
|
|
|
|
|
|
|
unless ref($mangle) eq 'ARRAY'; |
300
|
4
|
50
|
|
|
|
15
|
confess "'mangle' array MUST contain an even number of items" |
301
|
|
|
|
|
|
|
if @$mangle % 2; |
302
|
4
|
|
|
|
|
11
|
my @keys = keys %$self; |
303
|
|
|
|
|
|
|
confess "'mangle' MUST be standalone when present (found: '@keys')" |
304
|
4
|
100
|
|
|
|
6
|
if grep { ($_ ne 'app') && ($_ ne 'manglers') } @keys; |
|
8
|
50
|
|
|
|
36
|
|
305
|
|
|
|
|
|
|
} ## end if (exists $self->{manglers...}) |
306
|
|
|
|
|
|
|
else { # anything except app goes into mangle |
307
|
5
|
|
|
|
|
8
|
my $app = delete $self->{app}; # temporarily remove it |
308
|
5
|
|
|
|
|
21
|
%$self = ( |
309
|
|
|
|
|
|
|
app => $app, # put it back |
310
|
|
|
|
|
|
|
manglers => [%$self], # with rest as manglers |
311
|
|
|
|
|
|
|
); |
312
|
|
|
|
|
|
|
} ## end else [ if (exists $self->{manglers...})] |
313
|
9
|
|
|
|
|
12
|
return $self; |
314
|
|
|
|
|
|
|
} ## end sub _normalize_input_structure |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
sub _only_one { |
317
|
0
|
|
|
0
|
|
|
my ($self, $hash, @keys) = @_; |
318
|
0
|
|
|
|
|
|
my @found = grep { exists $hash->{$_} } @keys; |
|
0
|
|
|
|
|
|
|
319
|
0
|
0
|
|
|
|
|
return ($found[0], delete($hash->{$found[0]})) if @found == 1; |
320
|
|
|
|
|
|
|
|
321
|
0
|
|
|
|
|
|
@keys = $self->stringified_list(@keys); |
322
|
0
|
|
|
|
|
|
@found = $self->stringified_list(@found); |
323
|
0
|
0
|
|
|
|
|
confess scalar(@found) |
324
|
|
|
|
|
|
|
? "one in (@keys) MUST be provided, none found" |
325
|
|
|
|
|
|
|
: "only one in (@keys) is allowed, found (@found)"; |
326
|
|
|
|
|
|
|
} ## end sub __exactly_one_key_among |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
1; |
329
|
|
|
|
|
|
|
__END__ |