X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FDispatcher.pm;h=68fe551a22e77b2873cb25bff91a5c036e690121;hb=382d317c39473fe7792a08d071f00883f50ed73b;hp=3cb06eabe863cc32435cd4c6b48532a5ed330438;hpb=12f0342e49c1b2af2e71c30aa4dcfbac0b7735c2;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Dispatcher.pm b/lib/Catalyst/Dispatcher.pm index 3cb06ea..68fe551 100644 --- a/lib/Catalyst/Dispatcher.pm +++ b/lib/Catalyst/Dispatcher.pm @@ -10,10 +10,10 @@ use Catalyst::Action; use Catalyst::ActionContainer; use Catalyst::DispatchType::Default; use Catalyst::DispatchType::Index; +use Catalyst::Utils; use Text::SimpleTable; use Tree::Simple; use Tree::Simple::Visitor::FindByPath; -use Scalar::Util (); # Refactoring note: # do these belong as package vars or should we build these via a builder method? @@ -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 } @@ -146,7 +149,7 @@ sub _command2action { # go to a string path ("/foo/bar/gorch") # or action object - if (Scalar::Util::blessed($command) && $command->isa('Catalyst::Action')) { + if (blessed($command) && $command->isa('Catalyst::Action')) { $action = $command; } else { @@ -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": / @@ -316,6 +320,11 @@ sub _invoke_as_component { my $class = $self->_find_component_class( $c, $component ) || return 0; + if (my $code = $component_instance->can('action_for')) { + my $possible_action = $component_instance->$code($method); + return $possible_action if $possible_action; + } + if ( my $code = $class->can($method) ) { return $self->_method_action_class->new( { @@ -472,7 +481,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 +573,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,11 +593,15 @@ 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( - [ 20, 'Private' ], - [ 36, 'Class' ], - [ 12, 'Method' ] + [ 20, 'Private' ], [ 36, 'Class' ], [ $column_width, 'Method' ] ); my $has_private = 0; @@ -637,6 +652,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. @@ -666,7 +695,7 @@ foreach my $public_method_name (qw/ my %package_hash; # Only warn once per method, per package. These are infrequent enough that # I haven't provided a way to disable them, patches welcome. $meta->add_before_method_modifier($public_method_name, sub { - my $class = Scalar::Util::blessed(shift); + my $class = blessed(shift); $package_hash{$class}++ || do { warn("Class $class is calling the deprecated method Catalyst::Dispatcher::$public_method_name,\n" . "this will be removed in Catalyst 5.9X");