[Catalyst-commits] r12012 - in Catalyst-Runtime/5.80/branches/contextual_uri_for: lib lib/Catalyst lib/Catalyst/DispatchType t/aggregate

pjfl at dev.catalyst.perl.org pjfl at dev.catalyst.perl.org
Wed Nov 25 18:25:48 GMT 2009


Author: pjfl
Date: 2009-11-25 18:25:48 +0000 (Wed, 25 Nov 2009)
New Revision: 12012

Modified:
   Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst.pm
   Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType.pm
   Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Chained.pm
   Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Regex.pm
   Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/Dispatcher.pm
   Catalyst-Runtime/5.80/branches/contextual_uri_for/t/aggregate/unit_core_uri_for_action.t
Log:
Flatten captures ready for another round of review

Modified: Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Chained.pm
===================================================================
--- Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Chained.pm	2009-11-25 17:54:35 UTC (rev 12011)
+++ Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Chained.pm	2009-11-25 18:25:48 UTC (rev 12012)
@@ -399,6 +399,49 @@
     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 $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

Modified: Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Regex.pm
===================================================================
--- Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Regex.pm	2009-11-25 17:54:35 UTC (rev 12011)
+++ Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType/Regex.pm	2009-11-25 18:25:48 UTC (rev 12012)
@@ -168,6 +168,39 @@
     return undef;
 }
 
+=head2 $self->splice_captures_from( $c, $action, $args )
+
+Iterates over the regular expressions defined for the action. Stops when
+the number of captures equals the number of supplied args. Replaces the
+list of args with a list containing an array ref of args
+
+=cut
+
+sub splice_captures_from {
+    my ($self, $c, $action, $args) = @_; my $regexes;
+
+    return 0 unless ($regexes = $action->attributes->{Regex});
+
+    foreach my $orig (@{ $regexes }) {
+        my $re = "$orig"; $re =~ s/^\^//; $re =~ s/\$$//;
+        my $num_caps = 0;
+
+        while (my ($front, $rest) = split /\(/, $re, 2) {
+            last unless (defined $rest);
+
+            ($rest, $re) = Text::Balanced::extract_bracketed( "(${rest}", '(');
+            $num_caps++;
+        }
+
+        next unless ($num_caps == scalar @{ $args });
+
+        @{ $args } = ( [ @{ $args } ] );
+        return 1;
+    }
+
+    return 1;
+}
+
 =head1 AUTHORS
 
 Catalyst Contributors, see Catalyst.pm

Modified: Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType.pm
===================================================================
--- Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType.pm	2009-11-25 17:54:35 UTC (rev 12011)
+++ Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/DispatchType.pm	2009-11-25 18:25:48 UTC (rev 12012)
@@ -73,6 +73,15 @@
 
 sub expand_action { }
 
+=head2 $self->splice_captures_from
+
+Default fallback, returns nothing. See L<Catalyst::Dispatcher> for more info
+about splice_captures_from.
+
+=cut
+
+sub splice_captures_from { 0 }
+
 sub _is_low_precedence { 0 }
 
 =head1 AUTHORS

Modified: Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/Dispatcher.pm
===================================================================
--- Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/Dispatcher.pm	2009-11-25 17:54:35 UTC (rev 12011)
+++ Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst/Dispatcher.pm	2009-11-25 18:25:48 UTC (rev 12012)
@@ -497,6 +497,31 @@
     return $action;
 }
 
+=head2 $self->splice_captures_from( $c, $action, $args )
+
+Does nothing if the first element of the list that C<$args> references
+is an array ref. Otherwise calls this method in each dispatch type,
+stopping when the first one returns true
+
+=cut
+
+sub splice_captures_from {
+    my ($self, $c, $action, $args) = @_;
+
+    return if (!$args || (scalar @{ $args } && ref $args->[0] eq 'ARRAY'));
+
+    my $params = scalar @{ $args } && ref $args->[-1] eq 'HASH'
+               ? pop @{ $args } : undef;
+
+    foreach my $dispatch_type ( @{ $self->dispatch_types } ) {
+        last if ($dispatch_type->splice_captures_from( $c, $action, $args ));
+    }
+
+    push @{ $args }, $params if ($params); # Restore query parameters
+
+    return;
+}
+
 =head2 $self->register( $c, $action )
 
 Make sure all required dispatch types for this action are loaded, then

