-package ## Hide from pause
- Catalyst::Middleware::Stash;
-
-# Please don't use this, this is likely to go away before stable version is
-# released. Ideally this could be a stand alone distribution.
-#
-
use strict;
use warnings;
+
+package Catalyst::Middleware::Stash;
+
use base 'Plack::Middleware';
+use Exporter 'import';
+use Carp 'croak';
-sub PSGI_KEY { 'Catalyst.Stash.v1' };
+our @EXPORT_OK = qw(stash get_stash);
-sub _init_stash {
- my ($self, $env) = @_;
- $env->{&PSGI_KEY} = bless +{}, 'Catalyst::Stash';
+sub PSGI_KEY () { 'Catalyst.Stash.v1' }
+
+sub get_stash {
+ my $env = shift;
+ return $env->{+PSGI_KEY} ||
+ croak "You requested a stash, but one does not exist.";
}
-sub get {
- my ($class, $env) = @_;
- return $env->{&PSGI_KEY};
+sub stash {
+ my ($host, @args) = @_;
+ return get_stash($host->env)
+ ->(@args);
+}
+
+sub _create_stash {
+ my $stash = shift || +{};
+ return sub {
+ if(@_) {
+ my $new_stash = @_ > 1 ? {@_} : $_[0];
+ croak('stash takes a hash or hashref')
+ unless ref $new_stash;
+ foreach my $key (keys %$new_stash) {
+ $stash->{$key} = $new_stash->{$key};
+ }
+ }
+ $stash;
+ };
}
sub call {
my ($self, $env) = @_;
- $self->_init_stash($env);
- return $self->app->($env);
+ my $new_env = +{ %$env };
+ my %stash = %{ ($env->{+PSGI_KEY} || sub {})->() || +{} };
+
+ $new_env->{+PSGI_KEY} = _create_stash( \%stash );
+ return $self->app->($new_env);
}
=head1 TITLE
directly since it is likely to move off the Catalyst namespace into a stand
alone distribution
-=head1 METHODS
+We store a coderef under the C<PSGI_KEY> which can be dereferenced with
+key values or nothing to access the underly hashref.
+
+The stash middleware is designed so that you can 'nest' applications that
+use it. If for example you have a L<Catalyst> application that is called
+by a controller under a parent L<Catalyst> application, the child application
+will inherit the full stash of the parent BUT any new keys added by the child
+will NOT bubble back up to the parent. However, children of children will.
+
+For more information the current test case t/middleware-stash.t is the best
+documentation.
+
+=head1 SUBROUTINES
-This class defines the following methods
+This class defines the following subroutines.
=head2 PSGI_KEY
-Returns the hash key where we store the stash
+Returns the hash key where we store the stash. You should not assume
+the string value here will never change! Also, its better to use
+L</get_stash> or L</stash>.
-=head2 get
+=head2 get_stash
+
+Expect: $psgi_env.
+
+Exportable subroutine.
+
+Get the stash out of the C<$env>.
+
+=head2 stash
+
+Expects: An object that does C<env> and arguments
+
+Exportable subroutine.
+
+Given an object with a method C<env> get or set stash values, either
+as a method or via hashref modification. This stash is automatically
+reset for each request (it is not persistent or shared across connected
+clients. Stash key / value are stored in memory.
+
+ use Plack::Request;
+ use Catalyst::Middleware::Stash 'stash';
+
+ my $app = sub {
+ my $env = shift;
+ my $req = Plack::Request->new($env);
+ my $stashed = $req->stash->{in_the_stash}; # Assume the stash was previously populated.
+
+ return [200, ['Content-Type' => 'text/plain'],
+ ["I found $stashed in the stash!"]];
+ };
+
+If the stash does not yet exist, an exception is thrown.
+
+=head1 METHODS
-Get the stash out of the C<$env>
+This class defines the following methods.
=head2 call