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=0a2a03890a3fc6756e6dd5ec8dc2df17a903cf1e;hp=d637db7f5165010ee431557f1feff74e9573d736;hb=0bf7ab7160f4f2fd0f00cd3d53ac311e9ad50241;hpb=1cf0345be8d7bf7cd33467da529885068db2b710 diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index d637db7..0a2a038 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -101,7 +101,8 @@ sub match { my @parts = split('/', $path); - my ($chain, $captures) = $self->recurse_match($c, '/', \@parts); + my ($chain, $captures, $parts) = $self->recurse_match($c, '/', \@parts); + push @{$c->req->args}, @$parts if $parts && @$parts; return 0 unless $chain; @@ -126,6 +127,7 @@ sub recurse_match { my ( $self, $c, $parent, $path_parts ) = @_; my $children = $self->{children_of}{$parent}; return () unless $children; + my $best_action; my @captures; TRY: foreach my $try_part (sort { length($b) <=> length($a) } keys %$children) { @@ -152,22 +154,44 @@ sub recurse_match { push(@captures, splice(@parts, 0, $capture_attr->[0])); # try the remaining parts against children of this action - my ($actions, $captures) = $self->recurse_match( + my ($actions, $captures, $action_parts) = $self->recurse_match( $c, '/'.$action->reverse, \@parts ); - if ($actions) { - return [ $action, @$actions ], [ @captures, @$captures ]; + if ($actions && (!$best_action || $#$action_parts < $#{$best_action->{parts}})){ + $best_action = { + actions => [ $action, @$actions ], + captures=> [ @captures, @$captures ], + parts => $action_parts + }; } - } else { + } + else { { local $c->req->{arguments} = [ @{$c->req->args}, @parts ]; next TRY_ACTION unless $action->match($c); } - push(@{$c->req->args}, @parts); - return [ $action ], [ ]; + my $args_attr = $action->attributes->{Args}->[0]; + + # No best action currently + # OR This one matches with fewer parts left than the current best action, + # And therefore is a better match + # OR No parts and this expects 0 + # The current best action might also be Args(0), + # but we couldn't chose between then anyway so we'll take the last seen + + if (!$best_action || + @parts < @{$best_action->{parts}} || + (!@parts && $args_attr eq 0)){ + $best_action = { + actions => [ $action ], + captures=> [], + parts => \@parts + } + } } } } + return @$best_action{qw/actions captures parts/} if $best_action; return (); } @@ -184,7 +208,7 @@ sub register { return 0 unless @chained_attr; - if (@chained_attr > 2) { + if (@chained_attr > 1) { Catalyst::Exception->throw( "Multiple Chained attributes not supported registering ${action}" ); @@ -461,7 +485,7 @@ effect as using C<:PathPart>, it would default to the action name. Has to be specified for every child in the chain. Possible values are absolute and relative private action paths, with the relatives pointing to the current controller, or a single slash C to tell Catalyst that -this is the root of a chain. The attribute C<:Chained> without aguments +this is the root of a chain. The attribute C<:Chained> without arguments also defaults to the C behavior. Because you can specify an absolute path to the parent action, it @@ -531,9 +555,9 @@ 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. -=head1 AUTHOR +=head1 AUTHORS -Matt S Trout +Catalyst Contributors, see Catalyst.pm =head1 COPYRIGHT