File Coverage

blib/lib/HTML/FormHandler/Params.pm
Criterion Covered Total %
statement 39 62 62.9
branch 15 30 50.0
condition 2 6 33.3
subroutine 5 8 62.5
pod 0 4 0.0
total 61 110 55.4


line stmt bran cond sub pod time code
1             package # hide from Pause
2             HTML::FormHandler::Params;
3             # ABSTRACT: params handling
4              
5 142     142   376298 use Moose;
  142         447  
  142         1303  
6 142     142   973726 use Carp;
  142         416  
  142         107730  
7              
8             has 'separator' => ( isa => 'Str', is => 'rw', default => '.' );
9              
10             sub split_name {
11 586     586 0 1405 my ( $self, $name, $sep ) = @_;
12              
13 586   33     1512 $sep ||= $self->separator;
14 586         1252 $sep = "\Q$sep";
15              
16 586 50       1620 if ( $sep eq '[]' ) {
17 0         0 return grep { defined } (
  0         0  
18             $name =~ /
19             ^ (\w+) # root param
20             | \[ (\w+) \] # nested
21             /gx
22             );
23             }
24              
25             # These next two regexes are the escaping aware equivalent
26             # to the following:
27             # my ($first, @segments) = split(/\./, $name, -1);
28              
29             # m// splits on unescaped '.' chars. Can't fail b/c \G on next
30             # non ./ * -> escaped anything -> non ./ *
31 586         6725 $name =~ m/^ ( [^\\$sep]* (?: \\(?:.|$) [^\\$sep]* )* ) /gx;
32 586         1576 my $first = $1;
33 586         1353 $first =~ s/\\(.)/$1/g; # remove escaping
34              
35 586         4143 my (@segments) = $name =~
36             # . -> ( non ./ * -> escaped anything -> non ./ * )
37             m/\G (?:[$sep]) ( [^\\$sep]* (?: \\(?:.|$) [^\\$sep]* )* ) /gx;
38             # Escapes removed later, can be used to avoid using as array index
39              
40 586         2296 return ( $first, @segments );
41             }
42              
43             sub expand_hash {
44 358     358 0 1131 my ( $self, $flat, $sep ) = @_;
45              
46 358         820 my $deep = {};
47 358   33     11409 $sep ||= $self->separator;
48              
49 358         1793 for my $name ( keys %$flat ) {
50              
51 586         1821 my ( $first, @segments ) = $self->split_name( $name, $sep );
52              
53 586         1614 my $box_ref = \$deep->{$first};
54 586         1394 for (@segments) {
55 337 100       1052 if ( /^(0|[1-9]\d*)$/ ) {
56 118 100       314 $$box_ref = [] unless defined $$box_ref;
57 118 50       305 croak "HFH: param clash for $name=$_"
58             unless ref $$box_ref eq 'ARRAY';
59 118         336 $box_ref = \( $$box_ref->[$1] );
60             }
61             else {
62 219 50       622 s/\\(.)/$1/g if $sep; # remove escaping
63 219 100       593 $$box_ref = {} unless defined $$box_ref;
64 219 100       563 $$box_ref = { '' => $$box_ref } if ( !ref $$box_ref );
65 219 50       572 croak "HFH: param clash for $name=$_"
66             unless ref $$box_ref eq 'HASH';
67 219         575 $box_ref = \( $$box_ref->{$_} );
68             }
69             }
70 586 100       1618 if ( defined $$box_ref ) {
71 1 50       4 croak "HFH: param clash for $name value $flat->{$name}"
72             if ref $$box_ref ne 'HASH';
73 1         3 $box_ref = \( $$box_ref->{''} );
74             }
75 586         1466 $$box_ref = $flat->{$name};
76             }
77 358         1210 return $deep;
78             }
79              
80             sub collapse_hash {
81 0     0 0   my $self = shift;
82 0           my $deep = shift;
83 0           my $flat = {};
84              
85 0           $self->_collapse_hash( $deep, $flat, () );
86 0           return $flat;
87             }
88              
89             sub join_name {
90 0     0 0   my ( $self, @array ) = @_;
91 0           my $sep = substr( $self->separator, 0, 1 );
92 0           return join $sep, @array;
93             }
94              
95             sub _collapse_hash {
96 0     0     my ( $self, $deep, $flat, @segments ) = @_;
97              
98 0 0         if ( !ref $deep ) {
    0          
    0          
99 0           my $name = $self->join_name(@segments);
100 0           $flat->{$name} = $deep;
101             }
102             elsif ( ref $deep eq 'HASH' ) {
103 0           for ( keys %$deep ) {
104             # escape \ and separator chars (once only, at this level)
105 0           my $name = $_;
106 0 0         if ( defined( my $sep = $self->separator ) ) {
107 0           $sep = "\Q$sep";
108 0           $name =~ s/([\\$sep])/\\$1/g;
109             }
110 0           $self->_collapse_hash( $deep->{$_}, $flat, @segments, $name );
111             }
112             }
113             elsif ( ref $deep eq 'ARRAY' ) {
114 0           for ( 0 .. $#$deep ) {
115 0 0         $self->_collapse_hash( $deep->[$_], $flat, @segments, $_ )
116             if defined $deep->[$_];
117             }
118             }
119             else {
120 0           croak "Unknown reference type for ", $self->join_name(@segments), ":", ref $deep;
121             }
122             }
123              
124             __PACKAGE__->meta->make_immutable;
125 142     142   1296 use namespace::autoclean;
  142         406  
  142         1701  
126             1;
127              
128             __END__
129              
130             =pod
131              
132             =encoding UTF-8
133              
134             =head1 NAME
135              
136             HTML::FormHandler::Params - params handling
137              
138             =head1 VERSION
139              
140             version 0.40068
141              
142             =head1 AUTHOR
143              
144             FormHandler Contributors - see HTML::FormHandler
145              
146             =head1 COPYRIGHT AND LICENSE
147              
148             This software is copyright (c) 2017 by Gerda Shank.
149              
150             This is free software; you can redistribute it and/or modify it under
151             the same terms as the Perl 5 programming language system itself.
152              
153             =cut