X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FDispatcher.pm;h=6e182fa847146307b06fbd792fda2da07287740b;hb=542a67cf086b9e90d16d87e6f7ef0c1d02bacf03;hp=ae8946f593a6b3c530df38b245c93d91edd85104;hpb=80ef521fc623bcd3139f0e282e23959a3dcb4e76;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Dispatcher.pm b/lib/Catalyst/Dispatcher.pm index ae8946f..6e182fa 100644 --- a/lib/Catalyst/Dispatcher.pm +++ b/lib/Catalyst/Dispatcher.pm @@ -32,8 +32,8 @@ has _registered_dispatch_types => (is => 'rw', default => sub { {} }, required = has _method_action_class => (is => 'rw', default => 'Catalyst::Action'); has _action_hash => (is => 'rw', required => 1, lazy => 1, default => sub { {} }); has _container_hash => (is => 'rw', required => 1, lazy => 1, default => sub { {} }); - has preload_dispatch_types => (is => 'rw', required => 1, lazy => 1, default => sub { [@PRELOAD] }); + has postload_dispatch_types => (is => 'rw', required => 1, lazy => 1, default => sub { [@POSTLOAD] }); # Wrap accessors so you can assign a list and it will capture a list ref. @@ -101,7 +101,6 @@ it with a C<+>, like so: Delegate the dispatch to the action that matched the url, or return a message about unknown resource - =cut sub dispatch { @@ -109,7 +108,6 @@ sub dispatch { if ( my $action = $c->action ) { $c->forward( join( '/', '', $action->namespace, '_DISPATCH' ) ); } - else { my $path = $c->req->path; my $error = $path @@ -121,7 +119,8 @@ sub dispatch { } # $self->_command2action( $c, $command [, \@arguments ] ) -# Search for an action, from the command and returns C<($action, $args)> on +# $self->_command2action( $c, $command [, \@captures, \@arguments ] ) +# Search for an action, from the command and returns C<($action, $args, $captures)> on # success. Returns C<(0)> on error. sub _command2action { @@ -132,7 +131,11 @@ sub _command2action { return 0; } - my @args; + my (@args, @captures); + + if ( ref( $extra_params[-2] ) eq 'ARRAY' ) { + @captures = @{ pop @extra_params }; + } if ( ref( $extra_params[-1] ) eq 'ARRAY' ) { @args = @{ pop @extra_params } @@ -160,7 +163,7 @@ sub _command2action { $action = $self->_invoke_as_component( $c, $command, $method ); } - return $action, \@args; + return $action, \@args, \@captures; } =head2 $self->visit( $c, $command [, \@arguments ] ) @@ -178,7 +181,7 @@ sub _do_visit { my $self = shift; my $opname = shift; my ( $c, $command ) = @_; - my ( $action, $args ) = $self->_command2action(@_); + my ( $action, $args, $captures ) = $self->_command2action(@_); my $error = qq/Couldn't $opname("$command"): /; if (!$action) { @@ -187,7 +190,7 @@ sub _do_visit { } 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./ + .qq/method or component, must be an :Action of some sort./ } elsif (!$action->class->can('_DISPATCH')) { $error .= qq/Action cannot _DISPATCH. / @@ -206,6 +209,7 @@ sub _do_visit { $action = $self->expand_action($action); local $c->request->{arguments} = $args; + local $c->request->{captures} = $captures; local $c->{namespace} = $action->{'namespace'}; local $c->{action} = $action; @@ -239,7 +243,7 @@ sub _do_forward { my $self = shift; my $opname = shift; my ( $c, $command ) = @_; - my ( $action, $args ) = $self->_command2action(@_); + my ( $action, $args, $captures ) = $self->_command2action(@_); if (!$action) { my $error .= qq/Couldn't $opname to command "$command": / @@ -303,35 +307,44 @@ sub _invoke_as_path { } } -sub _find_component_class { +sub _find_component { my ( $self, $c, $component ) = @_; - return ref($component) - || ref( $c->component($component) ) - || $c->component($component); + # fugly, why doesn't ->component('MyApp') work? + return $c if ($component eq blessed($c)); + + return blessed($component) + ? $component + : $c->component($component); } sub _invoke_as_component { - my ( $self, $c, $component, $method ) = @_; + my ( $self, $c, $component_or_class, $method ) = @_; - my $class = $self->_find_component_class( $c, $component ) || return 0; + my $component = $self->_find_component($c, $component_or_class); + my $component_class = blessed $component || return 0; - if ( my $code = $class->can($method) ) { + if (my $code = $component_class->can('action_for')) { + my $possible_action = $component->$code($method); + return $possible_action if $possible_action; + } + + if ( my $code = $component_class->can($method) ) { return $self->_method_action_class->new( { name => $method, code => $code, - reverse => "$class->$method", - class => $class, + reverse => "$component_class->$method", + class => $component_class, namespace => Catalyst::Utils::class2prefix( - $class, $c->config->{case_sensitive} + $component_class, $c->config->{case_sensitive} ), } ); } else { my $error = - qq/Couldn't forward to "$class". Does not implement "$method"/; + qq/Couldn't forward to "$component_class". Does not implement "$method"/; $c->error($error); $c->log->debug($error) if $c->debug; @@ -472,7 +485,7 @@ sub uri_for_action { return undef; } -=head2 expand_action +=head2 expand_action expand an action into a full representation of the dispatch. mostly useful for chained, other actions will just return a @@ -564,13 +577,15 @@ sub _find_or_create_namespace_node { =head2 $self->setup_actions( $class, $context ) +Loads all of the preload dispatch types, registers their actions and then +loads all of the postload dispatch types, and iterates over the tree of +actions, displaying the debug information if appropriate. =cut sub setup_actions { my ( $self, $c ) = @_; - my @classes = $self->_load_dispatch_types( @{ $self->preload_dispatch_types } ); @{ $self->_registered_dispatch_types }{@classes} = (1) x @classes; @@ -582,6 +597,11 @@ sub setup_actions { $self->_load_dispatch_types( @{ $self->postload_dispatch_types } ); return unless $c->debug; + $self->_display_action_tables($c); +} + +sub _display_action_tables { + my ($self, $c) = @_; my $column_width = Catalyst::Utils::term_width() - 20 - 36 - 12; my $privates = Text::SimpleTable->new( @@ -636,6 +656,20 @@ sub _load_dispatch_types { return @loaded; } +# Dont document this until someone else is happy with beaviour. Ash 2009/03/16 +sub dispatch_type { + my ($self, $name) = @_; + + unless ($name =~ s/^\+//) { + $name = "Catalyst::DispatchType::" . $name; + } + + for (@{ $self->_dispatch_types }) { + return $_ if ref($_) eq $name; + } + return undef; +} + use Moose; # 5.70 backwards compatibility hacks.