dceb9c25ea1081f39d2aa90609f97f9fc892cdd1
[catagits/Catalyst-Plugin-Session-State-Stash.git] / lib / Catalyst / Plugin / Session / State / Stash.pm
1 package Catalyst::Plugin::Session::State::Stash;
2 use Moose;
3 use 5.008;
4 use MRO::Compat;
5 use namespace::autoclean;
6
7 extends 'Catalyst::Plugin::Session::State';
8
9 our $VERSION = '0.14';
10
11 has _deleted_session_id => ( is => 'rw' );
12 has _prepared => ( is => 'rw' );
13
14 sub _stash_key_components {
15     my ($c) = @_;
16     my $config = $c->_session_plugin_config;
17     return ($config->{stash_delim}) ?
18         split $config->{stash_delim}, $config->{stash_key} :
19         $config->{stash_key};
20 }
21
22 sub _get_session {
23     my ($c) = @_;
24     # This turns the list of path components into a nested tree of hashrefs for obtaining info/storing in: 123/456 = {123}->{456}
25     my $ref = $c->stash;
26     $ref = ($ref->{$_} ||= {}) foreach $c->_stash_key_components;
27     $ref;
28 }
29
30 sub _set_session {
31     my ( $c,$key,$value) = @_;
32     $c->_get_session->{$key} = $value;
33 }
34
35 sub setup_session {
36     my $c = shift;
37
38     $c->maybe::next::method(@_);
39
40     $c->_session_plugin_config->{stash_key} ||= '_session';
41 }
42
43 sub prepare_action {
44     my $c = shift;
45     my $id = $c->get_session_id;
46     $c->_prepared(1);
47     if ( $id ) {
48         $c->sessionid( $id );
49     }
50     $c->maybe::next::method( @_ );
51 }
52
53 sub get_session_id {
54     my $c = shift;
55     if(!$c->_deleted_session_id and my $session = $c->_get_session) {
56         my $sid = $session->{id};
57         return $sid if $sid;
58     }
59     $c->maybe::next::method(@_);
60 }
61
62 sub set_session_id {
63     my ( $c, $sid ) = @_;
64     $c->_set_session(id => $sid);
65     $c->maybe::next::method($sid);
66 }
67
68 sub get_session_expires {
69     my $c = shift;
70     my $session = $c->_get_session;
71     defined $session->{expires} ? $session->{expires} : undef;
72 }
73
74 sub set_session_expires {
75     my ( $c, $expires ) = @_;
76     $c->_set_session(expires => time() + $expires);
77     $c->maybe::next::method($expires)
78 }
79
80 sub delete_session_id {
81     my ($c, $sid ) = @_;
82     $c->_deleted_session_id(1);
83     #Empty the tip
84     %{$c->_get_session} = ();
85     $c->maybe::next::method($sid);
86 }
87
88
89 1;
90 __END__
91
92 =pod
93
94 =head1 NAME
95
96 Catalyst::Plugin::Session::State::Stash - Maintain session IDs using the stash
97
98 =head1 SYNOPSIS
99
100  use Catalyst qw/Session Session::State::Stash Session::Store::Foo/;
101
102 =head1 DESCRIPTION
103
104 An alternative state storage plugin that allows you some more flexibility in
105 dealing with session storage. This plugin loads and saves the session ID from
106 and to the stash.
107
108 =head1 METHODS
109
110 =over 4
111
112 =item delete_session_id
113
114 Deletes the session. Unfortunately I've been unable to squash a bug that will
115 stop you from opening a new session in the same execution, however.
116 Patches welcome!
117
118 =item get_session_id
119
120 Gets the current session id.
121
122 =item set_session_id
123
124 Sets the session id to the C<shift>.
125
126 =item get_session_expires
127
128 Gets when the current session expires.
129
130 =item set_session_expires
131
132 Sets how many seconds from now the session should expire.
133
134 =back
135
136 =head1 EXTENDED METHODS
137
138 =over 4
139
140 =item prepare_action
141
142 Loads the id off the stash.
143
144 =item setup_session
145
146 Defaults the C<stash_key> parameter to C<_session>.
147
148 =back
149
150 =head1 CONFIGURATION
151
152 =over 4
153
154 =item stash_key
155
156 The name of the hash key to use. Defaults to C<_session>.
157
158 =item stash_delim
159
160 If present, splits stash_key at this character to nest. E.g. delim of '/'
161 and key of '123/456' will store it as $c->stash->{123}->{456}
162
163 =item expires
164
165 How long the session should last in seconds.
166
167 =back
168
169 For example, you could stick this in MyApp.pm:
170
171   __PACKAGE__->config( 'Plugin::Session' => {
172      stash_key  => 'session_id',
173   });
174
175 =head1 BUGS
176
177 You can't delete a session then create a new one. If this is important to you,
178 patches welcome. It is not important to me and fixing this for completeness
179 is pretty low on my list of priorities.
180
181 =head1 CAVEATS
182
183 Manual work may be involved to make better use of this.
184
185 If you are writing a stateful web service with
186 L<Catalyst::Plugin::Server::XMLRPC>, you will probably only have to deal with
187 loading, as when saving, the ID will already be on the stash.
188
189 =head1 SEE ALSO
190
191 L<Catalyst>, L<Catalyst::Plugin::Session>, L<Catalyst::Plugin::Session::State>,
192 L<Catalyst::Plugin::Session::State::Cookie> (what you probably want).
193
194 =head1 AUTHORS
195
196 James Laver E<lt>perl -e 'printf qw/%s@%s.com cpan jameslaver/'E<gt>
197
198 =head1 CONTRIBUTORS
199
200 This module is derived from L<Catalyst::Plugin::Session::State::Cookie> code.
201
202 Thanks to anyone who wrote code for that.
203
204 Thanks to Kent Fredric for a patch for nested keys
205
206 =head1 COPYRIGHT
207
208 This program is free software, you can redistribute it and/or modify it
209 under the same terms as Perl itself.
210
211 =cut
212