Fixed uninitialized value warning in contextual_uri_for branch Chained
[catagits/Catalyst-Runtime.git] / lib / Catalyst / DispatchType / Chained.pm
index 585bf3f..d34545c 100644 (file)
@@ -7,6 +7,7 @@ use Text::SimpleTable;
 use Catalyst::ActionChain;
 use Catalyst::Utils;
 use URI;
+use Scalar::Util ();
 
 has _endpoints => (
                    is => 'rw',
@@ -79,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 (
@@ -127,7 +130,7 @@ sub list {
             push(@rows, [ '', $name ]);
         }
         push(@rows, [ '', (@rows ? "=> " : '')."/${endpoint}" ]);
-        $rows[0][0] = join('/', '', @parts);
+        $rows[0][0] = join('/', '', @parts) || '/';
         $paths->row(@$_) for @rows;
     }
 
@@ -151,7 +154,13 @@ sub match {
     my @parts = split('/', $path);
 
     my ($chain, $captures, $parts) = $self->recurse_match($c, '/', \@parts);
-    push @{$request->args}, @$parts if $parts && @$parts;
+
+    if ($parts && @$parts) {
+        for my $arg (@$parts) {
+            $arg =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+            push @{$request->args}, $arg;
+        }
+    }
 
     return 0 unless $chain;
 
@@ -231,7 +240,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
 
@@ -301,6 +310,23 @@ sub register {
 
     $self->_actions->{'/'.$action->reverse} = $action;
 
+    if (exists $action->attributes->{Args}) {
+        my $args = $action->attributes->{Args}->[0];
+        if (defined($args) and not (
+            Scalar::Util::looks_like_number($args) and
+            int($args) == $args
+        )) {
+            require Data::Dumper;
+            local $Data::Dumper::Terse = 1;
+            local $Data::Dumper::Indent = 0;
+            $args = Data::Dumper::Dumper($args);
+            Catalyst::Exception->throw(
+              "Invalid Args($args) for action " . $action->reverse() .
+              " (use 'Args' or 'Args(<number>)'"
+            );
+        }
+    }
+
     unless ($action->attributes->{CaptureArgs}) {
         unshift(@{ $self->_endpoints }, $action);
     }
@@ -350,7 +376,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<Catalyst::Dispatcher> for more info. You probably want to
 use the expand_action it provides rather than this directly.
 
@@ -373,6 +399,50 @@ sub expand_action {
     return Catalyst::ActionChain->from_chain([reverse @chain]);
 }
 
+=head2 $self->splice_captures_from( $c, $action, $args )
+
+Calculates the number of capture args for the given action,
+splices off the front of the supplied args, and pushes them back
+on the args list wrapped in an array ref
+
+=cut
+
+sub splice_captures_from {
+    my ($self, $c, $action, $args) = @_; my $attrs = $action->attributes;
+
+    return 0 unless ($attrs->{Chained});
+
+    if ($attrs->{CaptureArgs}) {
+        $c->log->debug( 'Action '.$action->reverse.' is a midpoint' )
+            if ($c->debug);
+        return 1;
+    }
+
+    my @captures = ();
+    my @chain    = @{ $self->expand_action( $action )->chain }; pop @chain;
+
+    # Now start from the root of the chain, populate captures
+    for my $num_caps (map { $_->attributes->{CaptureArgs}->[0] } @chain) {
+        if ($num_caps > scalar @{ $args }) {
+            $c->log->debug( 'Action '.$action->reverse.' insufficient args' )
+                if ($c->debug);
+            return 1;
+        }
+
+        push @captures, splice @{ $args }, 0, $num_caps;
+    }
+
+    if (    defined $attrs->{Args}->[0]
+        and defined $args->[ $attrs->{Args}->[0] ]) {
+        $c->log->debug( 'Action '.$action->reverse.' too many args' )
+            if ($c->debug);
+    }
+
+    unshift @{ $args }, \@captures if (defined $captures[0]);
+
+    return 1;
+}
+
 __PACKAGE__->meta->make_immutable;
 
 =head1 USAGE
@@ -533,7 +603,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
@@ -649,7 +719,7 @@ 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