File Coverage

blib/lib/CGI/State.pm
Criterion Covered Total %
statement 42 44 95.4
branch 19 24 79.1
condition 12 19 63.1
subroutine 7 7 100.0
pod 2 2 100.0
total 82 96 85.4


line stmt bran cond sub pod time code
1             package CGI::State;
2              
3 1     1   57292 use strict;
  1         2  
  1         35  
4 1     1   761 use integer;
  1         9  
  1         5  
5 1     1   20 use overload;
  1         6  
  1         4  
6 1     1   30 use CGI ();
  1         1  
  1         15  
7              
8 1     1   3 use vars qw($VERSION);
  1         2  
  1         514  
9              
10             $VERSION = (qw$Revision: 0.02 $)[-1];
11              
12             #Returns a state hashref
13             sub state {
14 1     1 1 6073 my $class = shift;
15 1         3 my $cgi = shift;
16 1   50     9 my $state = shift || {};
17              
18             #Alternative calling method is with a hash, rather
19             #than a CGI object. This allows validation before
20             #building a multi-dimensional hash from submitted
21             #values.
22 1 50       4 if(ref $cgi eq 'HASH') {
23 0         0 $cgi = CGI->new($cgi);
24             }
25              
26 1         7 foreach my $param ($cgi->param) {
27              
28 12         62 my @words = split(/[\.\[\]]+/o, $param);
29 12         17 my $node = $state;
30              
31 12         30 for( my $w = 0; #start at the first word
32             $w < scalar @words; #go until the end
33             $w++ ){ #increment the w count
34              
35             #If the next word is undefined, then we must
36             #be looking at the last node. If the next word
37             #is a non-number, it must be a hashref, otherwise,
38             #it is an arrayref.
39 30         34 my $over_write = 0;
40              
41 30 100       108 my $next = (not defined $words[$w + 1])
    100          
42             ? ($over_write++, $cgi->param($param))
43             : $words[$w + 1] =~ /\D/
44             ? {}
45             : [];
46              
47             #Figures out if this is a reference to a hash,
48             #array, an object or even an over-loaded object.
49 30         270 my ($ref) = overload::StrVal($node) =~ /^(?:.*\=)?([^=]*)\([^\(]*\)$/o;
50              
51 30 100 66     348 $node = $ref eq 'HASH'
    50 66        
    100          
52             ? $over_write
53             ? ($node->{ $words[$w] } = $next)
54             : ($node->{ $words[$w] } ||= $next)
55             : $over_write
56             ? ($node->[ $words[$w] ] = $next)
57             : ($node->[ $words[$w] ] ||= $next);
58             }
59             }
60              
61 1         5 return $state;
62             }
63              
64             #Takes the state, and returns a CGI object representing
65             #a "flattened" representation of state.
66             sub cgi {
67 19     19 1 26 my $class = shift;
68 19         26 my $state = shift;
69 19   66     44 my $cgi = shift || CGI->new('');
70 19   100     360 my $param = shift || '';
71              
72             #Figures out if this is a reference to a hash,
73             #array, an object or even an over-loaded object.
74 19 100 33     76 if(my $ref = ref $state) {
    50          
75              
76             #If it's really necessary, then use overload::StrVal
77 7 50 66     26 unless($ref eq 'HASH' or $ref eq 'ARRAY') {
78 0         0 $ref = overload::StrVal($state) =~ /([^=]*)\(/o;
79             }
80              
81 7 100       22 if($ref eq 'ARRAY') {
    50          
82              
83 1         7 for( my $index = 0; #start at the first word
84             $index < scalar @$state; #go until the end
85             $index++ ){
86 3         13 $class->cgi( $state->[$index], $cgi, "$param\[$index\]" );
87             }
88              
89             } elsif($ref eq 'HASH') {
90              
91 6 100       13 $param .= '.' unless $param eq '';
92              
93 6         17 foreach my $key (keys %$state) {
94 15         55 $class->cgi( $state->{$key}, $cgi, $param.$key );
95             }
96              
97             }
98              
99             } elsif(defined $state and $param ne '') {
100              
101 12         35 $cgi->param($param, $state);
102              
103             }
104              
105 19         645 return $cgi;
106             }
107              
108             1;
109              
110             __END__