fix unicode in chain and path parts + debug console
[catagits/Catalyst-Runtime.git] / lib / Catalyst / Dispatcher.pm
index 779c213..12040b2 100644 (file)
@@ -14,6 +14,8 @@ use Catalyst::Utils;
 use Text::SimpleTable;
 use Tree::Simple;
 use Tree::Simple::Visitor::FindByPath;
+use Class::Load qw(load_class try_load_class);
+use Encode 2.21 'decode_utf8';
 
 use namespace::clean -except => 'meta';
 
@@ -22,14 +24,14 @@ use namespace::clean -except => 'meta';
 # See Catalyst-Plugin-Server for them being added to, which should be much less ugly.
 
 # Preload these action types
-our @PRELOAD = qw/Index Path Regex/;
+our @PRELOAD = qw/Index Path/;
 
 # Postload these action types
 our @POSTLOAD = qw/Default/;
 
 # Note - see back-compat methods at end of file.
 has _tree => (is => 'rw', builder => '_build__tree');
-has _dispatch_types => (is => 'rw', default => sub { [] }, required => 1, lazy => 1);
+has dispatch_types => (is => 'rw', default => sub { [] }, required => 1, lazy => 1);
 has _registered_dispatch_types => (is => 'rw', default => sub { {} }, required => 1, lazy => 1);
 has _method_action_class => (is => 'rw', default => 'Catalyst::Action');
 has _action_hash => (is => 'rw', required => 1, lazy => 1, default => sub { {} });
