Reworked Session to make the expiration a store's responsibility and
[catagits/Web-Session.git] / lib / Plack / Session.pm
1 package Plack::Session;
2 use strict;
3 use warnings;
4
5 our $VERSION   = '0.03';
6 our $AUTHORITY = 'cpan:STEVAN';
7
8 use Plack::Util::Accessor qw( id expired _manager );
9
10 sub fetch_or_create {
11     my($class, $request, $manager) = @_;
12
13     my($id, $session);
14     if ($id = $manager->state->extract($request) and
15         $session = $manager->store->fetch($id)) {
16         return $class->new( id => $id, _stash => $session, _manager => $manager, _changed => 0 );
17     } else {
18         $id = $manager->state->generate($request);
19         return $class->new( id => $id, _stash => {}, _manager => $manager, _changed=> 1 );
20     }
21 }
22
23 sub new {
24     my ($class, %params) = @_;
25     bless { %params } => $class;
26 }
27
28 ## Data Managment
29
30 sub dump {
31     my $self = shift;
32     $self->{_stash};
33 }
34
35 sub get {
36     my ($self, $key) = @_;
37     $self->{_stash}{$key};
38 }
39
40 sub set {
41     my ($self, $key, $value) = @_;
42     $self->{_changed}++;
43     $self->{_stash}{$key} = $value;
44 }
45
46 sub remove {
47     my ($self, $key) = @_;
48     $self->{_changed}++;
49     delete $self->{_stash}{$key};
50 }
51
52 sub keys {
53     my $self = shift;
54     keys %{$self->{_stash}};
55 }
56
57 ## Lifecycle Management
58
59 sub expire {
60     my $self = shift;
61     $self->{_stash} = {};
62     $self->expired(1);
63 }
64
65 sub commit {
66     my $self = shift;
67
68     if ($self->expired) {
69         $self->_manager->store->cleanup($self->id);
70     } else {
71         $self->_manager->store->store($self->id, $self);
72     }
73
74     $self->{_changed} = 0;
75 }
76
77 sub is_changed {
78     my $self = shift;
79     $self->{_changed} > 0;
80 }
81
82 sub finalize {
83     my ($self, $response) = @_;
84
85     $self->commit if $self->is_changed || $self->expired;
86     if ($self->expired) {
87         $self->_manager->state->expire_session_id($self->id, $response);
88     } else {
89         $self->_manager->state->finalize($self->id, $response, $self);
90     }
91 }
92
93 1;
94
95 __END__
96
97 =pod
98
99 =head1 NAME
100
101 Plack::Session - Middleware for session management
102
103 =head1 SYNOPSIS
104
105   use Plack::Session;
106
107   my $store = Plack::Session::Store->new;
108   my $state = Plack::Session::State->new;
109
110   my $s = Plack::Session->new(
111       store   => $store,
112       state   => $state,
113       request => Plack::Request->new( $env )
114   );
115
116   # ...
117
118 =head1 DESCRIPTION
119
120 This is the core session object, you probably want to look
121 at L<Plack::Middleware::Session>, unless you are writing your
122 own session middleware component.
123
124 =head1 METHODS
125
126 =over 4
127
128 =item B<new ( %params )>
129
130 The constructor expects keys in C<%params> for I<state>,
131 I<store> and I<request>. The I<request> param is expected to be
132 a L<Plack::Request> instance or an object with an equivalent
133 interface.
134
135 =item B<id>
136
137 This is the accessor for the session id.
138
139 =item B<state>
140
141 This is expected to be a L<Plack::Session::State> instance or
142 an object with an equivalent interface.
143
144 =item B<store>
145
146 This is expected to be a L<Plack::Session::Store> instance or
147 an object with an equivalent interface.
148
149 =back
150
151 =head2 Session Data Management
152
153 These methods allows you to read and write the session data like
154 Perl's normal hash. The operation is not synced to the storage until
155 you call C<finalize> on it.
156
157 =over 4
158
159 =item B<get ( $key )>
160
161 =item B<set ( $key, $value )>
162
163 =item B<remove ( $key )>
164
165 =item B<keys>
166
167 =back
168
169 =head2 Session Lifecycle Management
170
171 =over 4
172
173 =item B<commit>
174
175 This method synchronizes the session data to the data store, without
176 waiting for the response final phase.
177
178 =item B<expire>
179
180 This method can be called to expire the current session id. It marks
181 the session as expire and call the C<cleanup> method on the C<store>
182 and the C<expire_session_id> method on the C<state>.
183
184 =item B<finalize ( $manager, $response )>
185
186 This method should be called at the end of the response cycle. It will
187 call the C<store> method on the C<store> and the C<expire_session_id>
188 method on the C<state>. The C<$response> is expected to be a
189 L<Plack::Response> instance or an object with an equivalent interface.
190
191 =back
192
193 =head1 BUGS
194
195 All complex software has bugs lurking in it, and this module is no
196 exception. If you find a bug please either email me, or add the bug
197 to cpan-RT.
198
199 =head1 AUTHOR
200
201 Stevan Little E<lt>stevan.little@iinteractive.comE<gt>
202
203 =head1 COPYRIGHT AND LICENSE
204
205 Copyright 2009, 2010 Infinity Interactive, Inc.
206
207 L<http://www.iinteractive.com>
208
209 This library is free software; you can redistribute it and/or modify
210 it under the same terms as Perl itself.
211
212 =cut
213