X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FCatalyst%2FController.pm;h=7ee1b15c416fd3ef46a464c6d38d2a704a6f8ce7;hb=75d3bb653f60b685aaf9247364f7616830746b0d;hp=5902597e231cdf1236e02ff73ea3efbf038eaf04;hpb=fb56008f2eeb293d69d5fe4c8de24ce7a9cae066;p=catagits%2FCatalyst-Runtime.git diff --git a/lib/Catalyst/Controller.pm b/lib/Catalyst/Controller.pm index 5902597..7ee1b15 100644 --- a/lib/Catalyst/Controller.pm +++ b/lib/Catalyst/Controller.pm @@ -1,12 +1,45 @@ package Catalyst::Controller; -use strict; -use base qw/Catalyst::Component Catalyst::AttrContainer Class::Accessor::Fast/; +use Moose; +# Note - Must be done at compile time due to attributes (::AttrContainer) +BEGIN { extends qw/Catalyst::Component Catalyst::AttrContainer/; } +use Class::MOP::Object (); use Catalyst::Exception; use Catalyst::Utils; -use Class::Inspector; -use NEXT; + +with 'Catalyst::Component::ApplicationAttribute'; + +has path_prefix => + ( + is => 'rw', + isa => 'Str', + init_arg => 'path', + predicate => 'has_path_prefix', + ); + +has action_namespace => + ( + is => 'rw', + isa => 'Str', + init_arg => 'namespace', + predicate => 'has_action_namespace', + ); + +has actions => + ( + is => 'rw', + isa => 'HashRef', + init_arg => undef, + ); + +sub BUILD { + my ($self, $args) = @_; + my $action = delete $args->{action} || {}; + my $actions = delete $args->{actions} || {}; + my $attr_value = $self->merge_config_hashes($actions, $action); + $self->actions($attr_value); +} =head1 NAME @@ -31,15 +64,13 @@ for more info about how Catalyst dispatches to actions. =cut +#I think both of these could be attributes. doesn't really seem like they need +#to ble class data. i think that attributes +default would work just fine __PACKAGE__->mk_classdata($_) for qw/_dispatch_steps _action_class/; __PACKAGE__->_dispatch_steps( [qw/_BEGIN _AUTO _ACTION/] ); __PACKAGE__->_action_class('Catalyst::Action'); -__PACKAGE__->mk_accessors( qw/_application/ ); - -### _app as alias -*_app = *_application; sub _DISPATCH : Private { my ( $self, $c ) = @_; @@ -88,59 +119,76 @@ sub _END : Private { return !@{ $c->error }; } -sub new { - my $self = shift; - my $app = $_[0]; - my $new = $self->NEXT::new(@_); - $new->_application( $app ); - return $new; -} - - sub action_for { my ( $self, $name ) = @_; my $app = ($self->isa('Catalyst') ? $self : $self->_application); return $app->dispatcher->get_action($name, $self->action_namespace); } -sub action_namespace { +#my opinion is that this whole sub really should be a builder method, not +#something that happens on every call. Anyone else disagree?? -- groditi +## -- apparently this is all just waiting for app/ctx split +around action_namespace => sub { + my $orig = shift; my ( $self, $c ) = @_; - unless ( $c ) { - $c = ($self->isa('Catalyst') ? $self : $self->_application); + + if( ref($self) ){ + return $self->$orig if $self->has_action_namespace; + } else { + return $self->config->{namespace} if exists $self->config->{namespace}; } - my $hash = (ref $self ? $self : $self->config); # hate app-is-class - return $hash->{namespace} if exists $hash->{namespace}; - return Catalyst::Utils::class2prefix( ref($self) || $self, - $c->config->{case_sensitive} ) - || ''; -} -sub path_prefix { - my ( $self, $c ) = @_; - unless ( $c ) { - $c = ($self->isa('Catalyst') ? $self : $self->_application); + my $case_s; + if( $c ){ + $case_s = $c->config->{case_sensitive}; + } else { + if ($self->isa('Catalyst')) { + $case_s = $self->config->{case_sensitive}; + } else { + if (ref $self) { + $case_s = $self->_application->config->{case_sensitive}; + } else { + confess("Can't figure out case_sensitive setting"); + } + } } - my $hash = (ref $self ? $self : $self->config); # hate app-is-class - return $hash->{path} if exists $hash->{path}; - return shift->action_namespace(@_); -} + + my $namespace = Catalyst::Utils::class2prefix(ref($self) || $self, $case_s) || ''; + $self->$orig($namespace) if ref($self); + return $namespace; +}; + +#Once again, this is probably better written as a builder method +around path_prefix => sub { + my $orig = shift; + my $self = shift; + if( ref($self) ){ + return $self->$orig if $self->has_path_prefix; + } else { + return $self->config->{path} if exists $self->config->{path}; + } + my $namespace = $self->action_namespace(@_); + $self->$orig($namespace) if ref($self); + return $namespace; +}; sub register_actions { my ( $self, $c ) = @_; my $class = ref $self || $self; + #this is still not correct for some reason. my $namespace = $self->action_namespace($c); - my %methods; - $methods{ $self->can($_) } = $_ - for @{ Class::Inspector->methods($class) || [] }; + my $meta = $self->Class::MOP::Object::meta(); + my %methods = map { $_->body => $_->name } + grep { $_->package_name ne 'Moose::Object' } #ignore Moose::Object methods + $meta->get_all_methods; # Advanced inheritance support for plugins and the like + #moose todo: migrate to eliminate CDI compat my @action_cache; - { - no strict 'refs'; - for my $isa ( @{"$class\::ISA"}, $class ) { - push @action_cache, @{ $isa->_action_cache } - if $isa->can('_action_cache'); + for my $isa ( $meta->superclasses, $class ) { + if(my $coderef = $isa->can('_action_cache')){ + push(@action_cache, @{ $isa->$coderef }); } } @@ -156,7 +204,7 @@ sub register_actions { if $c->debug; next; } - my $reverse = $namespace ? "$namespace/$method" : $method; + my $reverse = $namespace ? "${namespace}/${method}" : $method; my $action = $self->create_action( name => $method, code => $code, @@ -178,10 +226,7 @@ sub create_action { ? $args{attributes}{ActionClass}[0] : $self->_action_class); - unless ( Class::Inspector->loaded($class) ) { - require Class::Inspector->filename($class); - } - + Class::MOP::load_class($class); return $class->new( \%args ); } @@ -204,15 +249,24 @@ sub _parse_attrs { } } - my $hash = (ref $self ? $self : $self->config); # hate app-is-class - - if (exists $hash->{actions} || exists $hash->{action}) { - my $a = $hash->{actions} || $hash->{action}; - %raw_attributes = ((exists $a->{'*'} ? %{$a->{'*'}} : ()), - %raw_attributes, - (exists $a->{$name} ? %{$a->{$name}} : ())); + #I know that the original behavior was to ignore action if actions was set + # but i actually think this may be a little more sane? we can always remove + # the merge behavior quite easily and go back to having actions have + # presedence over action by modifying the keys. i honestly think this is + # superior while mantaining really high degree of compat + my $actions; + if( ref($self) ) { + $actions = $self->actions; + } else { + my $cfg = $self->config; + $actions = $self->merge_config_hashes($cfg->{actions}, $cfg->{action}); } + %raw_attributes = ((exists $actions->{'*'} ? %{$actions->{'*'}} : ()), + %raw_attributes, + (exists $actions->{$name} ? %{$actions->{$name}} : ())); + + my %final_attributes; foreach my $key (keys %raw_attributes) { @@ -222,8 +276,8 @@ sub _parse_attrs { foreach my $value (ref($raw) eq 'ARRAY' ? @$raw : $raw) { my $meth = "_parse_${key}_attr"; - if ( $self->can($meth) ) { - ( $key, $value ) = $self->$meth( $c, $name, $value ); + if ( my $code = $self->can($meth) ) { + ( $key, $value ) = $self->$code( $c, $name, $value ); } push( @{ $final_attributes{$key} }, $value ); } @@ -333,6 +387,10 @@ sub _parse_MyAction_attr { return ( 'ActionClass', $value ); } +no Moose; + +__PACKAGE__->meta->make_immutable; + 1; __END__