X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FDispatchType%2FChained.pm;h=632fd201e285f21e5cd61302023c9e04d896df64;hb=8f0e79ad6a2e2f64a9bda579bd5f9e1aa55a841c;hp=d55d22db8048e4568303238c04b83efc65416a26;hpb=f505df49a4707ce6962d8a9ebcf5280430a801cf;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index d55d22d..632fd20 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -85,7 +85,7 @@ sub list { $paths->row(@$_) for @rows; } - $c->log->debug( "Loaded Path Part actions:\n" . $paths->draw ); + $c->log->debug( "Loaded Chained actions:\n" . $paths->draw . "\n" ); } =head2 $self->match( $c, $path ) @@ -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,51 @@ 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 ]; + # No best action currently + # OR The action has less parts + # OR The action has equal parts but less captured data (ergo more defined) + if ($actions && + (!$best_action || + $#$action_parts < $#{$best_action->{parts}} || + ($#$action_parts == $#{$best_action->{parts}} && + $#$captures < $#{$best_action->{captures}}))){ + $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,31 +215,13 @@ 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}" ); } - my $parent = $chained_attr[0]; - - if (defined($parent) && length($parent)) { - if ($parent eq '.') { - $parent = '/'.$action->namespace; - } elsif ($parent !~ m/^\//) { - if ($action->namespace) { - $parent = '/'.join('/', $action->namespace, $parent); - } else { - $parent = '/'.$parent; # special case namespace '' (root) - } - } - } else { - $parent = '/' - } - - $action->attributes->{Chained} = [ $parent ]; - - my $children = ($self->{children_of}{$parent} ||= {}); + my $children = ($self->{children_of}{ $chained_attr[0] } ||= {}); my @path_part = @{ $action->attributes->{PathPart} || [] }; @@ -456,12 +469,16 @@ with C would bind to C. If you don't specify C<:PathPart> it has the same effect as using C<:PathPart>, it would default to the action name. +=item PathPrefix + +Sets PathPart to the path_prefix of the current controller. + =item Chained 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 +548,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