use Catalyst::Utils;
use Catalyst::Action;
use Catalyst::ActionContainer;
-use Catalyst::DispatchType::Path;
-use Catalyst::DispatchType::Regex;
use Catalyst::DispatchType::Default;
+use Catalyst::DispatchType::Index;
use Text::ASCIITable;
use Tree::Simple;
use Tree::Simple::Visitor::FindByPath;
# Stringify to class
use overload '""' => sub { return ref shift }, fallback => 1;
-__PACKAGE__->mk_accessors(qw/actions tree dispatch_types/);
+__PACKAGE__->mk_accessors(qw/tree dispatch_types/);
+
+# Preload these action types
+our @PRELOAD = qw/Path Regex/;
+
+# Postload these action types
+our @POSTLOAD = qw/Index Default/;
=head1 NAME
sub get_action {
my ( $self, $c, $action, $namespace, $inherit ) = @_;
return [] unless $action;
- $namespace ||= '/';
+ $namespace ||= '';
$inherit ||= 0;
my @match = $self->get_containers($namespace);
foreach my $child ( $inherit ? @match : $match[-1] ) {
my $node = $child->actions;
- push( @results, [ $node->{$action} ] ) if defined $node->{$action};
+ if ( defined $node->{$action} ) {
+ unless ($inherit) {
+ $namespace = '' if $namespace eq '/';
+ my $reverse = $node->{$action}->reverse;
+ my $name = $namespace
+ ? $namespace =~ /\/$/
+ ? "$namespace$action"
+ : "$namespace/$action"
+ : $action;
+ last unless $name eq $reverse;
+ }
+ push( @results, [ $node->{$action} ] );
+ }
}
return \@results;
}
# Parse out :Foo(bar) into Foo => bar etc (and arrayify)
+ my %initialized;
+ $initialized{ ref $_ }++ for @{ $self->dispatch_types };
+
if ( my ( $key, $value ) = ( $attr =~ /^(.*?)(?:\(\s*(.+)\s*\))?$/ ) ) {
+
+ # Initialize types
+ my $class = "Catalyst::DispatchType::$key";
+ unless ( $initialized{$class} ) {
+ eval "require $class";
+ push( @{ $self->dispatch_types }, $class->new ) unless $@;
+ $initialized{$class}++;
+ }
+
if ( defined $value ) {
( $value =~ s/^'(.*)'$/$1/ ) || ( $value =~ s/^"(.*)"/$1/ );
}
sub setup_actions {
my ( $self, $class ) = @_;
- # These are the core structures
- $self->actions(
- {
- plain => {},
- private => {},
- regex => {},
- compiled => []
- }
- );
+ $self->dispatch_types( [] );
- $self->dispatch_types(
- [ map { "Catalyst::DispatchType::$_"->new } qw/Path Regex Default/ ] );
+ # Preload action types
+ for my $type (@PRELOAD) {
+ my $class = "Catalyst::DispatchType::$type";
+ eval "require $class";
+ Catalyst::Exception->throw( message => qq/Couldn't load "$class"/ )
+ if $@;
+ push @{ $self->dispatch_types }, $class->new;
+ }
# We use a tree
my $container =
}
for my $namespace ( keys %namespaces ) {
-
for my $sym ( values %{ $namespace . '::' } ) {
-
if ( *{$sym}{CODE} && *{$sym}{CODE} == $code ) {
-
$name = *{$sym}{NAME};
$class->set_action( $name, $code, $comp, $attrs );
last;
}
-
}
-
}
-
}
+ }
+ # Postload action types
+ for my $type (@POSTLOAD) {
+ my $class = "Catalyst::DispatchType::$type";
+ eval "require $class";
+ Catalyst::Exception->throw( message => qq/Couldn't load "$class"/ )
+ if $@;
+ push @{ $self->dispatch_types }, $class->new;
}
return unless $class->debug;
- my $actions = $self->actions;
my $privates = Text::ASCIITable->new;
$privates->setCols( 'Private', 'Class' );
$privates->setColWidth( 'Private', 36, 1 );