X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Runtime.git;a=blobdiff_plain;f=lib%2FCatalyst%2FDispatchType%2FChained.pm;h=ec0e74305b94781ab484f80867efb695606fafc6;hp=24376983ffe86a1e25db2f6beb829ee30b6cdca7;hb=a273dd589895d687efd358d65f2cc4e623350e97;hpb=f4de8c998c61fd442cb9590a3c052cf41b4c0d67 diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index 2437698..ec0e743 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -96,14 +96,15 @@ sub list { sort { $a->reverse cmp $b->reverse } @{ $self->_endpoints } ) { - my $args = $endpoint->attributes->{Args}->[0]; + my $args = $endpoint->list_extra_info->{Args}; my @parts = (defined($args) ? (("*") x $args) : '...'); my @parents = (); my $parent = "DUMMY"; + my $extra = $self->_list_extra_http_methods($endpoint); my $curr = $endpoint; while ($curr) { - if (my $cap = $curr->attributes->{CaptureArgs}) { - unshift(@parts, (("*") x $cap->[0])); + if (my $cap = $curr->list_extra_info->{CaptureArgs}) { + unshift(@parts, (("*") x $cap)); } if (my $pp = $curr->attributes->{PathPart}) { unshift(@parts, $pp->[0]) @@ -121,15 +122,19 @@ sub list { my @rows; foreach my $p (@parents) { my $name = "/${p}"; - if (my $cap = $p->attributes->{CaptureArgs}) { - $name .= ' ('.$cap->[0].')'; + + if (defined(my $extra = $self->_list_extra_http_methods($p))) { + $name = "${extra} ${name}"; + } + if (defined(my $cap = $p->list_extra_info->{CaptureArgs})) { + $name .= ' ('.$cap.')'; } unless ($p eq $parents[0]) { $name = "-> ${name}"; } push(@rows, [ '', $name ]); } - push(@rows, [ '', (@rows ? "=> " : '')."/${endpoint}" ]); + push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : '')."/${endpoint}" ]); $rows[0][0] = join('/', '', @parts) || '/'; $paths->row(@$_) for @rows; } @@ -139,6 +144,12 @@ sub list { if $has_unattached_actions; } +sub _list_extra_http_methods { + my ( $self, $action ) = @_; + return unless defined $action->list_extra_info->{HTTP_METHODS}; + return join(', ', @{$action->list_extra_info->{HTTP_METHODS}}); +} + =head2 $self->match( $c, $path ) Calls C to see if a chain matches the C<$path>. @@ -201,9 +212,10 @@ sub recurse_match { my @try_actions = @{$children->{$try_part}}; TRY_ACTION: foreach my $action (@try_actions) { if (my $capture_attr = $action->attributes->{CaptureArgs}) { + $capture_attr ||= 0; # Short-circuit if not enough remaining parts - next TRY_ACTION unless @parts >= ($capture_attr->[0]||0); + next TRY_ACTION unless @parts >= $capture_attr->[0]; my @captures; my @parts = @parts; # localise @@ -211,6 +223,9 @@ sub recurse_match { # strip CaptureArgs into list push(@captures, splice(@parts, 0, $capture_attr->[0])); + # check if the action may fit, depending on a given test by the app + if ($action->can('match_captures')) { next TRY_ACTION unless $action->match_captures($c, \@captures) } + # try the remaining parts against children of this action my ($actions, $captures, $action_parts, $n_pathparts) = $self->recurse_match( $c, '/'.$action->reverse, \@parts @@ -249,7 +264,7 @@ sub recurse_match { if (!$best_action || @parts < @{$best_action->{parts}} || - (!@parts && $args_attr eq 0)){ + (!@parts && defined($args_attr) && $args_attr eq "0")){ $best_action = { actions => [ $action ], captures=> [], @@ -357,7 +372,7 @@ sub uri_for_action { my $curr = $action; while ($curr) { if (my $cap = $curr->attributes->{CaptureArgs}) { - return undef unless @captures >= $cap->[0]; # not enough captures + return undef unless @captures >= ($cap->[0]||0); # not enough captures if ($cap->[0]) { unshift(@parts, splice(@captures, -$cap->[0])); } @@ -670,9 +685,18 @@ of the endpoint of the chain, not on the chained actions way. The C actions will be run before the chain dispatching begins. In every other aspect, C actions behave as documented. -The Cing to other actions does just what you would expect. But if -you C out of a chain, the rest of the chain will not get called -after the C. +The Cing to other actions does just what you would expect. ie +only the target action is run. The actions that that action is chained +to are not run. +If you C out of a chain, the rest of the chain will not get +called after the C. + +=head2 match_captures + +A method which can optionally be implemented by actions to +stop chain matching. + +See L for further details. =head1 AUTHORS