fix issues with middleware stash localizing stuff
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Middleware / Stash.pm
index 8560828..0ed488d 100644 (file)
@@ -1,33 +1,53 @@
-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.v2' }
+
+sub get_stash {
+  my $env = shift;
+  return $env->{+PSGI_KEY} ||
+   croak "You requested a stash, but one does not exist.";
+}
+
+sub stash {
+  my ($host, @args) = @_;
+  return get_stash($host->env)
+    ->(@args);
 }
 
-sub get {
-  my ($class, $env) = @_;
-  return $env->{&PSGI_KEY};
+sub _create_stash {
+  my $self = shift;
+  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);
+  $env->{+PSGI_KEY} = $self->_create_stash 
+    unless exists($env->{+PSGI_KEY});
+
   return $self->app->($env);
 }
 
-=head1 TITLE
+=head1 NAME
 
 Catalyst::Middleware::Stash - The Catalyst stash - in middleware
 
@@ -37,17 +57,66 @@ We've moved the L<Catalyst> stash to middleware.  Please don't use this
 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 underlying hashref.
+
+Anything placed into the stash will be available in the stash of any 'mounted'
+Catalyst applictions.  A mounted Catalyst application may set the stash and
+'pass back' information to the parent application.  Non Catalyst applications
+may use this middleware to access and set stash values.
+
+Please note I highly recommend having a stronger interface than a stash key
+between applications.
+
+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