@@ -107,6 +109,9 @@ sub dispatch {
     }
     else {
         my $path  = $c->req->path;
+        $path =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+        $path = decode_utf8($path);
+
         my $error = $path
           ? qq/Unknown resource "$path"/
           : "No default action defined";
@@ -131,7 +136,7 @@ sub _command2action {
     my (@args, @captures);
 
     if ( ref( $extra_params[-2] ) eq 'ARRAY' ) {
-        @captures = @{ pop @extra_params };
+        @captures = @{ splice @extra_params, -2, 1 };
     }
 
     if ( ref( $extra_params[-1] ) eq 'ARRAY' ) {
@@ -153,7 +158,7 @@ sub _command2action {
         $action = $self->_invoke_as_path( $c, "$command", \@args );
     }
 
-    # go to a component ( "MyApp::*::Foo" or $c->component("...")
+    # go to a component ( "View::Foo" or $c->component("...")
     # - a path or an object)
     unless ($action) {
         my $method = @extra_params ? $extra_params[0] : "process";
@@ -335,7 +340,7 @@ sub _invoke_as_component {
                 reverse   => "$component_class->$method",
                 class     => $component_class,
                 namespace => Catalyst::Utils::class2prefix(
-                    $component_class, $c->config->{case_sensitive}
+                    $component_class, ref($c)->config->{case_sensitive}
                 ),
             }
         );
@@ -372,7 +377,7 @@ sub prepare_action {
         # Check out dispatch types to see if any will handle the path at
         # this level
 
-        foreach my $type ( @{ $self->_dispatch_types } ) {
+        foreach my $type ( @{ $self->dispatch_types } ) {
             last DESCEND if $type->match( $c, $path );
         }
 
@@ -384,10 +389,14 @@ sub prepare_action {
 
     s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg for grep { defined } @{$req->captures||[]};
 
-    $c->log->debug( 'Path is "' . $req->match . '"' )
-      if ( $c->debug && defined $req->match && length $req->match );
+    if($c->debug && defined $req->match && length $req->match) {
+      my $match = $req->match;
+      $match =~ s/%([0-9A-Fa-f]{2})/chr(hex($1))/eg;
+      $match = decode_utf8($match);
+      $c->log->debug( 'Path is "' . $match . '"' )
+    }
 
-    $c->log->debug( 'Arguments are "' . join( '/', @args ) . '"' )
+    $c->log->debug( 'Arguments are "' . join( '/', map { decode_utf8 $_ } @args ) . '"' )
       if ( $c->debug && @args );
 }
 
@@ -470,7 +479,7 @@ cannot determine an appropriate URI, this method will return undef.
 sub uri_for_action {
     my ( $self, $action, $captures) = @_;
     $captures ||= [];
-    foreach my $dispatch_type ( @{ $self->_dispatch_types } ) {
+    foreach my $dispatch_type ( @{ $self->dispatch_types } ) {
         my $uri = $dispatch_type->uri_for_action( $action, $captures );
         return( $uri eq '' ? '/' : $uri )
             if defined($uri);
@@ -489,7 +498,7 @@ single action.
 sub expand_action {
     my ($self, $action) = @_;
 
-    foreach my $dispatch_type (@{ $self->_dispatch_types }) {
+    foreach my $dispatch_type (@{ $self->dispatch_types }) {
         my $expanded = $dispatch_type->expand_action($action);
         return $expanded if $expanded;
     }
@@ -510,20 +519,22 @@ sub register {
 
     my $registered = $self->_registered_dispatch_types;
 
-    #my $priv = 0; #seems to be unused
     foreach my $key ( keys %{ $action->attributes } ) {
         next if $key eq 'Private';
         my $class = "Catalyst::DispatchType::$key";
         unless ( $registered->{$class} ) {
             # FIXME - Some error checking and re-throwing needed here, as
             #         we eat exceptions loading dispatch types.
-            eval { Class::MOP::load_class($class) };
-            push( @{ $self->_dispatch_types }, $class->new ) unless $@;
+            # see also try_load_class
+            eval { load_class($class) };
+            my $load_failed = $@;
+            $self->_check_deprecated_dispatch_type( $key, $load_failed );
+            push( @{ $self->dispatch_types }, $class->new ) unless $load_failed;
             $registered->{$class} = 1;
         }
     }
 
-    my @dtypes = @{ $self->_dispatch_types };
+    my @dtypes = @{ $self->dispatch_types };
     my @normal_dtypes;
     my @low_precedence_dtypes;
 
@@ -589,8 +600,8 @@ sub _find_or_create_namespace_node {
 
 =head2 $self->setup_actions( $class, $context )
 
-Loads all of the preload dispatch types, registers their actions and then
-loads all of the postload dispatch types, and iterates over the tree of
+Loads all of the pre-load dispatch types, registers their actions and then
+loads all of the post-load dispatch types, and iterates over the tree of
 actions, displaying the debug information if appropriate.
 
 =cut
@@ -647,7 +658,7 @@ sub _display_action_tables {
       if $has_private;
 
     # List all public actions
-    $_->list($c) for @{ $self->_dispatch_types };
+    $_->list($c) for @{ $self->dispatch_types };
 }
 
 sub _load_dispatch_types {
@@ -659,10 +670,9 @@ sub _load_dispatch_types {
         # first param is undef because we cannot get the appclass
         my $class = Catalyst::Utils::resolve_namespace(undef, 'Catalyst::DispatchType', $type);
 
-        eval { Class::MOP::load_class($class) };
-        Catalyst::Exception->throw( message => qq/Couldn't load "$class"/ )
-          if $@;
-        push @{ $self->_dispatch_types }, $class->new;
+        my ($success, $error) = try_load_class($class);
+        Catalyst::Exception->throw( message => $error ) if not $success;
+        push @{ $self->dispatch_types }, $class->new;
 
         push @loaded, $class;
     }
@@ -684,12 +694,34 @@ sub dispatch_type {
     # first param is undef because we cannot get the appclass
     $name = Catalyst::Utils::resolve_namespace(undef, 'Catalyst::DispatchType', $name);
 
-    for (@{ $self->_dispatch_types }) {
+    for (@{ $self->dispatch_types }) {
         return $_ if ref($_) eq $name;
     }
     return undef;
 }
 
+sub _check_deprecated_dispatch_type {
+    my ($self, $key, $load_failed) = @_;
+
+    return unless $key =~ /^(Local)?Regexp?/;
+
+    # TODO: Should these throw an exception rather than just warning?
+    if ($load_failed) {
+        warn(   "Attempt to use deprecated $key dispatch type.\n"
+              . "  Use Chained methods or install the standalone\n"
+              . "  Catalyst::DispatchType::Regex if necessary.\n" );
+    } elsif ( !defined $Catalyst::DispatchType::Regex::VERSION
+        || $Catalyst::DispatchType::Regex::VERSION le '5.90020' ) {
+        # We loaded the old core version of the Regex module this will break
+        warn(   "The $key DispatchType has been removed from Catalyst core.\n"
+              . "  An old version of the core Catalyst::DispatchType::Regex\n"
+              . "  has been loaded and will likely fail. Please remove\n"
+              . "   $INC{'Catalyst/DispatchType/Regex.pm'}\n"
+              . "  and use Chained methods or install the standalone\n"
+              . "  Catalyst::DispatchType::Regex if necessary.\n" );
+    }
+}
+
 use Moose;
 
 # 5.70 backwards compatibility hacks.
@@ -722,7 +754,6 @@ use Moose;
 # Alias _method_name to method_name, add a before modifier to warn..
 foreach my $public_method_name (qw/
         tree
-        dispatch_types
         registered_dispatch_types
         method_action_class
         action_hash
@@ -740,7 +771,7 @@ foreach my $public_method_name (qw/
             $package_hash{$class}++ || do {
                 warn("Class $class is calling the deprecated method\n"
                     . "  Catalyst::Dispatcher::$public_method_name,\n"
-                    . "  this will be removed in Catalyst 5.9X\n");
+                    . "  this will be removed in Catalyst 5.9\n");
             };
         });
     }