[Jifty-commit] r1416 - in jifty/trunk: . lib/Jifty lib/Jifty/Test/WWW t t/Continuations/lib/Continuations t/Continuations/share/web/templates t/Continuations/t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Sat Jul 1 04:15:54 EDT 2006


Author: alexmv
Date: Sat Jul  1 04:15:52 2006
New Revision: 1416

Modified:
   jifty/trunk/   (props changed)
   jifty/trunk/lib/Jifty/Continuation.pm
   jifty/trunk/lib/Jifty/Handler.pm
   jifty/trunk/lib/Jifty/Request.pm
   jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm
   jifty/trunk/lib/Jifty/Web.pm
   jifty/trunk/lib/Jifty/Web/PageRegion.pm
   jifty/trunk/t/03-form-protocol.t
   jifty/trunk/t/Continuations/lib/Continuations/Dispatcher.pm
   jifty/trunk/t/Continuations/share/web/templates/index.html
   jifty/trunk/t/Continuations/t/04-before-blocks.t

Log:
 r14681 at zoq-fot-pik:  chmrr | 2006-07-01 04:15:40 -0400
  * Remove old clone code; it can be re-added when it is better
 thought-out, but currently it just adds non-working complexity.
  * Continuation calls now are formally split into two phases, call and
 return.  Return is in the caller's context (path) and is handled as
 early as possible, so that the dispatcher doesn't see the return path
 more than once.  Call is equivilent to a 'return' statement, and is in
 the continuation's context.
  * Refactor continuations to use data structures in Requests
  * Bulletproof data structure parsing slightly
  * Specify that actions added to requests with add_action are forced
 to not have run yet


Modified: jifty/trunk/lib/Jifty/Continuation.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Continuation.pm	(original)
+++ jifty/trunk/lib/Jifty/Continuation.pm	Sat Jul  1 04:15:52 2006
@@ -79,13 +79,6 @@
 An optional subroutine reference to evaluate when the continuation is
 called.
 
-=item clone
-
-There is a interface to support continuation "cloning," a process
-which is useful to creating multi-page wizards and the like.  However,
-this feature is still very much in flux; the documentation is waiting
-for the interface to settle down a bit before being written.
-
 =back
 
 =cut
@@ -99,7 +92,6 @@
                 request  => Jifty::Request->new(),
                 response => Jifty::Response->new(),
                 code     => undef,
-                clone    => undef,
                 @_
                );
 
@@ -107,19 +99,9 @@
     $args{parent} = $args{parent}->id
       if $args{parent} and ref $args{parent};
 
-    # We're cloning most of our attributes from a previous continuation
-    if ($args{clone} and Jifty->web->session->get_continuation($args{clone})) {
-        $self = dclone(Jifty->web->session->get_continuation($args{clone}));
-        for (grep {/^J:A/} keys %{$args{request}->arguments}) {
-            $self->request->argument($_ => $args{request}->arguments->{$_});
-        }
-        $self->response($args{response});
-    } else {
-        delete $args{clone};
-        # We're getting most of our properties from the arguments
-        for (keys %args) {
-            $self->$_($args{$_}) if $self->can($_);
-        }
+    # We're getting most of our properties from the arguments
+    for (keys %args) {
+        $self->$_($args{$_}) if $self->can($_);
     }
 
     # Generate a hopefully unique ID
@@ -133,21 +115,15 @@
     return $self;
 }
 
-=head2 call
+=head2 return_path_matches
 
-Call the continuation; this is generally done during request
-processing, after an actions have been run.
-L<Jifty::Request::Mapper>-controlled values are filled into the stored
-request based on the current request and response.  If an values
-needed to be filled in, then *another* continuation is created, with
-the filled-in values included, and the browser is redirected there.
-This is to ensure that we end up at the correct request path, while
-keeping continuations immutable and maintaining all of the request
-state that we need.
+Returns true if the continuation matches the current request's path,
+and it would return to its caller in this context.  This can be used
+to ask "are we about to call a continuation?"
 
 =cut
 
