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';
# 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 { {} });
}
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";
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' ) {
$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";
reverse => "$component_class->$method",
class => $component_class,
namespace => Catalyst::Utils::class2prefix(
- $component_class, $c->config->{case_sensitive}
+ $component_class, ref($c)->config->{case_sensitive}
),
}
);
# 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 );
}
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 );
}
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);
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;
}
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;
=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
my $col1_width = ($avail_width * .25) < 20 ? 20 : int($avail_width * .25);
my $col2_width = ($avail_width * .50) < 36 ? 36 : int($avail_width * .50);
my $col3_width = $avail_width - $col1_width - $col2_width;
- $c->log->debug("col1: $col1_width");
- $c->log->debug("col2: $col2_width");
- $c->log->debug("col3: $col3_width");
my $privates = Text::SimpleTable->new(
[ $col1_width, 'Private' ], [ $col2_width, 'Class' ], [ $col3_width, 'Method' ]
);
if $has_private;
# List all public actions
- $_->list($c) for @{ $self->_dispatch_types };
+ $_->list($c) for @{ $self->dispatch_types };
}
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;
}
# 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.
# 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
$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");
};
});
}