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=2b27ec49eebb9d57e12b11a937482e41ae94977e;hp=95e0bcddca07ce93bc8079fdc7a6564ec01de1bd;hb=6a61d5b76357261fef77fc2151899491f2ec4695;hpb=8df53bed55eff8f87a6d62e6e07be033298796a7 diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index 95e0bcd..2b27ec4 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -96,14 +96,14 @@ 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 $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,12 +121,15 @@ sub list { my @rows; foreach my $p (@parents) { my $name = "/${p}"; - if (my $cap = $p->attributes->{CaptureArgs}) { - $name .= ' ('.$cap->[0].')'; + if (defined(my $cap = $p->list_extra_info->{CaptureArgs})) { + $name .= ' ('.$cap.')'; } unless ($p eq $parents[0]) { $name = "-> ${name}"; } + if (defined(my $extra = $p->list_extra_info->{HTTP_METHODS})) { + $name .= ' ('.join(', ', @$extra).')'; + } push(@rows, [ '', $name ]); } push(@rows, [ '', (@rows ? "=> " : '')."/${endpoint}" ]); @@ -187,7 +190,6 @@ sub recurse_match { return () unless $children; my $best_action; my @captures; - my $found=0; TRY: foreach my $try_part (sort { length($b) <=> length($a) } keys %$children) { # $b then $a to try longest part first @@ -198,11 +200,11 @@ sub recurse_match { splice( # and strip them off @parts as well @parts, 0, scalar(@{[split('/', $try_part)]}) ))); # @{[]} to avoid split to @_ - $found=1; } 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]; @@ -213,8 +215,11 @@ 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, $found) = $self->recurse_match( + my ($actions, $captures, $action_parts, $n_pathparts) = $self->recurse_match( $c, '/'.$action->reverse, \@parts ); # No best action currently @@ -222,16 +227,17 @@ sub recurse_match { # 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}} || ($#$action_parts == $#{$best_action->{parts}} && - $#$captures < $#{$best_action->{captures}} && ($found > $best_action->{found}) - ))) { + $#$captures < $#{$best_action->{captures}} && + $n_pathparts > $best_action->{n_pathparts}))) { + my @pathparts = split /\//, $action->attributes->{PathPart}->[0]; $best_action = { actions => [ $action, @$actions ], captures=> [ @captures, @$captures ], parts => $action_parts, - found=>$found - }; + n_pathparts => scalar(@pathparts) + $n_pathparts, + }; } } else { @@ -240,7 +246,7 @@ sub recurse_match { next TRY_ACTION unless $action->match($c); } my $args_attr = $action->attributes->{Args}->[0]; - + my @pathparts = split /\//, $action->attributes->{PathPart}->[0]; # No best action currently # OR This one matches with fewer parts left than the current best action, # And therefore is a better match @@ -250,18 +256,18 @@ 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=> [], parts => \@parts, - found=>$found, - } + n_pathparts => scalar(@pathparts), + }; } } } } - return @$best_action{qw/actions captures parts found/} if $best_action; + return @$best_action{qw/actions captures parts n_pathparts/} if $best_action; return (); } @@ -358,7 +364,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])); } @@ -405,6 +411,7 @@ sub expand_action { } __PACKAGE__->meta->make_immutable; +1; =head1 USAGE @@ -674,6 +681,13 @@ 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. +=head2 match_captures + +A method which can optionally be implemented by actions to +stop chain matching. + +See L for further details. + =head1 AUTHORS Catalyst Contributors, see Catalyst.pm