stop using Moo as a test package
[catagits/Catalyst-Runtime.git] / lib / Catalyst / DispatchType / Chained.pm
index 2029a6e..138727c 100644 (file)
@@ -98,7 +98,14 @@ sub list {
                            @{ $self->_endpoints }
                   ) {
         my $args = $endpoint->list_extra_info->{Args};
-        my @parts = (defined($args) ? (("*") x $args) : '...');
+
+        my @parts;
+        if($endpoint->has_args_constraints) {
+            @parts = map { "{$_}" } $endpoint->all_args_constraints;
+        } elsif(defined $endpoint->attributes->{Args}) {
+            @parts = (defined($endpoint->attributes->{Args}[0]) ? (("*") x $args) : '...');
+        }
+
         my @parents = ();
         my $parent = "DUMMY";
         my $extra  = $self->_list_extra_http_methods($endpoint);
@@ -107,7 +114,12 @@ sub list {
         my $curr = $endpoint;
         while ($curr) {
             if (my $cap = $curr->list_extra_info->{CaptureArgs}) {
-                unshift(@parts, (("*") x $cap));
+                if($curr->has_captures_constraints) {
+                    my $names = join '/', map { "{$_}" } $curr->all_captures_constraints;
+                    unshift(@parts, $names);
+                } else {
+                    unshift(@parts, (("*") x $cap));
+                }
             }
             if (my $pp = $curr->attributes->{PathPart}) {
                 unshift(@parts, $pp->[0])
@@ -130,7 +142,12 @@ sub list {
                 $name = "${extra} ${name}";
             }
             if (defined(my $cap = $p->list_extra_info->{CaptureArgs})) {
-                $name .= ' ('.$cap.')';
+                if($p->has_captures_constraints) {
+                  my $tc = join ',', @{$p->captures_constraints};
+                  $name .= " ($tc)";
+                } else {
+                  $name .= " ($cap)";
+                }
             }
             if (defined(my $ct = $p->list_extra_info->{Consumes})) {
                 $name .= ' :'.$ct;
@@ -144,7 +161,15 @@ sub list {
             }
             push(@rows, [ '', $name ]);
         }
-        push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : ''). ($scheme ? "$scheme: ":'')."/${endpoint}". ($consumes ? " :$consumes":"" ) ]);
+
+        my $endpoint_arg_info = $endpoint;
+        if($endpoint->has_args_constraints) {
+          my $tc = join ',', @{$endpoint->args_constraints};
+          $endpoint_arg_info .= " ($tc)";
+        } else {
+          $endpoint_arg_info .= defined($endpoint->attributes->{Args}[0]) ? " ($args)" : " (...)";
+        }
+        push(@rows, [ '', (@rows ? "=> " : '').($extra ? "$extra " : ''). ($scheme ? "$scheme: ":'')."/${endpoint_arg_info}". ($consumes ? " :$consumes":"" ) ]);
         my @display_parts = map { $_ =~s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg; decode_utf8 $_ } @parts;
         $rows[0][0] = join('/', '', @display_parts) || '/';
         $paths->row(@$_) for @rows;
@@ -235,6 +260,8 @@ sub recurse_match {
         }
         my @try_actions = @{$children->{$try_part}};
         TRY_ACTION: foreach my $action (@try_actions) {
+
+
             if (my $capture_attr = $action->attributes->{CaptureArgs}) {
                 my $capture_count = $action->number_of_captures|| 0;
 
@@ -278,6 +305,7 @@ sub recurse_match {
                     next TRY_ACTION unless $action->match($c);
                 }
                 my $args_attr = $action->attributes->{Args}->[0];
+                my $args_count = $action->comparable_arg_number;
                 my @pathparts = split /\//, $action->attributes->{PathPart}->[0];
                 #    No best action currently
                 # OR This one matches with fewer parts left than the current best action,
@@ -285,14 +313,29 @@ sub recurse_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                       ||
+                if (
+                    !$best_action                       ||
                     @parts < @{$best_action->{parts}}   ||
-                    (!@parts && defined($args_attr) && $args_attr eq "0")){
+                    (
+                        !@parts && 
+                        defined($args_attr) && 
+                        (
+                            $args_count eq "0" &&
+                            (
+                              ($c->config->{use_chained_args_0_special_case}||0) || 
+                                (
+                                  exists($best_action->{args_count}) && defined($best_action->{args_count}) ?
+                                  ($best_action->{args_count} ne 0) : 1
+                                )
+                            )
+                        )
+                    )
+                ){
                     $best_action = {
                         actions => [ $action ],
                         captures=> [],
                         parts   => \@parts,
+                        args_count => $args_count,
                         n_pathparts => scalar(@pathparts),
                     };
                 }
@@ -387,11 +430,15 @@ sub uri_for_action {
     my @captures = @$captures;
     my $parent = "DUMMY";
     my $curr = $action;
+    # If this is an action chain get the last action in the chain
+    if($curr->can('chain') ) {
+      $curr = ${$curr->chain}[-1];
+    }
     while ($curr) {
-        if (my $cap = $curr->attributes->{CaptureArgs}) {
-            return undef unless @captures >= ($cap->[0]||0); # not enough captures
-            if ($cap->[0]) {
-                unshift(@parts, splice(@captures, -$cap->[0]));
+        if (my $cap = $curr->number_of_captures) {
+            return undef unless @captures >= $cap; # not enough captures
+            if ($cap) {
+                unshift(@parts, splice(@captures, -$cap));
             }
         }
         if (my $pp = $curr->attributes->{PathPart}) {
@@ -655,7 +702,7 @@ controller. For Example:
   # in MyApp::Controller::Foo
   sub bar : Chained CaptureArgs(1) { ... }
 
-  # in MyApp::Controller::Foo::Moo
+  # in MyApp::Controller::Foo::Bar
   sub bar : ChainedParent Args(1) { ... }
 
 This builds a chain like C</bar/*/bar/*>.
@@ -668,7 +715,7 @@ parts of the path (separated by C</>) this action wants to capture as
 its arguments. If it doesn't expect any, just specify
 C<:CaptureArgs(0)>.  The captures get passed to the action's C<@_> right
 after the context, but you can also find them as array references in
-C<$c-E<gt>request-E<gt>captures-E<gt>[$level]>. The C<$level> is the
+C<< $c->request->captures->[$level] >>. The C<$level> is the
 level of the action in the chain that captured the parts of the path.
 
 An action that is part of a chain (that is, one that has a C<:Chained>
@@ -695,6 +742,10 @@ custom type constraints and import them into the controller namespace:
 
       sub int_priority_chain :Chained(chain_base) PathPart('') Args(Int) { }
 
+If you use a reference type constraint in CaptureArgs, it must be a type
+like Tuple in L<Types::Standard> that allows us to determine the number of
+args to match.  Otherwise this will raise an error during startup.
+
 See L<Catalyst::RouteMatching> for more.
 
 =item Args
@@ -713,7 +764,10 @@ of path parts after the endpoint.
 
 Just as with C<:CaptureArgs>, the arguments get passed to the action in
 C<@_> after the context object. They can also be reached through
-C<$c-E<gt>request-E<gt>arguments>.
+C<< $c->request->arguments >>.
+
+You should see 'Args' in L<Catalyst::Controller> for more details on using
+type constraints in your Args declarations.
 
 =back