-sub call {
+sub return_path_matches {
     my $self = shift;
     my $called_uri = $ENV{'REQUEST_URI'};
     my $request_path = $self->request->path;
@@ -159,65 +135,89 @@
     $request_path =~ s{/+}{/}g; 
     $request_path = $escape while $request_path ne ($escape = URI::Escape::uri_unescape($request_path));
 
-    if (defined $request_path and 
-        ($called_uri !~ /^\Q$request_path\E[?&;]J:CALL=@{[$self->id]}/)) {
-        # If we needed to fix up the path (it contains invalid
-        # characters) then warn, because this may cause infinite
-        # redirects
-        Jifty->log->warn("Redirect to '@{[$self->request->path]}' contains unsafe characters")
-          if $self->request->path =~ m{[^A-Za-z0-9\-_.!~*'()/?&;+]};
-
-        # Clone our request
-        my $request = dclone($self->request);
-        
-        # Fill in return value(s) into correct part of $request
-        $request->do_mapping;
-
-        my $response = $self->response;
-        # If the current response has results, we need to pull them
-        # in.  For safety, monikers from the saved continuation
-        # override those from the request prior to the call
-        if (Jifty->web->response->results) {
-            $response = dclone(Jifty->web->response);
-            my %results = $self->response->results;
-            $response->result($_ => $results{$_}) for keys %results;
-        }
-        
-        # Make a new continuation with that request
-        my $next = Jifty::Continuation->new(parent => $self->parent, 
-                                            request => $request,
-                                            response => $response,
-                                            code => $self->code,
-                                           );
-        $next->request->continuation(Jifty->web->session->get_continuation($next->parent))
-          if defined $next->parent;
-
-        # Redirect to right page if we're not there already
-        Jifty->web->_redirect($next->request->path . "?J:CALL=" . $next->id);
-    } else {
-        # Pull state information out of the continuation and set it
-        # up; we use clone so that the continuation itself is
-        # immutable.  It is vaguely possible that there are results in
-        # the response already (set up by the dispatcher) so we place
-        # results from the continuation's response into the existing
-        # response only if it wouldn't clobber something.
+    return $called_uri =~ /^\Q$request_path\E[?&;]J:RETURN=@{[$self->id]}$/;
+}
+
+=head2 call
+
+Call the continuation; this is generally done during request
+processing, after an actions have been run.
+L<Jifty::Request::Mapper>-controlled values are filled into the stored
+request based on the current request and response.  During the
+process, another continuation is created, with the filled-in results
+of the current actions included, and the browser is redirected to the
+proper path, with that continuation.
+
+=cut
+
+sub call {
+    my $self = shift;
+
+    # If we needed to fix up the path (it contains invalid
+    # characters) then warn, because this may cause infinite
+    # redirects
+    Jifty->log->warn("Redirect to '@{[$self->request->path]}' contains unsafe characters")
+      if $self->request->path =~ m{[^A-Za-z0-9\-_.!~*'()/?&;+]};
+
+    # Clone our request
+    my $request = $self->request->clone;
+
+    # Fill in return value(s) into correct part of $request
+    $request->do_mapping;
+
+    my $response = $self->response;
+    # If the current response has results, we need to pull them
+    # in.  For safety, monikers from the saved continuation
+    # override those from the request prior to the call
+    if (Jifty->web->response->results) {
+        $response = dclone(Jifty->web->response);
         my %results = $self->response->results;
-        for (keys %results) {
-            next if Jifty->web->response->result($_);
-            Jifty->web->response->result($_,dclone($results{$_}));
-        }
-
-        # Run any code in the continuation
-        $self->code->(Jifty->web->request)
-          if $self->code;
-
-        # Enter the request in the continuation, and handle it.  This
-        # will possibly cause 'before' blocks to run more than once,
-        # but is slightly preferrable to them never running.
-        Jifty->web->request(dclone($self->request));
-        Jifty->handler->dispatcher->handle_request;
-        Jifty::Dispatcher::_abort;
+        $response->result($_ => $results{$_}) for keys %results;
+    }
+
+    # Make a new continuation with that request
+    my $next = Jifty::Continuation->new(parent => $self->parent, 
+                                        request => $request,
+                                        response => $response,
+                                        code => $self->code,
+                                       );
+    $next->request->continuation(Jifty->web->session->get_continuation($next->parent))
+      if defined $next->parent;
+
+    # Redirect to right page if we're not there already
+    Jifty->web->_redirect($next->request->path . "?J:RETURN=" . $next->id);
+}
+
+=head2 return
+
+Returns from the continuation by pulling out the stored request, and
+setting that to be the active request.  This shouldn't need to be
+called by hand -- use L<Jifty::Request/return_from_continuation>,
+which ensures that all requirements are ment before it calls this.
+
+=cut
+
+sub return {
+    my $self = shift;
+
+    # Pull state information out of the continuation and set it
+    # up; we use clone so that the continuation itself is
+    # immutable.  It is vaguely possible that there are results in
+    # the response already (set up by the dispatcher) so we place
+    # results from the continuation's response into the existing
+    # response only if it wouldn't clobber something.
+    my %results = $self->response->results;
+    for (keys %results) {
+        next if Jifty->web->response->result($_);
+        Jifty->web->response->result($_,dclone($results{$_}));
     }
+
+    # Run any code in the continuation
+    $self->code->(Jifty->web->request)
+      if $self->code;
+
+    # Set the current request to the one in the continuation
+    return Jifty->web->request($self->request->clone);
 }
 
 =head2 delete

Modified: jifty/trunk/lib/Jifty/Handler.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Handler.pm	(original)
+++ jifty/trunk/lib/Jifty/Handler.pm	Sat Jul  1 04:15:52 2006
@@ -185,10 +185,10 @@
     # Build a new stash for the life of this request
     $self->stash({});
     local $HTML::Mason::Commands::JiftyWeb = Jifty::Web->new();
-    Jifty->web->request( Jifty::Request->new()->fill( $self->cgi ) );
 
-    Jifty->web->response( Jifty::Response->new );
     Jifty->web->setup_session;
+    Jifty->web->request( Jifty::Request->new()->fill( $self->cgi ) );
+    Jifty->web->response( Jifty::Response->new );
     Jifty->web->session->set_cookie;
     Jifty->api->reset;
     $_->new_request for Jifty->plugins;
@@ -200,6 +200,9 @@
         = $self->static_handler->handle_request( Jifty->web->request->path )
         if ( Jifty->config->framework('Web')->{'ServeStaticFiles'} );
 
+    # Return from the continuation if need be
+    Jifty->web->request->return_from_continuation;
+
     $self->dispatcher->handle_request() unless ($sent_response);
 
     $self->cleanup_request();

Modified: jifty/trunk/lib/Jifty/Request.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Request.pm	(original)
+++ jifty/trunk/lib/Jifty/Request.pm	Sat Jul  1 04:15:52 2006
@@ -4,10 +4,11 @@
 package Jifty::Request;
 
 use base qw/Jifty::Object Class::Accessor::Fast/;
-__PACKAGE__->mk_accessors(qw(_top_request arguments just_validating path _continuation));
+__PACKAGE__->mk_accessors(qw(_top_request arguments just_validating path continuation_id continuation_type continuation_path));
 
 use Jifty::JSON;
 use Jifty::YAML;
+use Storable 'dclone';
 
 =head1 NAME
 
@@ -88,6 +89,17 @@
     return $self;
 }
 
+=head2 clone
+
+Return a copy of the request.
+
+=cut
+
+sub clone {
+    my $self = shift;
+    return dclone($self);
+}
+
 =head2 fill
 
 Attempt to fill in the request from any number of various methods --
@@ -130,12 +142,18 @@
     my $self = shift;
     my $data = shift;
 
-    # TODO: continuations
-
     $self->path($data->{path});
+    $self->just_validating($data->{validating}) if $data->{validating};
+
+    if (ref $data->{continuation} eq "HASH") {
+        $self->continuation_id($data->{continuation}{id});
+        $self->continuation_type($data->{continuation}{type} || "parent");
+        $self->continuation_path($data->{continuation}{create});
+    }
 
     my %actions = %{$data->{actions} || {}};
     for my $a (values %actions) {
+        next unless ref $a eq "HASH";
         my %arguments;
         for my $arg (keys %{$a->{fields} || {}}) {
             if (ref $a->{fields}{$arg}) {
@@ -155,20 +173,21 @@
                          );
     }
 
-    my %variables = %{$data->{variables} || {}};
+    my %variables = ref $data->{variables} eq "HASH" ? %{$data->{variables}} : ();
     for my $v (keys %variables) {
         $self->add_state_variable(key => $v, value => $variables{$v});
     }
 
-    my %fragments = %{$data->{fragments} || {}};
+    my %fragments = ref $data->{fragments} eq "HASH" ? %{$data->{fragments}} : ();
     for my $f (values %fragments) {
+        next unless ref $f eq "HASH";
         my $current = $self->add_fragment(
             name      => $f->{name},
             path      => $f->{path},
             arguments => $f->{args},
             wrapper   => $f->{wrapper} || 0,
         );
-        while ($f = $f->{parent}) {
+        while (ref $f->{parent} eq "HASH" and $f = $f->{parent}) {
             $current = $current->parent(Jifty::Request::Fragment->new({
                 name => $f->{name},
                 path => $f->{path},
@@ -230,19 +249,12 @@
 
     my %args = (@_);
 
-    # We pull in the continuations first, because if we have a
-    # J:CLONE, we want the cloned values to be fallbacks
-    $self->_extract_continuations_from_webform(%args);
-
     # Pull in all of the arguments
-    # XXX ALEX: I think this breaks J:CLONE
     $self->arguments(\%args);
 
     # Extract actions and state variables
     $self->from_data_structure($self->webform_to_data_structure(%args));
 
-    $self->just_validating(1) if defined $args{'J:VALIDATE'} and length $args{'J:VALIDATE'};
-
     return $self;
 }
 
@@ -261,13 +273,33 @@
         my $value = shift;
         $self->arguments->{$key} = $value;
 
-        if ($key =~ /^J:A-(?:(\d+)-)?(.+)/s) {
-            $self->add_action(moniker => $2, class => $value, order => $1, arguments => {}, active => 1);
-        } elsif ($key =~ /^J:A:F-(\w+)-(.+)/s and $self->action($2)) {
-            $self->action($2)->argument($1 => $value);
-            $self->action($2)->modified(1);
+        if ($key eq "J:VALIDATE") {
+            $self->{validating} = $value;
+        } elsif ($key eq "J:C" and $self->continuation_type ne "return" and $self->continuation_type ne "call") {
+            # J:C Doesn't take preference over J:CALL or J:RETURN
+            $self->continuation_id($value);
+            $self->continuation_type("parent");
+        } elsif ($key eq "J:CALL" and $self->continuation_type ne "return") {
+            # J:CALL doesn't take preference over J:RETURN
+            $self->continuation_id($value);
+            $self->continuation_type("call");
+        } elsif ($key eq "J:RETURN") {
+            # J:RETURN trumps all
+            $self->continuation_id($value);
+            $self->continuation_type("return");
+        } elsif ($key eq "J:PATH") {
+            $self->continuation_path($value);
         } elsif ($key =~ /^J:V-(.*)/s) {
             $self->add_state_variable(key => $1, value => $value);
+        } elsif ($key =~ /^J:A-(?:(\d+)-)?(.+)/s) {
+            $self->add_action(moniker => $2, class => $value, order => $1, arguments => {}, active => 1);
+        } else {
+            # It's possibly a form field
+            my ($t, $a, $m) = $self->parse_form_field_name($key);
+            if ($t and $t eq "J:A:F" and $self->action($m)) {
+                $self->action($m)->argument($a => $value);
+                $self->action($m)->modified(1);
+            }
         }
     }
 
@@ -366,6 +398,17 @@
     # Pass path through
     $data->{path} = $self->path;
 
+    $data->{validating} = $args{'J:VALIDATE'} if defined $args{'J:VALIDATE'} and length $args{'J:VALIDATE'};
+
+    # Continuations
+    if ($args{'J:C'} or $args{'J:CALL'} or $args{'J:RETURN'}) {
+        $data->{continuation}{id} = $args{'J:RETURN'} || $args{'J:CALL'} || $args{'J:C'};
+        $data->{continuation}{type} = "parent" if $args{'J:C'};
+        $data->{continuation}{type} = "call"   if $args{'J:CALL'};
+        $data->{continuation}{type} = "return" if $args{'J:RETURN'};
+    }
+    $data->{continuation}{create} = $args{'J:PATH'} if $args{'J:CREATE'};
+
     # Are we only setting some actions as active?
     my $active_actions;
     if (exists $args{'J:ACTIONS'}) {
@@ -380,7 +423,7 @@
     # come before action arguments
     for my $key (sort keys %args) {
         my $value = $args{$key};
-        if( $key  =~ /^J:V-(.*)$/s ) {
+        if( $key  =~ /^J:V-(.*)/s ) {
             # It's a variable
             $data->{variables}{$1} = $value;
         } elsif ($key =~ /^J:A-(?:(\d+)-)?(.+)/s) {
@@ -402,34 +445,55 @@
     return $data;
 }
 
-sub _extract_continuations_from_webform {
-    my $self = shift;
-    my %args = (@_);
+=head2 continuation_id [CONTINUATION_ID]
 
-    if ($args{'J:CLONE'} and Jifty->web->session->get_continuations($args{'J:CLONE'})) {
-        my %params = %{Jifty->web->session->get_continuations($args{'J:CLONE'})->request->arguments};
-        $self->argument($_ => $params{$_}) for keys %params;
-    }
-}
+Gets or sets the ID of the continuation associated with the request.
+
+=cut
 
 =head2 continuation [CONTINUATION]
 
-Gets or sets the continuation associated with the request.
+Returns the L<Jifty::Continuation> object associated with this
+request, if any.
 
 =cut
 
 sub continuation {
     my $self = shift;
 
-    $self->_continuation(@_) if @_;
-    return $self->_continuation if $self->_continuation;
+    $self->continuation_id(ref $_[0] ? $_[0]->id : $_[0])
+      if @_;
 
-    foreach my $continuation_id ($self->argument('J:C'), $self->argument('J:CALL') ) {
-        next unless $continuation_id;
-        return Jifty->web->session->get_continuation($continuation_id);
-    }
+    return Jifty->web->session->get_continuation($self->continuation_id);
+}
+
+=head3 save_continuation
+
+Saves the current request and response if we've been asked to.  If we
+save the continuation, we redirect to the next page -- the call to
+C<save_continuation> never returns.
+
+=cut
+
+sub save_continuation {
+    my $self = shift;
+    my $path;
+    return unless $path = $self->continuation_path;
 
-    return undef;
+    # Clear out the create path so we don't ave the "create a
+    # continuation" into the continuation!
+    $self->continuation_path(undef);
+
+    my $c = Jifty::Continuation->new(
+        request  => $self,
+        response => Jifty->web->response,
+        parent   => $self->continuation,
+    );
+
+    # Set us up with the new continuation
+    Jifty->web->_redirect( Jifty::Web->url . $path
+                      . ( $path =~ /\?/ ? "&" : "?" ) . "J:C="
+                      . $c->id );
 }
 
 =head2 call_continuation
@@ -443,14 +507,25 @@
 
 sub call_continuation {
     my $self = shift;
-    my $cont = $self->arguments->{'J:CALL'};
-    return unless $cont and Jifty->web->session->get_continuation($cont);
-    $self->log->debug("Calling continuation $cont");
-    $self->continuation(Jifty->web->session->get_continuation($cont));
+    return if $self->is_subrequest;
+    return unless $self->continuation_type and $self->continuation_type eq "call" and $self->continuation;
+    $self->log->debug("Calling continuation ".$self->continuation->id);
     $self->continuation->call;
     return 1;
 }
 
+=head2 return_from_continuation
+
+=cut
+
+sub return_from_continuation {
+    my $self = shift;
+    return unless $self->continuation_type and $self->continuation_type eq "return" and $self->continuation;
+    return $self->continuation->call unless $self->continuation->return_path_matches;
+    $self->log->debug("Returning from continuation ".$self->continuation->id);
+    return $self->continuation->return;
+}
+
 =head2 path
 
 Returns the path that was requested
@@ -578,7 +653,7 @@
         order => undef,
         active => 1,
         arguments => undef,
-        has_run => undef,
+        has_run => 0,
         @_
     );
 
@@ -853,7 +928,7 @@
 parameters.  These are requests submitted using CGI GET or POST
 requests to your Jifty application.
 
-=head2 argument munging
+=head3 argument munging
 
 In addition to standard Mason argument munging, Jifty also takes
 arguments with a B<name> of
@@ -864,9 +939,9 @@
 separate arguments.  The purpose is to allow submit buttons to act as
 if they'd sent multiple values, without using JavaScript.
 
-=head2 actions
+=head3 actions
 
-=head3 registration
+=head4 registration
 
 For each action, the client sends a query argument whose name is
 C<J:A-I<moniker>> and whose value is the fully qualified class name of
@@ -874,7 +949,7 @@
 The registration may also take the form C<J:A-I<order>-I<moniker>>,
 which also sets the action's run order.
 
-=head3 arguments
+=head4 arguments
 
 The action's arguments are specified with query arguments of the form
 C<J:A:F-I<argumentname>-I<moniker>>.  To cope with checkboxes and the
@@ -883,19 +958,19 @@
 C<J:A:F:F-I<argumentname>-I<moniker>> and
 C<J:A:F:F:F-I<argumentname>-I<moniker>>.
 
-=head2 state variables
+=head3 state variables
 
 State variables are set via C<J:V-I<name>> being set to the value of
 the state parameter.
 
-=head2 continuations
+=head4 continuations
 
 The current continuation set by passing the parameter C<J:C>, which is
 set to the id of the continuation.  To create a new continuation, the
 parameter C<J:CREATE> is passed.  Calling a continuation is a ssimple
 as passing C<J:CALL> with the id of the continuation to call.
 
-=head2 request options
+=head3 request options
 
 The existence of C<J:VALIDATE> says that the request is only
 validating arguments.  C<J:ACTIONS> is set to a semicolon-separated
@@ -903,13 +978,12 @@
 active, while all other actions are marked inactive.  In the absence
 of C<J:ACTIONS>, all actions are active.
 
-=head1 YAML POST Request Protocol
+=head2 YAML POST Request Protocol
+
 
-To be spec'd later
+=head2 JSON POST Request Protocol
 
-=head1 JSON POST Request Protocol
 
-To be spec'd later
 
 =cut
 

Modified: jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm	(original)
+++ jifty/trunk/lib/Jifty/Test/WWW/Mechanize.pm	Sat Jul  1 04:15:52 2006
@@ -379,7 +379,7 @@
     return undef unless $session;
     
     my $id = shift;
-    ($id) = $self->uri =~ /J:C(?:ALL)?=([^&;]+)/ unless $id;
+    ($id) = $self->uri =~ /J:(?:C|CALL|RETURN)=([^&;]+)/ unless $id;
 
     return $session->get_continuation($id);
 }

Modified: jifty/trunk/lib/Jifty/Web.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web.pm	(original)
+++ jifty/trunk/lib/Jifty/Web.pm	Sat Jul  1 04:15:52 2006
@@ -16,7 +16,6 @@
 use XML::Writer;
 use CSS::Squish;
 use Digest::MD5 qw(md5_hex);
-use Storable 'dclone';
 use base qw/Class::Accessor::Fast Class::Data::Inheritable Jifty::Object/;
 
 use vars qw/$SERIAL @JS_INCLUDES/;
@@ -257,13 +256,13 @@
 
 Before they are run, however, the request has a chance to be
 interrupted and saved away into a continuation, to be resumed at some
-later point.  This is handled by L</save_continuation>.
+later point.  This is handled by L<Jifty::Request/save_continuation>.
 
 If the continuation isn't being saved, then C<handle_request> goes on
 to run all of the actions.  If all of the actions are successful, it
 looks to see if the request wished to call any continuations, possibly
 jumping back and re-running a request that was interrupted in the
-past.  This is handled by L</call_continuation>.
+past.  This is handled by L<Jifty::Request/call_continuation>.
 
 For more details about continuations, see L<Jifty::Continuation>.
 
@@ -299,7 +298,7 @@
 
         push @valid_actions, $request_action;
     }
-    $self->save_continuation;
+    $self->request->save_continuation;
 
     unless ( $self->request->just_validating ) {
         for my $request_action (@valid_actions) {
@@ -602,7 +601,7 @@
             response => $self->response,
             parent   => $self->request->continuation,
         );
-        $page = $page->url."?J:CALL=" . $cont->id;
+        $page = $page->url."?J:RETURN=" . $cont->id;
     } else {
         $page = $page->complete_url;
     }
@@ -635,87 +634,6 @@
     Jifty::Dispatcher::_abort;
 }
 
-=head3 save_continuation
-
-Saves the current request and response if we've been asked to.  If we
-save the continuation, we redirect to the next page -- the call to
-C<save_continuation> never returns.
-
-=cut
-
-sub save_continuation {
-    my $self = shift;
-
-    my %args = %{ $self->request->arguments };
-    my $clone = delete $self->request->arguments->{'J:CLONE'};
-    my $create = delete $self->request->arguments->{'J:CREATE'};
-    if ( $clone or $create ) {
-
-        # Saving a continuation
-        my $c = Jifty::Continuation->new(
-            request  => $self->request,
-            response => $self->response,
-            parent   => $self->request->continuation,
-            clone    => $clone,
-        );
-
-# XXX Only if we're cloning should we do the following check, I think??  Cloning isn't a stack push, so it works out
-        if ( $clone
-            and $self->request->just_validating
-            and $self->response->failure )
-        {
-
-# We don't get to redirect to the new page; redirect to the same page, new cont
-            $self->_redirect(
-                $self->request->path . "?J:C=" . $c->id );
-        } else {
-
-            # Set us up with the new continuation
-            $self->_redirect( Jifty::Web->url . $args{'J:PATH'}
-                    . ( $args{'J:PATH'} =~ /\?/ ? "&" : "?" ) . "J:C="
-                    . $c->id );
-        }
-
-    }
-}
-
-=head3 multipage START_URL, ARGUMENTS
-
-B<Note>: This API is very much not finalized.  Don't use it yet!
-
-Create a multipage action.  The first argument is the URL of the start
-of the multipage action -- the user will be redirected there if they
-try to enter the multipage action on any other page.  The rest of the
-arguments are passed to L<Jifty::Request/add_action> to create the
-multipage action.
-
-=cut
-
-sub multipage {
-    my $self = shift;
-    my ( $start, %args ) = @_;
-
-    my $request_action = Jifty->web->caller->action( $args{moniker} );
-
-    unless ($request_action) {
-        my $request = Jifty::Request->new();
-        $request->argument(
-            'J:CALL' => Jifty->web->request->continuation->id )
-            if Jifty->web->request->continuation;
-        $request->path("/");
-        $request->add_action(%args);
-        my $cont = Jifty::Continuation->new( request => $request );
-        Jifty->web->redirect( $start . "?J:C=" . $cont->id );
-    }
-
-    my $action = Jifty->web->new_action_from_request($request_action);
-    $action->result(
-        Jifty->web->request->continuation->response->result( $args{moniker} )
-        )
-        if Jifty->web->request->continuation->response;
-    return $action;
-}
-
 =head3 caller
 
 Returns the L<Jifty::Request> of our enclosing continuation, or an
@@ -759,11 +677,11 @@
         $clickable->state_variable( $_ => $self->{'state_variables'}{$_} )
             for keys %{ $self->{'state_variables'} };
 
-        my $request = dclone(Jifty->web->request);
+        my $request = Jifty->web->request->clone;
         my %clickable = $clickable->get_parameters;
         $request->argument($_ => $clickable{$_}) for keys %clickable;
         local Jifty->web->{request} = $request;
-        Jifty->web->handle_request();
+        Jifty->web->request->save_continuation;
     }
 }
 

Modified: jifty/trunk/lib/Jifty/Web/PageRegion.pm
==============================================================================
--- jifty/trunk/lib/Jifty/Web/PageRegion.pm	(original)
+++ jifty/trunk/lib/Jifty/Web/PageRegion.pm	Sat Jul  1 04:15:52 2006
@@ -258,14 +258,10 @@
             . qq|<div id="region-| . $self->qualified_name . qq|">|;
     }
 
-    # Merge in defaults
-    %arguments = ( %{ Jifty->web->request->arguments }, 
-                    region => $self, 
-                    %arguments );
-
     # Make a fake request and throw it at the dispatcher
-    my $subrequest = Jifty::Request->new;
-    $subrequest->from_webform(%arguments);
+    my $subrequest = Jifty->web->request->clone;
+    $subrequest->argument( region => $self );
+    $subrequest->argument( $_ => $arguments{$_}) for keys %arguments;
     $subrequest->path( $self->path );
     $subrequest->top_request( Jifty->web->request->top_request );
 

Modified: jifty/trunk/t/03-form-protocol.t
==============================================================================
--- jifty/trunk/t/03-form-protocol.t	(original)
+++ jifty/trunk/t/03-form-protocol.t	Sat Jul  1 04:15:52 2006
@@ -17,6 +17,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -43,6 +44,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -50,6 +52,7 @@
     moniker: second
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla
@@ -79,6 +82,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -86,6 +90,7 @@
     moniker: second
     class: DoThat
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla
@@ -114,6 +119,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -142,6 +148,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 0
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -149,6 +156,7 @@
     moniker: second
     class: DoThat
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla
@@ -177,6 +185,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -184,6 +193,7 @@
     moniker: second
     class: DoThat
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla
@@ -215,6 +225,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -222,6 +233,7 @@
     moniker: second
     class: DoThat
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla
@@ -253,6 +265,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -260,6 +273,7 @@
     moniker: second
     class: DoThat
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla
@@ -286,6 +300,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -311,6 +326,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -335,6 +351,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 96
         something: else
@@ -362,6 +379,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -369,6 +387,7 @@
     moniker: second
     class: DoThat
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: feepy
@@ -398,6 +417,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 123
         something: else
@@ -424,6 +444,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 123
         something: else
@@ -449,6 +470,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 456
         something: else
@@ -473,6 +495,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 789
         something: else
@@ -500,6 +523,7 @@
     moniker: mymoniker
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 23
         something: else
@@ -507,6 +531,7 @@
     moniker: second
     class: DoSomething
     active: 1
+    has_run: 0
     arguments:
         id: 42
         something: bla

Modified: jifty/trunk/t/Continuations/lib/Continuations/Dispatcher.pm
==============================================================================
--- jifty/trunk/t/Continuations/lib/Continuations/Dispatcher.pm	(original)
+++ jifty/trunk/t/Continuations/lib/Continuations/Dispatcher.pm	Sat Jul  1 04:15:52 2006
@@ -1,12 +1,12 @@
 package Continuations::Dispatcher;
 use Jifty::Dispatcher -base;
 
-
+my $before = 0;
 before '/tutorial' => run {
     unless (Jifty->web->session->get('got_help')) {
         Jifty->web->tangent(url => '/index-help.html');
     }
-    set been_helped => 1;
+    set been_helped => ++$before;
 };
 
 on '/tutorial' => run {
@@ -17,6 +17,4 @@
     Jifty->web->session->set(got_help => 1);
 };
 
-on '*' => show;
-
 1;

Modified: jifty/trunk/t/Continuations/share/web/templates/index.html
==============================================================================
--- jifty/trunk/t/Continuations/share/web/templates/index.html	(original)
+++ jifty/trunk/t/Continuations/share/web/templates/index.html	Sat Jul  1 04:15:52 2006
@@ -14,5 +14,5 @@
 <% Jifty->web->form->end %>
 
 % if($been_helped) {
-<p>Congratulations on being helped.</p>
+<p>Congratulations on being helped: <% $been_helped %>.</p>
 % }

Modified: jifty/trunk/t/Continuations/t/04-before-blocks.t
==============================================================================
--- jifty/trunk/t/Continuations/t/04-before-blocks.t	(original)
+++ jifty/trunk/t/Continuations/t/04-before-blocks.t	Sat Jul  1 04:15:52 2006
@@ -12,7 +12,7 @@
 
 BEGIN {chdir "t/Continuations"}
 use lib '../../lib';
-use Jifty::Test tests => 7;
+use Jifty::Test tests => 9;
 
 use_ok('Jifty::Test::WWW::Mechanize');
 
@@ -25,9 +25,11 @@
 $mech->follow_link_ok(text => 'Done');
 like($mech->uri, qr'/tutorial', 'Continuation call worked properly');
 $mech->content_contains('Congratulations', 'before blocks got run properly on continuation call');
+$mech->content_contains('being helped: 1', 'before blocks got run only once');
 
 $mech->get($URL . '/tutorial');
 $mech->content_contains('Congratulations', 'before blocks got run properly');
+$mech->content_contains('being helped: 2', 'before blocks got run only once again');
 
 1;
 


More information about the Jifty-commit mailing list