X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FDispatcher.pm;h=2f5430ec935f1a9b99b9773c45a7f8fd94644f36;hb=3295c7dbc672a0d1c03f657a2a37f12f322bbece;hp=91ae6fc8ddf21671d95203857f78178efc2ad857;hpb=52f71256fa6baba38de781b3074884ff0d12769f;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Dispatcher.pm b/lib/Catalyst/Dispatcher.pm index 91ae6fc..2f5430e 100644 --- a/lib/Catalyst/Dispatcher.pm +++ b/lib/Catalyst/Dispatcher.pm @@ -84,18 +84,6 @@ it with a C<+>, like so: +My::Dispatch::Type -=head2 $self->detach( $c, $command [, \@arguments ] ) - -Documented in L - -=cut - -sub detach { - my ( $self, $c, $command, @args ) = @_; - $c->forward( $command, @args ) if $command; - die $Catalyst::DETACH; -} - =head2 $self->dispatch($c) Delegate the dispatch to the action that matched the url, or return a @@ -145,8 +133,13 @@ sub _command2action { my $action; # go to a string path ("/foo/bar/gorch") - # or action object which stringifies to that - $action = $self->_invoke_as_path( $c, "$command", \@args ); + # or action object + if (Scalar::Util::blessed($command) && $command->isa('Catalyst::Action')) { + $action = $command; + } + else { + $action = $self->_invoke_as_path( $c, "$command", \@args ); + } # go to a component ( "MyApp::*::Foo" or $c->component("...") # - a path or an object) @@ -158,21 +151,41 @@ sub _command2action { return $action, \@args; } -=head2 $self->go( $c, $command [, \@arguments ] ) +=head2 $self->visit( $c, $command [, \@arguments ] ) Documented in L =cut -sub go { +sub visit { + my $self = shift; + $self->_do_visit('visit', @_); +} + +sub _do_visit { my $self = shift; + my $opname = shift; my ( $c, $command ) = @_; my ( $action, $args ) = $self->_command2action(@_); + my $error = qq/Couldn't $opname("$command"): /; - unless ($action && defined $action->namespace) { - my $error = - qq/Couldn't go to command "$command": / - . qq/Invalid action or component./; + if (!$action) { + $error .= qq/Couldn't $opname to command "$command": / + .qq/Invalid action or component./; + } + elsif (!defined $action->namespace) { + $error .= qq/Action has no namespace: cannot $opname() to a plain / + .qq/method or component, must be a :Action or some sort./ + } + elsif (!$action->class->can('_DISPATCH')) { + $error .= qq/Action cannot _DISPATCH. / + .qq/Did you try to $opname() a non-controller action?/; + } + else { + $error = q(); + } + + if($error) { $c->error($error); $c->log->debug($error) if $c->debug; return 0; @@ -181,10 +194,21 @@ sub go { $action = $self->expand_action($action); local $c->request->{arguments} = $args; - $c->namespace($action->namespace); - $c->action($action); + local $c->{namespace} = $action->{'namespace'}; + local $c->{action} = $action; + $self->dispatch($c); +} + +=head2 $self->go( $c, $command [, \@arguments ] ) + +Documented in L + +=cut +sub go { + my $self = shift; + $self->_do_visit('go', @_); die $Catalyst::GO; } @@ -196,30 +220,45 @@ Documented in L sub forward { my $self = shift; + $self->_do_forward(forward => @_); +} + +sub _do_forward { + my $self = shift; + my $opname = shift; my ( $c, $command ) = @_; my ( $action, $args ) = $self->_command2action(@_); - unless ($action) { - my $error = - qq/Couldn't forward to command "$command": / - . qq/Invalid action or component./; + if (!$action) { + my $error .= qq/Couldn't $opname to command "$command": / + .qq/Invalid action or component./; $c->error($error); $c->log->debug($error) if $c->debug; return 0; } - #push @$args, @_; - no warnings 'recursion'; my $orig_args = $c->request->arguments(); $c->request->arguments($args); $action->dispatch( $c ); $c->request->arguments($orig_args); - + return $c->state; } +=head2 $self->detach( $c, $command [, \@arguments ] ) + +Documented in L + +=cut + +sub detach { + my ( $self, $c, $command, @args ) = @_; + $self->_do_forward(detach => $c, $command, @args ) if $command; + die $Catalyst::DETACH; +} + sub _action_rel2abs { my ( $self, $c, $path ) = @_; @@ -327,7 +366,7 @@ sub prepare_action { s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg for grep { defined } @{$req->captures||[]}; $c->log->debug( 'Path is "' . $req->match . '"' ) - if ( $c->debug && length $req->match ); + if ( $c->debug && defined $req->match && length $req->match ); $c->log->debug( 'Arguments are "' . join( '/', @args ) . '"' ) if ( $c->debug && @args ); @@ -423,6 +462,14 @@ sub uri_for_action { return undef; } +=head2 expand_action + +expand an action into a full representation of the dispatch. +mostly useful for chained, other actions will just return a +single action. + +=cut + sub expand_action { my ($self, $action) = @_;