| Catalyst-Plugin-Session-Store-Delegate documentation | Contained in the Catalyst-Plugin-Session-Store-Delegate distribution. |
Catalyst::Plugin::Session::Store::Delegate - Delegate session storage to an application model object.
use Catalyst::Plugin::Session::Store::Delegate;
This store plugins makes delegating session storage to a first class object model easy.
The model is used to retrieve the delegate object for a given session ID.
This is normally something like DBIC's resultset object.
The model must respond to the get_delegate method or closure in the sesion
config hash (defaults to get_session_store_delegate).
An object must always be returned from this method, even if it means autovivifying. The object may optimize and create itself lazily in the actual store only when ->store methods are actually called.
A single delegate belongs to a single session ID. It provides storage space for arbitrary fields.
The delegate object must respond to method calls as per the
session_store_delegate_key_to_accessor method's return values.
Typically this means responding to $obj->$field type accessors.
If necessary, the delegate should maintain an internal reference count of the stored fields, so that it can garbage collect itself when all fields have been deleted.
The fields are arbitrary, and are goverend by the various session plugins.
The basic keys that must be supported are:
A timestamp indicating when the session will expire.
If a store so chooses it may clean up session data after this timestamp, even without being told to delete.
The main session data hash.
Might not be used, if only flash exists.
A hash much like the main session data hash, which can be created and deleted multiple times per session, as required.
The delegate must also respond to the flush method which is used to tell the
store delegate that no more set/get/delete methods will be invoked on it.
This method implements the various calling conventions. It accepts a key and an
operation name (get, set or delete), and must return a method (could
be a string or a code reference), and an optional list of arguments that will
be invoked on the delegate.
The default version splits $key on the first colon, extracting the field name
and the ID. It then returns the unaltered field name, and if the operation is
'delete' also provides the extra argument undef. This works with accessor
semantics like these:
$obj->foo;
$obj->foo("bar");
$obj->foo(undef);
To facilitate a convention like
$obj->get_foo;
$obj->set_foo("bar");
$obj->delete_foo;
or
$obj->get("foo");
$obj->set("foo", "bar");
$obj->delete("foo");
simply override this method. You may look in the source of this module to find commented out versions which should help you.
This method returns the delegate, which may be cached in $c.
This method should get the delegate object for a given ID. See "THE MODEL" for more details.
This method should return the model that will provide the delegate object.The
default implementation will simply return
$c->model( $c->session_store_model_name ).
Returns $c->config->{session}{model_name} || "Sessions".
Invokes the flush method on the delegate. May be overridden if that behavior
is inappropriate.
These methods translate the store API into the delegate API using
session_store_delegate_key_to_accessor.
Yuval Kogman, nothingmuch@woobling.org
Tomas Doran, (t0m) bobtfish@bobtfish.net (current maintainer)
Copyright (c) 2006 the aforementioned authors. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
| Catalyst-Plugin-Session-Store-Delegate documentation | Contained in the Catalyst-Plugin-Session-Store-Delegate distribution. |
#!/usr/bin/perl package Catalyst::Plugin::Session::Store::Delegate; use Moose; use MRO::Compat; use namespace::clean -except => 'meta'; extends 'Catalyst::Plugin::Session::Store'; with 'MooseX::Emulate::Class::Accessor::Fast'; our $VERSION = "0.06"; __PACKAGE__->mk_accessors(qw/_session_store_delegate/); sub session_store_model_name { my $c = shift; $c->_session_plugin_config->{model} || "Sessions"; } sub session_store_model { my ( $c, $id ) = @_; # $id may be used in for e.g. keyspace partitioning my $name = $c->session_store_model_name; $c->model( $name, $id ) || die "Couldn't find a model named $name"; } sub session_store_delegate { my ( $c, $id ) = @_; my $obj = $c->_session_store_delegate; unless($obj) { unless ($id) { $c->create_session_id_if_needed; $id = $c->sessionid; } $obj = $c->get_session_store_delegate($id); $c->_session_store_delegate($obj) } return $obj; } sub get_session_store_delegate { my ( $c, $id ) = @_; # $model is not necessarily a catalyst model, just something that can # ->get_session_store_delegate($id) my $model = $c->session_store_model($id); # allow methods or arbitrary code refs my $method = $c->_session_plugin_config->{get_delegate} || "get_session_store_delegate"; $model->$method($id) || die "couldn't get delegate from model: $model with method: $method"; } sub _clear_session_instance_data { my ( $c, @args ) = @_; my $ret = $c->maybe::next::method(@args); # let the session plugin do it's thing my $delegate = $c->_session_store_delegate; $c->_session_store_delegate(undef); $c->finalize_session_delegate($delegate) if $delegate; return $ret; } sub finalize_session_delegate { my ( $c, $obj ) = @_; $obj->flush; } sub session_store_delegate_key_to_accessor { my ( $self, $key, $operation, @args ) = @_; my ( $field, $id ) = split(':', $key, 2); return ( $field, ($operation eq "delete" ? (undef, @args) : @args ) ); # delete is effectively set to undef # return ( join("_", $operation, $field) ); # for (get|set|delete)_foo type accessors # return ( $operation, $field ) # for get("foo"), set("foo") type accessors } sub get_session_data { my ( $c, $key ) = @_; my ( $accessor, @args ) = $c->session_store_delegate_key_to_accessor($key, "get"); $c->session_store_delegate->$accessor(@args); } sub store_session_data { my ( $c, $key, $value ) = @_; my ( $accessor, @args ) = $c->session_store_delegate_key_to_accessor($key, "set", $value); $c->session_store_delegate->$accessor(@args); } sub delete_session_data { my ( $c, $key ) = @_; my ( $accessor, @args ) = $c->session_store_delegate_key_to_accessor($key, "delete"); $c->session_store_delegate->$accessor(@args); } sub delete_expired_sessions { my $c = shift; my $model = $c->session_store_model; if ( eval { $model->can("delete_expired_sessions") } ) { $model->delete_expired_sessions; } } __PACKAGE__->meta->make_immutable; __PACKAGE__; __END__