make sure we can properly do utf8 constraints
[catagits/Catalyst-Runtime.git] / lib / Catalyst.pm
index 03b49c6..20595e0 100644 (file)
@@ -129,7 +129,7 @@ __PACKAGE__->stats_class('Catalyst::Stats');
 __PACKAGE__->_encode_check(Encode::FB_CROAK | Encode::LEAVE_SRC);
 
 # Remember to update this in Catalyst::Runtime as well!
-our $VERSION = '5.90085';
+our $VERSION = '5.90089_001';
 $VERSION = eval $VERSION if $VERSION =~ /_/; # numify for warning-free dev releases
 
 sub import {
@@ -1447,6 +1447,10 @@ In general the scheme of the generated URI object will follow the incoming reque
 however if your targeted action or action chain has the Scheme attribute it will
 use that instead.
 
+Also, if the targeted Action or Action chain declares Args/CaptureArgs that have
+type constraints, we will require that your proposed URL verify on those declared
+constraints.
+
 =cut
 
 sub uri_for {
@@ -1469,15 +1473,17 @@ sub uri_for {
     foreach my $arg (@args) {
       if(ref($arg)||'' eq 'ARRAY') {
         push @encoded_args, [map {
-          my $encoded = encode_utf8 $_;
-          $encoded =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
-         $encoded;
+          #   my $encoded = encode_utf8 $_;
+          # $encoded =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+          # $encoded;
+          $_
         } @$arg];
       } else {
         push @encoded_args, do {
-          my $encoded = encode_utf8 $arg;
-          $encoded =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
-          $encoded;
+          #   my $encoded = encode_utf8 $arg;
+          # $encoded =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+          # $encoded;
+          $arg;
         }
       }
     }
@@ -1491,20 +1497,36 @@ sub uri_for {
                          : ()) ];
 
         my $action = $path;
+        my $expanded_action = $c->dispatcher->expand_action( $action );
+        my $num_captures = $expanded_action->number_of_captures;
+
         # ->uri_for( $action, \@captures_and_args, \%query_values? )
         if( !@encoded_args && $action->number_of_args ) {
-            my $expanded_action = $c->dispatcher->expand_action( $action );
-            my $num_captures = $expanded_action->number_of_captures;
-            unshift @encoded_args, splice @$captures, $num_captures;
+          unshift @encoded_args, splice @$captures, $num_captures;
+        }
+
+        if($num_captures) {
+          unless($expanded_action->match_captures($c, $captures)) {
+            carp "captures [@{$captures}] do not match the type constraints in actionchain ending with '$action'";
+            return;
+          }
         }
 
-       $path = $c->dispatcher->uri_for_action($action, $captures);
+        $path = $c->dispatcher->uri_for_action($action, $captures);
         if (not defined $path) {
             $c->log->debug(qq/Can't find uri_for action '$action' @$captures/)
                 if $c->debug;
             return undef;
         }
         $path = '/' if $path eq '';
+
+        # At this point @encoded_args is the remaining Args (all captures removed).
+        if($expanded_action->has_args_constraints) {
+          unless($expanded_action->match_args($c,\@encoded_args)) {
+             carp "args [@encoded_args] do not match the type constraints in action '$expanded_action'";
+             return;
+          }
+        }
     }
 
     unshift(@encoded_args, $path);
@@ -1567,6 +1589,11 @@ sub uri_for {
       } @keys);
     }
 
+    $base = encode_utf8 $base;
+    $base =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+    $args = encode_utf8 $args;
+    $args =~ s/([^$URI::uric])/$URI::Escape::escapes{$1}/go;
+    
     my $res = bless(\"${base}${args}${query}", $class);
     $res;
 }