Modified: Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst.pm
===================================================================
--- Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst.pm	2009-11-25 17:54:35 UTC (rev 12011)
+++ Catalyst-Runtime/5.80/branches/contextual_uri_for/lib/Catalyst.pm	2009-11-25 18:25:48 UTC (rev 12012)
@@ -1258,6 +1258,7 @@
     }
 
     if ( blessed($path) ) { # action object
+        $c->dispatcher->splice_captures_from( $c, $path, \@args );
         my $captures = [ map { s|/|%2F|; $_; }
                         ( scalar @args && ref $args[0] eq 'ARRAY'
                          ? @{ shift(@args) }

Modified: Catalyst-Runtime/5.80/branches/contextual_uri_for/t/aggregate/unit_core_uri_for_action.t
===================================================================
--- Catalyst-Runtime/5.80/branches/contextual_uri_for/t/aggregate/unit_core_uri_for_action.t	2009-11-25 17:54:35 UTC (rev 12011)
+++ Catalyst-Runtime/5.80/branches/contextual_uri_for/t/aggregate/unit_core_uri_for_action.t	2009-11-25 18:25:48 UTC (rev 12012)
@@ -8,7 +8,7 @@
 
 use Test::More;
 
-plan tests => 30;
+plan tests => 43;
 
 use_ok('TestApp');
 
@@ -116,10 +116,18 @@
    "http://127.0.0.1/foo/action/regexp/foo/123/bar/baz?q=1",
    "uri_for correct for regex with captures, args and query");
 
+is($context->uri_for($regex_action, 'foo', 123, { q => 1 }),
+   "http://127.0.0.1/foo/action/regexp/foo/123?q=1",
+   "uri_for correct for regex no captures with args and query");
+
 is($context->uri_for($chained_action, [ 1 ], 2, { q => 1 }),
    "http://127.0.0.1/foo/chained/foo/1/end/2?q=1",
    "uri_for correct for chained with captures, args and query");
 
+is($context->uri_for($chained_action, 1, 2, { q => 1 }),
+   "http://127.0.0.1/foo/chained/foo/1/end/2?q=1",
+   "uri_for correct for chained no captures with args and query");
+
 #
 #   More Chained with Context Tests
 #
@@ -128,19 +136,37 @@
         'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4?x=5',
         'uri_for_action correct for chained with multiple captures and args' );
 
+    is( $context->uri_for_action( '/action/chained/endpoint2', qw(1 2 3 4), { x => 5 } ),
+        'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4?x=5',
+        'uri_for_action correct for chained without captures with multiple args' );
+
     is( $context->uri_for_action( '/action/chained/three_end', [1,2,3], (4,5,6) ),
         'http://127.0.0.1/foo/chained/one/1/two/2/3/three/4/5/6',
         'uri_for_action correct for chained with multiple capturing actions' );
 
+    is( $context->uri_for_action( '/action/chained/three_end', qw(1 2 3 4 5 6) ),
+        'http://127.0.0.1/foo/chained/one/1/two/2/3/three/4/5/6',
+        'uri_for_action correct for chained no captures multi capturing actions' );
+
+    ok( ! defined( $context->uri_for_action( '/action/chained/foo2' ) ),
+        'uri_for_action returns undef for chained action midpoints' );
+
     my $action_needs_two = '/action/chained/endpoint2';
     
     ok( ! defined( $context->uri_for_action($action_needs_two, [1],     (2,3)) ),
         'uri_for_action returns undef for not enough captures' );
         
+    ok( ! defined( $context->uri_for_action($action_needs_two, 1) ),
+        'uri_for_action returns undef for not enough captures/args total' );
+
     is( $context->uri_for_action($action_needs_two,            [1,2],   (2,3)),
         'http://127.0.0.1/foo/chained/foo2/1/2/end2/2/3',
         'uri_for_action returns correct uri for correct captures' );
         
+    is( $context->uri_for_action($action_needs_two,            qw(1 2 2 3)),
+        'http://127.0.0.1/foo/chained/foo2/1/2/end2/2/3',
+        'uri_for_action returns correct uri for correct captures/args total' );
+
     ok( ! defined( $context->uri_for_action($action_needs_two, [1,2,3], (2,3)) ),
         'uri_for_action returns undef for too many captures' );
     
@@ -148,27 +174,51 @@
         'http://127.0.0.1/foo/chained/foo2/1/2/end2/3',
         'uri_for_action returns uri with lesser args than specified on action' );
 
+    is( $context->uri_for_action($action_needs_two, qw(1 2 3)),
+        'http://127.0.0.1/foo/chained/foo2/1/2/end2/3',
+        'uri_for_action returns uri with lesser args and no captures' );
+
     is( $context->uri_for_action($action_needs_two, [1,2],   (3,4,5)),
         'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4/5',
         'uri_for_action returns uri with more args than specified on action' );
 
+    is( $context->uri_for_action($action_needs_two, qw(1 2 3 4 5)),
+        'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/4/5',
+        'uri_for_action returns uri with more args and no captures' );
+
     is( $context->uri_for_action($action_needs_two, [1,''], (3,4)),
         'http://127.0.0.1/foo/chained/foo2/1//end2/3/4',
         'uri_for_action returns uri with empty capture on undef capture' );
 
+    is( $context->uri_for_action($action_needs_two, 1, '', 3, 4),
+        'http://127.0.0.1/foo/chained/foo2/1//end2/3/4',
+        'uri_for_action returns uri with no captures and empty arg' );
+
     is( $context->uri_for_action($action_needs_two, [1,2], ('',3)),
         'http://127.0.0.1/foo/chained/foo2/1/2/end2//3',
         'uri_for_action returns uri with empty arg on undef argument' );
 
+    is( $context->uri_for_action($action_needs_two, 1, 2, '', 3),
+        'http://127.0.0.1/foo/chained/foo2/1/2/end2//3',
+        'uri_for_action returns uri no captures with empty arg on undef argument' );
+
     is( $context->uri_for_action($action_needs_two, [1,2], (3,'')),
         'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/',
         'uri_for_action returns uri with empty arg on undef last argument' );
 
+    is( $context->uri_for_action($action_needs_two, 1, 2, 3, ''),
+        'http://127.0.0.1/foo/chained/foo2/1/2/end2/3/',
+        'uri_for_action returns uri no captures empty arg undef last argument' );
+
     my $complex_chained = '/action/chained/empty_chain_f';
     is( $context->uri_for_action( $complex_chained, [23], (13), {q => 3} ),
         'http://127.0.0.1/foo/chained/empty/23/13?q=3',
         'uri_for_action returns correct uri for chain with many empty path parts' );
 
+    is( $context->uri_for_action( $complex_chained, 23, 13, {q => 3} ),
+        'http://127.0.0.1/foo/chained/empty/23/13?q=3',
+        'uri_for_action returns correct uri for chain no captures empty path parts' );
+
     eval { $context->uri_for_action( '/does/not/exist' ) };
     like $@, qr{^Can't find action for path '/does/not/exist'},
         'uri_for_action croaks on nonexistent path';




More information about the Catalyst-commits mailing list