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=5f72fba9ae1c13d63cfbb9f0bf598a171d234027;hp=a29cb7419ae89f33f2c9d0804668d3696d955bca;hb=3c0da3ece98e535f1c168bb985980583498894ad;hpb=dd97c1ac48f275a692de1d2ce980e9d3155d78b9 diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index a29cb74..5f72fba 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -80,14 +80,16 @@ sub list { return unless $self->_endpoints; - my $column_width = Catalyst::Utils::term_width() - 35 - 9; + my $avail_width = Catalyst::Utils::term_width() - 9; + my $col1_width = ($avail_width * .50) < 35 ? 35 : int($avail_width * .50); + my $col2_width = $avail_width - $col1_width; my $paths = Text::SimpleTable->new( - [ 35, 'Path Spec' ], [ $column_width, 'Private' ], + [ $col1_width, 'Path Spec' ], [ $col2_width, 'Private' ], ); my $has_unattached_actions; my $unattached_actions = Text::SimpleTable->new( - [ 35, 'Private' ], [ $column_width, 'Missing parent' ], + [ $col1_width, 'Private' ], [ $col2_width, 'Missing parent' ], ); ENDPOINT: foreach my $endpoint ( @@ -103,7 +105,7 @@ sub list { if (my $cap = $curr->attributes->{CaptureArgs}) { unshift(@parts, (("*") x $cap->[0])); } - if (my $pp = $curr->attributes->{PartPath}) { + if (my $pp = $curr->attributes->{PathPart}) { unshift(@parts, $pp->[0]) if (defined $pp->[0] && length $pp->[0]); } @@ -199,6 +201,7 @@ 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]; @@ -209,8 +212,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) = $self->recurse_match( + my ($actions, $captures, $action_parts, $n_pathparts) = $self->recurse_match( $c, '/'.$action->reverse, \@parts ); # No best action currently @@ -220,12 +226,15 @@ sub recurse_match { (!$best_action || $#$action_parts < $#{$best_action->{parts}} || ($#$action_parts == $#{$best_action->{parts}} && - $#$captures < $#{$best_action->{captures}}))){ + $#$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 - }; + parts => $action_parts, + n_pathparts => scalar(@pathparts) + $n_pathparts, + }; } } else { @@ -234,27 +243,28 @@ 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 - # OR No parts and this expects 0 + # 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)){ + (!@parts && defined($args_attr) && $args_attr eq "0")){ $best_action = { actions => [ $action ], captures=> [], - parts => \@parts - } + parts => \@parts, + n_pathparts => scalar(@pathparts), + }; } } } } - return @$best_action{qw/actions captures parts/} if $best_action; + return @$best_action{qw/actions captures parts n_pathparts/} if $best_action; return (); } @@ -302,7 +312,7 @@ sub register { ); } - $action->attributes->{PartPath} = [ $part ]; + $action->attributes->{PathPart} = [ $part ]; unshift(@{ $children->{$part} ||= [] }, $action); @@ -351,14 +361,12 @@ 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, - map { s/([^A-Za-z0-9\-_.!~*'()])/$URI::Escape::escapes{$1}/go; $_; } - splice(@captures, -$cap->[0])); + unshift(@parts, splice(@captures, -$cap->[0])); } } - if (my $pp = $curr->attributes->{PartPath}) { + if (my $pp = $curr->attributes->{PathPart}) { unshift(@parts, $pp->[0]) if (defined($pp->[0]) && length($pp->[0])); } @@ -376,7 +384,7 @@ sub uri_for_action { =head2 $c->expand_action($action) -Return a list of actions that represents a chained action. See +Return a list of actions that represents a chained action. See L for more info. You probably want to use the expand_action it provides rather than this directly. @@ -400,6 +408,7 @@ sub expand_action { } __PACKAGE__->meta->make_immutable; +1; =head1 USAGE @@ -559,7 +568,7 @@ this debugging output: '-----------------------+------------------------------' ... -Here's a more detailed specification of the attributes belonging to +Here's a more detailed specification of the attributes belonging to C<:Chained>: =head2 Attributes @@ -669,13 +678,20 @@ 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 =head1 COPYRIGHT -This program is free software, you can redistribute it and/or modify it under +This library is free software. You can redistribute it and/or modify it under the same terms as Perl itself. =cut