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=a7d08a35680bf9254dcdc13a31ce6a0b6e5be386;hp=257f7fb8a2e99aca9f1f3409f095564cfe6b2fa5;hb=213cf5bba2c5d308357e07a6041fc01a9519b6e2;hpb=be5cb4e4793133bae5f0ae5d269f4be3876b1e27 diff --git a/lib/Catalyst/DispatchType/Chained.pm b/lib/Catalyst/DispatchType/Chained.pm index 257f7fb..a7d08a3 100644 --- a/lib/Catalyst/DispatchType/Chained.pm +++ b/lib/Catalyst/DispatchType/Chained.pm @@ -3,8 +3,6 @@ package Catalyst::DispatchType::Chained; use Moose; extends 'Catalyst::DispatchType'; -#use strict; -#use base qw/Catalyst::DispatchType/; use Text::SimpleTable; use Catalyst::ActionChain; use URI; @@ -30,6 +28,8 @@ has _children_of => ( default => sub{ {} }, ); +no Moose; + # please don't perltidy this. hairy code within. =head1 NAME @@ -121,20 +121,21 @@ Calls C to see if a chain matches the C<$path>. sub match { my ( $self, $c, $path ) = @_; - return 0 if @{$c->req->args}; + my $request = $c->request; + return 0 if @{$request->args}; my @parts = split('/', $path); my ($chain, $captures, $parts) = $self->recurse_match($c, '/', \@parts); - push @{$c->req->args}, @$parts if $parts && @$parts; + push @{$request->args}, @$parts if $parts && @$parts; return 0 unless $chain; my $action = Catalyst::ActionChain->from_chain($chain); - $c->req->action("/${action}"); - $c->req->match("/${action}"); - $c->req->captures($captures); + $request->action("/${action}"); + $request->match("/${action}"); + $request->captures($captures); $c->action($action); $c->namespace( $action->namespace ); @@ -181,7 +182,14 @@ sub recurse_match { my ($actions, $captures, $action_parts) = $self->recurse_match( $c, '/'.$action->reverse, \@parts ); - if ($actions && (!$best_action || $#$action_parts < $#{$best_action->{parts}})){ + # 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 ], @@ -199,7 +207,7 @@ sub recurse_match { # 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 @@ -232,31 +240,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} || [] }; @@ -266,13 +256,13 @@ sub register { $part = $path_part[0]; } elsif (@path_part > 1) { Catalyst::Exception->throw( - "Multiple PathPart attributes not supported registering ${action}" + "Multiple PathPart attributes not supported registering " . $action->reverse() ); } if ($part =~ m(^/)) { Catalyst::Exception->throw( - "Absolute parameters to PathPart not allowed registering ${action}" + "Absolute parameters to PathPart not allowed registering " . $action->reverse() ); } @@ -326,9 +316,28 @@ sub uri_for_action { return undef if @captures; # fail for too many captures return join('/', '', @parts); + +} + +sub expand_action { + my ($self, $action) = @_; + + return unless $action->attributes && $action->attributes->{Chained}; + + my @chain; + my $curr = $action; + while ($curr) { + push @chain, $curr; + my $parent = $curr->attributes->{Chained}->[0]; + $curr = $self->_actions->{$parent}; + } + + return Catalyst::ActionChain->from_chain([reverse @chain]); } +__PACKAGE__->meta->make_immutable; + =head1 USAGE =head2 Introduction @@ -487,7 +496,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 @@ -504,13 +513,18 @@ 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 arguments -also defaults to the C behavior. +absolute and relative private action paths or a single slash C to +tell Catalyst that this is the root of a chain. The attribute +C<:Chained> without arguments also defaults to the C behavior. +Relative action paths may use C<../> to refer to actions in parent +controllers. Because you can specify an absolute path to the parent action, it doesn't matter to Catalyst where that parent is located. So, if your @@ -533,6 +547,19 @@ with the path of the current controller namespace, namely C. That action chains directly to C, so the C chain comes out as the end product. +=item ChainedParent + +Chains an action to another action with the same name in the parent +controller. For Example: + + # in MyApp::Controller::Foo + sub bar : Chained CaptureArgs(1) { ... } + + # in MyApp::Controller::Foo::Moo + sub bar : ChainedParent Args(1) { ... } + +This builds a chain like C. + =item CaptureArgs Must be specified for every part of the chain that is not an @@ -579,9 +606,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