File Coverage

blib/lib/CGI/Session/Flash.pm
Criterion Covered Total %
statement 89 100 89.0
branch 26 38 68.4
condition 12 16 75.0
subroutine 19 21 90.4
pod 18 18 100.0
total 164 193 84.9


line stmt bran cond sub pod time code
1             package CGI::Session::Flash;
2 2     2   52260 use Carp;
  2         5  
  2         194  
3 2     2   10 use strict;
  2         3  
  2         2770  
4              
5             our $VERSION = '0.02';
6              
7              
8             # Create a new flash object.
9             #
10             # A session is required, all other parameters are optional and specify
11             # options for the flash.
12             sub new
13             {
14 3     3 1 32 my $class = shift;
15 3         7 my $session = shift;
16 3         15 my %options = (
17             session_key => '_flash',
18             @_,
19             );
20              
21             # Make sure a session was provided.
22 3 50 33     58 croak "No session provided."
      33        
23             unless (defined $session && ref $session &&
24             $session->isa('CGI::Session'));
25              
26             # Initialize data from the session.
27 3   100     16 my $data = $session->param($options{session_key}) || { };
28 3   100     64 my $keep = $session->param($options{session_key} . '_keep') || [ ];
29              
30 3         19 my $self = {
31             _session => $session,
32             _data => $data,
33 3         33 _keep => { map { $_ => 1 } @$keep },
34             _cleanup_done => 0,
35             _session_key => $options{session_key},
36             };
37              
38 3         12 bless $self, $class;
39 3         10 return $self;
40             }
41              
42             # When the object goes out of scope and flush it's contents so that they get
43             # saved back into the session.
44 3     3   525 sub DESTROY { shift->flush(); }
45              
46              
47             # Accessors
48             #------------------------------------------------------------------------------
49              
50             # Returns boolean for whether cleanup has been performed.
51 14     14 1 74 sub cleanup_done { shift->{_cleanup_done} }
52              
53             # Return the associated session object.
54 9     9 1 34 sub session { shift->{_session} }
55              
56             # A list of the session keys. This returns an array ref, the first is the
57             # flash data, the second is the keys to keep.
58 6     6 1 21 sub session_key { shift->{_session_key} }
59              
60              
61             # Getting and setting values
62             #------------------------------------------------------------------------------
63              
64             # Set the data in the flash for the specified key.
65             sub set
66             {
67 2     2 1 3 my $self = shift;
68 2         5 my $key = shift;
69 2         5 my @vals = @_;
70              
71 2 50       8 croak "No flash key specified." unless (defined $key);
72 2 50       7 croak "No flash values specified." unless (@vals);
73              
74             # Set the values and mark the key as not used.
75 2         6 $self->{_data}{$key} = \@vals;
76 2         7 $self->keep($key);
77              
78 2         8 return 1;
79             }
80              
81             # Retrieve the data from the flash for the specified key.
82             sub get
83             {
84 5     5 1 2254 my $self = shift;
85 5         9 my $key = shift;
86 5         7 my $vals;
87              
88 5 50       15 croak "No flash key specified." unless (defined $key);
89              
90             # Get the values.
91 5 50       16 $vals = $self->{_data}{$key} if ($self->has_key($key));
92              
93 5 50       14 return undef if (!defined $vals);
94 5 100 100     31 return $vals->[0] if (ref $vals eq "ARRAY" && @$vals == 1);
95 4 100       41 return wantarray ? @$vals : $vals;
96             }
97              
98             # Set data in the flash that will only last until the next time that cleanup
99             # is called.
100             sub now
101             {
102 0     0 1 0 my $self = shift;
103 0         0 my $key = shift;
104 0         0 my @vals = @_;
105              
106 0 0       0 croak "No flash key specified." unless (defined $key);
107 0 0       0 croak "No flash values specified." unless (@vals);
108              
109 0         0 $self->set($key => @vals);
110 0         0 $self->discard($key);
111              
112 0         0 return 1;
113             }
114              
115              
116             # Keys and Contents
117             #------------------------------------------------------------------------------
118              
119             # Get a hashref of the flash contents. Used internally by the teardown hook
120             # for saving the flash to the session.
121             sub contents
122             {
123 4     4 1 6 my $self = shift;
124            
125 4         27 return $self->{_data};
126             }
127              
128             # Return a list of keys that are marked as kept.
129             sub keep_keys
130             {
131 8     8 1 12 my $self = shift;
132 3         11 my @keep = grep { $self->{_keep}{$_} > 0 }
  8         22  
133 8         10 keys %{ $self->{_keep} };
134              
135 8 100       45 return wantarray ? @keep : \@keep;
136             }
137              
138             # Return a list of keys currently in the flash.
139             sub keys
140             {
141 5     5 1 1535 my $self = shift;
142 5         9 my @keys = sort keys %{ $self->{_data} };
  5         31  
143              
144 5 50       37 return wantarray ? @keys : \@keys;
145             }
146              
147             # Return true or false depending on if the flash contains the specified key.
148             sub has_key
149             {
150 8     8 1 11 my $self = shift;
151 8         14 my $key = shift;
152              
153 8 50       20 croak "No flash key specified." unless (defined $key);
154              
155 8 100       45 return 1 if (exists $self->{_data}{$key});
156 1         5 return 0;
157             }
158              
159             # Returns true or false depending on if the flash is empty or not.
160             sub is_empty
161             {
162 6     6 1 718 my $self = shift;
163              
164 6 100       13 return 0 if (scalar CORE::keys %{ $self->{_data} } > 0);
  6         40  
165 4         16 return 1;
166             }
167              
168             # Clear all flash data out and start fresh.
169             sub reset
170             {
171 1     1 1 2 my $self = shift;
172              
173 1         3 $self->{_data} = { };
174 1         5 $self->{_keep} = { };
175 1         3 $self->{_cleanup_done} = 0;
176              
177 1         4 return 1;
178             }
179              
180              
181             # Keeping keys and cleanup
182             #------------------------------------------------------------------------------
183              
184             # Mark the specified keys as being kept for one more iteration.
185             sub keep
186             {
187 4     4 1 8 my $self = shift;
188 4         10 my @keys = @_;
189              
190             # If no keys were specified, keep all.
191 4 100       18 @keys = $self->keys unless (@_);
192              
193 4         7 foreach my $key (@keys)
194             {
195 5         21 $self->{_keep}{$key}++;
196             }
197              
198 4         13 return 1;
199             }
200              
201             # Mark the specified keys for deletion at the next time that cleanup is called.
202             sub discard
203             {
204 2     2 1 3 my $self = shift;
205 2         6 my @keys = @_;
206              
207             # If no keys were specified, keep all.
208 2 100       12 @keys = $self->keys unless (@_);
209              
210 2         5 foreach my $key (@keys)
211             {
212 3         8 delete $self->{_keep}{$key};
213             }
214              
215 2         11 return 1;
216             }
217              
218             # Cleanup the flash. All keys not marked as kept will be deleted, otherwise
219             # they are marked for discard next time this method is called. This method
220             # is automatically called during flush().
221             #
222             # Cleanup process is tracked, and it will not be performed more than once unless
223             # you pass a true value to signify that you want to force the cleanup.
224             sub cleanup
225             {
226 8     8 1 12 my $self = shift;
227 8         11 my $force = shift;
228              
229             # Skip cleanup since it has already been performed.
230 8 100 100     21 return 1 if ($self->cleanup_done && !$force);
231              
232 4         9 foreach my $key (CORE::keys %{ $self->{_data} })
  4         14  
233             {
234 7 100       18 if ($self->{_keep}{$key})
235             {
236 2         7 delete $self->{_keep}{$key};
237             }
238             else
239             {
240 5         13 delete $self->{_data}{$key};
241             }
242             }
243              
244             # Set flag
245 4         9 $self->{_cleanup_done}++;
246              
247 4         13 return 1;
248             }
249              
250             # Perform cleanup and save the contents of the flash back to the session.
251             sub flush
252             {
253 4     4 1 6 my $self = shift;
254 4         12 my $session_key = $self->session_key;
255              
256             # Perform cleanup
257 4         11 $self->cleanup();
258              
259             # Save the data back into the session
260 4         12 $self->session->param($session_key => $self->contents);
261 4         30 $self->session->param($session_key . '_keep' => scalar $self->keep_keys);
262              
263 4         211 return 1;
264             }
265              
266              
267             # Debugging
268             #------------------------------------------------------------------------------
269              
270             # Return a Data::Dumper dump of the flash for debugging purposes.
271             sub dump
272             {
273 0     0 1   my $self = shift;
274              
275 0           require Data::Dumper;
276 0           return Data::Dumper->Dump([ $self->contents ], [ "flash" ]);
277             }
278              
279             1;
280             __END__