Path done
[catagits/Catalyst-Runtime.git] / lib / Catalyst / DispatchType / Chained.pm
index d55d22d..0dc4c25 100644 (file)
@@ -1,7 +1,10 @@
 package Catalyst::DispatchType::Chained;
 
-use strict;
-use base qw/Catalyst::DispatchType/;
+use Moose;
+extends 'Catalyst::DispatchType';
+
+#use strict;
+#use base qw/Catalyst::DispatchType/;
 use Text::SimpleTable;
 use Catalyst::ActionChain;
 use URI;
@@ -85,7 +88,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 +104,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 +130,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 +157,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 ();
 }
 
@@ -278,7 +305,7 @@ sub uri_for_action {
     return undef if @captures; # fail for too many captures
 
     return join('/', '', @parts);
-   
+
 }
 
 =head1 USAGE
@@ -439,7 +466,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
@@ -461,7 +488,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